本篇將介紹常用基於OpenCv等視覺庫的影像分割以及圖像處理技術,並且附贈源碼
一:邊檢測器
先複習一下基礎的OpenCv操作:如上圖:第一張是原圖;
第二張是灰度圖:
gray = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)
用法很簡單,調包調參嘛,以灰度形式讀圖,介紹一下灰度轉換原理:
RGB是三通道彩色圖,在矩陣(圖像)中的順序是B,G,R;GRAY是單通道灰度圖
COLOR_BGR2GRAY的原理:
GRAY = B * 0.114 + G * 0.587 + R * 0.299
利用CV_RGB2GRAY將原圖src轉換爲灰度圖rgb2gray,轉換公式Gray = 0.1140R + 0.5870G + 0.2989*B,與CV_BGR2GRAY相比,轉換的係數一致,不同的是係數後緊跟的通道的順序變化了,由BGB變爲RGB。
利用CV_GRAY2BGR將bgr2grayImg轉換爲gray2bgrImg,轉換公式B = G = R = Gray
又或者 利用CV_GRAY2RGB將rgb2grayImg轉換爲gray2rgbImg,轉換公式R = G = B = Gray
第三、第四張是sobel算子的橫向檢測器和縱向檢測器(垂直),這個比灰度圖就是真的屬於調包了:
sobel算子技術,使用的是卷積運算。可以利用sobel算子作用於圖像梯度上
sobel算子主要用作邊緣檢測上,在技術上,他是一個離散型差分算子,用來運算圖像高亮度函數的灰度的近似值,在圖像中任意一點使用此算子,都會產生對應的灰度矢量或者法向量。
我上面圖中沒有轉化成灰度圖後使用sobel算子,現在演示一下灰度圖下的sobel算子以及不同Ksize參數下的圖案:
Sobel算子下的圖像卷積過程:(正常的卷積過程就不贅述了,建議百度百科,看不懂可以私聊我討論一下)
第五張圖是高斯模糊處理
“模糊”的算法有很多種,其中有一種叫做“高斯模糊”(Gaussian Blur)。它將正態分佈(又名”高斯分佈”)用於圖像處理。 本質上,它是一種數據平滑技術(data smoothing),適用於多個場合,圖像處理恰好提供了一個直觀的應用實例。
所謂”模糊”,可以理解成每一個像素都取周邊像素的平均值。
上圖中,2是中間點,周邊點都是1。
“中間點”取”周圍點”的平均值,就會變成1。在數值上,這是一種”平滑化”。在圖形上,就相當於產生”模糊”效果,”中間點”失去細節。
顯然,計算平均值時,取值範圍越大,”模糊效果”越強烈。
上面分別是原圖、模糊半徑3像素、模糊半徑10像素的效果。模糊半徑越大,圖像就越模糊。從數值角度看,就是數值越平滑。
接下來的問題就是,既然每個點都要取周邊像素的平均值,那麼應該如何分配權重呢?
如果使用簡單平均,顯然不是很合理,因爲圖像都是連續的,越靠近的點關係越密切,越遠離的點關係越疏遠。因此,加權平均更合理,距離越近的點權重越大,距離越遠的點權重越小。
二、正態分佈的權重
正態分佈顯然是一種可取的權重分配模式。
在圖形上,正態分佈是一種鐘形曲線,越接近中心,取值越大,越遠離中心,取值越小。
計算平均值的時候,我們只需要將”中心點”作爲原點,其他點按照其在正態曲線上的位置,分配權重,就可以得到一個加權平均值。
第六張圖是拉普拉斯算子,最後一張圖是Canny算子,原理建議百度百科,
概述一下
使用Sobel算子邊檢測器時,邊緣檢測並不那麼理想,拉普拉斯邊檢測器彌補了Sobel檢測器的不足,但是拉普拉斯便檢測器的輸出仍帶有很多的噪音,它可以檢測兩個方向上的邊,Canny邊檢測器在解決噪聲方面優於拉普拉斯邊檢測器和Sobel邊檢測器·,Canny邊檢測器是一個分階段的處理過程,他用到了遲滯性來做邊數據處理,還使用了 非極大值抑制。 這一步排除非邊緣像素, 僅僅保留了一些細線條(候選邊緣) 。
Canny邊緣檢測算子是John F.Canny於 1986 年開發出來的一個多級邊緣檢測算法。更爲重要的是 Canny 創立了邊緣檢測計算理論(Computational theory ofedge detection),解釋了這項技術是如何工作的。Canny邊緣檢測算法以Canny的名字命名,被很多人推崇爲當今最優的邊緣檢測的算法。
源碼附上:
import cv2
import PIL
img = cv2.imread('lena.jpg')
gray = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)
gray = cv2.resize(gray, (400, 430))
img = cv2.resize(img, (400, 430))
sober_horizontal = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=1)
sober_vertical = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)
laplacian = cv2.Laplacian(img, cv2.CV_64F)
canny = cv2.Canny(img, 50, 240)
img_GanssianBlur = cv2.GaussianBlur(img, (3, 3), 0)
cv2.imshow('original', img)
cv2.imshow('Gray', gray)
cv2.imshow('sobel horizontal', sober_horizontal)
cv2.imshow('sobel vertical', sober_vertical)
cv2.imshow('Laplacation', laplacian)
cv2.imshow('Canny',canny)
cv2.imshow('GaussianBlur', img_GanssianBlur)
cv2.waitKey()
二:直方圖均衡化
img = 'lena.jpg'
img = cv2.imread(img)
img = cv2.resize(img, (400, 430))
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', img_gray)
histeq = cv2.equalizeHist(img_gray)
cv2.imshow('histeq', histeq)
yuv = cv2.cvtColor(img,cv2.COLOR_BGR2YUV)
yuv[:, :, 0] = cv2.equalizeHist(yuv[:, :, 0])
img_histeq = cv2.cvtColor(yuv,cv2.COLOR_YUV2BGR)
cv2.imshow('input', img)
cv2.imshow('histeqs', img_histeq)
cv2.waitKey()
解釋一下;
圖像的空域處理是一種重要的圖像處理技術,這類方法直接以圖像的像素操作爲基礎,主要分爲灰度變換和空域濾波兩大類,直方圖均衡化(Histogram equalization)就是一種常用的灰度變換方法。
直方圖
對於灰度級(intensity levels)範圍爲[0,L−1]
[0,L−1]的數字圖像,其直方圖可以表示爲一個離散函數h(rk)=nkr**k是第k級灰度值(intensity value),nkr**k的像素個數,也就是說,。在實際應用中,通常對直方圖進行歸一化再進行後續處理,假設灰度圖像的維數是M×N,MN表示圖像的像素總數,則歸一化直方圖可以表示爲p(r**k)=n**k/M**N,k=0,1,…,L−1也就是說,p(rk)表示灰度級*r**k*。
對於灰度級(intensity levels)範圍爲[0,L−1]的數字圖像,其直方圖可以表示爲一個離散函數h(rk)=nkr**k是第k級灰度值(intensity value),nkr**k的像素個數,也就是說,。在實際應用中,通常對直方圖進行歸一化再進行後續處理,假設灰度圖像的維數是M×N,MN表示圖像的像素總數,則歸一化直方圖可以表示爲p(r**k)=n**k/M**N,k=0,1,…,L−1也就是說,*p(rk)表示灰度級*r*k*
直方圖均衡化
1. 問題描述
通常,暗圖像直方圖的分量集中在灰度較低的一端,而亮圖像直方圖分量偏向於灰度較高的一端,如下圖
從圖中可以得到這樣的結論:如果一幅圖像的灰度直方圖幾乎覆蓋了整個灰度的取值範圍,並且除了個別灰度值的個數較爲突出,整個灰度值分佈近似於均勻分佈,那麼這幅圖像就具有較大的灰度動態範圍和較高的對比度,同時圖像的細節更爲豐富。已經證明,僅僅依靠輸入圖像的直方圖信息,就可以得到一個變換函數,利用該變換函數可以將輸入圖像達到上述效果,該過程就是直方圖均衡化。
三、棱角檢測
input_file = 'box.png'
img = cv2.imread(input_file)
cv2.imshow('Input image', img)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_gray = np.float32(img_gray)
img_harris = cv2.cornerHarris(img_gray, 7, 5, 0.04)
img_harris = cv2.dilate(img_harris, None)
img[img_harris > 0.01 * img_harris.max()] = [0, 0, 0]
cv2.imshow('Harris Corners', img)
cv2.waitKey()
基於哈里斯角檢測器,基本用法就是:先加載圖片,轉換爲灰度圖,然後強制類型轉換爲浮點值,是爲了方便棱角檢測,使用cv2.dilate進行膨脹放大操作,便於進行標記棱角,然後進行閾值分割,根據閾值確定棱角判斷程度,這個跑跑代碼就明白了
Harris角點檢測器
1.對圖像進行高斯濾波。
2.對每個像素,估計其垂直方向的梯度大小值。使用近似於導數的核做兩次一維卷積即可。
3.對每一像素核給定的鄰域窗口:
- 計算局部結構矩陣A
- 計算響應函數R(A)
4.選取響應函數R(A)的一個閾值,以選擇最佳候選角點,並完成非最大化抑制。
Harris角點檢測算子是於1988年由CHris Harris & Mike Stephens提出來的。在具體展開之前,不得不提一下Moravec早在1981就提出來的Moravec角點檢測算子。
其中還有使用Forstner和Moravec角點檢測算子的,這兩個比較古老了,大家可以谷歌一下。
四:檢測SIFT特徵點
尺度不變特徵變換SIFT 是計算機視覺中最常用的特徵之一,SIFT成爲圖像識別與圖像內容分析領域最有效的特徵之一,他在大小,對比度,等方向都有較強的魯棒性,SIFT也是目標識別系統的基礎。
input_file = 'box.png'
img = cv2.imread(input_file)
cv2.imshow('Input image', img)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_gray = np.float32(img_gray)
img_harris = cv2.(img_gray, 7, 5, 0.04)
cv2.imshow('Harris Cornersess', img_harris)
img_harris = cv2.dilate(img_harris, None)
img[img_harris > 0.01 * img_harris.max()] = [0, 0, 0]
cv2.imshow('Harris Corners', img)
cv2.imshow('Harris Cornerses', img_harris)
cv2.waitKey()
上圖實現的是使用SIFT提取圖像突出的關鍵點,思想策略比較簡單,無非是跟前面的棱角檢測一樣的思想,不過SIFT不僅僅是做關鍵點的檢測的,他用的更深的是特徵的提取器!
SIFT在1999年提出,在2004年加以完善 。SIFT在數字圖像的特徵描述方面當之無愧可稱之爲最紅最火的一種,許多人對SIFT進行了改進,誕生了SIFT的一系列變種。SIFT已經申請了專利。
SIFT特徵是基於物體上的一些局部外觀的興趣點而與影像的大小和旋轉無關。對於光線、噪聲、微視角改變的容忍度也相當高。基於這些特性,它們是高度顯著而且相對容易擷取,在母數龐大的特徵數據庫中,很容易辨識物體而且鮮有誤認。使用SIFT特徵描述對於部分物體遮蔽的偵測率也相當高,甚至只需要3個以上的SIFT物體特徵就足以計算出位置與方位。在現今的電腦硬件速度下和小型的特徵數據庫條件下,辨識速度可接近即時運算。SIFT特徵的信息量大,適合在海量數據庫中快速準確匹配。
SIFT算法具有如下一些特點:
1.SIFT特徵是圖像的局部特徵,其對旋轉、尺度縮放、亮度變化保持不變性,對視角變化、仿射變換、噪聲也保持一定程度的穩定性;
-
區分性(Distinctiveness)好,信息量豐富,適用於在海量特徵數據庫中進行快速、準確的匹配;
-
多量性,即使少數的幾個物體也可以產生大量的SIFT特徵向量;
-
高速性,經優化的SIFT匹配算法甚至可以達到實時的要求;
-
可擴展性,可以很方便的與其他形式的特徵向量進行聯合。
SIFT特徵檢測主要包括以下4個基本步驟:
-
尺度空間極值檢測:
搜索所有尺度上的圖像位置。通過高斯微分函數來識別潛在的對於尺度和旋轉不變的興趣點。
-
關鍵點定位
在每個候選的位置上,通過一個擬合精細的模型來確定位置和尺度。關鍵點的選擇依據於它們的穩定程度。
- 方向確定
基於圖像局部的梯度方向,分配給每個關鍵點位置一個或多個方向。所有後面的對圖像數據的操作都相對於關鍵點的方向、尺度和位置進行變換,從而提供對於這些變換的不變性。
- 關鍵點描述
在每個關鍵點周圍的鄰域內,在選定的尺度上測量圖像局部的梯度。這些梯度被變換成一種表示,這種表示允許比較大的局部形狀的變形和光照變化。
SIFT特徵匹配主要包括2個階段:
第一階段:SIFT特徵的生成,即從多幅圖像中提取對尺度縮放、旋轉、亮度變化無關的特徵向量。
第二階段:SIFT特徵向量的匹配。
SIFT特徵的生成一般包括以下幾個步驟:
1. 構建尺度空間,檢測極值點,獲得尺度不變性。
圖1 粗檢特徵點
- 特徵點過濾並進行精確定位。
- 爲特徵點分配方向值。
- 生成特徵描述子。
以特徵點爲中心取16×16的鄰域作爲採樣窗口,將採樣點與特徵點的相對方向通過高斯加權後歸入包含8個bin的方向直方圖,最後獲得4×4×8的128維特徵描述子。示意圖如下:
當兩幅圖像的SIFT特徵向量生成以後,下一步就可以採用關鍵點特徵向量的歐式距離來作爲兩幅圖像中關鍵點的相似性判定度量。取圖1的某個關鍵點,通過遍歷找到圖像2中的距離最近的兩個關鍵點。在這兩個關鍵點中,如果最近距離除以次近距離小於某個閾值,則判定爲一對匹配點。
SIFT特徵匹配的例子:
[
SIFT算法流程圖演示:
![](https://img-blog.csdnimg.c
另外SIFT十分常用,我後續還會繼續介紹,這邊原理和拓展知識比較多,本篇可能寫不下,大家關注一下,以後繼續!
前面的代碼源碼合集:(圖片自己改就行)
import cv2
import PIL
import numpy as np
# 邊檢測器
img = cv2.imread('lena.jpg')
gray = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)
gray = cv2.resize(gray, (400, 430))
img = cv2.resize(img, (400, 430))
sober_horizontal = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=1)
sober_vertical = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)
laplacian = cv2.Laplacian(img, cv2.CV_64F)
canny = cv2.Canny(img, 50, 240)
img_GanssianBlur = cv2.GaussianBlur(img, (3, 3), 0)
# cv2.imshow('original', img)
# cv2.imshow('Gray', gray)
# cv2.imshow('sobel horizontal', sober_horizontal)
# cv2.imshow('sobel vertical', sober_vertical)
# cv2.imshow('Laplacation', laplacian)
# cv2.imshow('Canny',canny)
# cv2.imshow('GaussianBlur', img_GanssianBlur)
# cv2.waitKey()
# 直方圖均衡化
img = 'lena.jpg'
img = cv2.imread(img)
img = cv2.resize(img, (400, 430))
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# cv2.imshow('gray', img_gray)
histeq = cv2.equalizeHist(img_gray)
# cv2.imshow('histeq', histeq)
yuv = cv2.cvtColor(img,cv2.COLOR_BGR2YUV)
yuv[:, :, 0] = cv2.equalizeHist(yuv[:, :, 0])
img_histeq = cv2.cvtColor(yuv,cv2.COLOR_YUV2BGR)
# cv2.imshow('input', img)
# cv2.imshow('histeqs', img_histeq)
# cv2.waitKey()
input_file = 'box.png'
img = cv2.imread(input_file)
# cv2.imshow('Input image', img)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_gray = np.float32(img_gray)
img_harris = cv2.cornerHarris(img_gray, 7, 5, 0.04)
img_harris = cv2.dilate(img_harris, None)
img[img_harris > 0.01 * img_harris.max()] = [0, 0, 0]
# cv2.imshow('Harris Corners', img)
cv2.waitKey()
input_file = 'table.jpg'
img = cv2.imread(input_file)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
keypoints = sift.detect(img_gray, None)
img_sift = np.copy(img)
cv2.drawKeypoints(img, keypoints, img_sift, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow('Input image', img)
cv2.imshow('SIFT features', img_sift)
cv2.waitKey()
五:Star特徵檢測
上面說了SIFT,現在介紹一下Star,SIFT特徵檢測器在很多場景下都很好用,不過,在創建目標識別系統時,在用SIFT特徵檢測之前,往往需要用到一個不同的特徵檢測器,就是爲了通過靈活地堆疊不同地模塊來獲得最佳的性能,
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-JRm62UO4-1590071543607)(D:\CSDN\pic\醫學影像處理(二)\1590071005354.png)]
import cv2
class StarFeatureDetector(object):
def __init__(self):
self.detector = cv2.xfeatures2d.StarDetector_create()
def detect(self, img):
return self.detector.detect(img)
if __name__=='__main__':
input_file = 'table.jpg'
input_img = cv2.imread(input_file)
img_gray = cv2.cvtColor(input_img, cv2.COLOR_BGR2GRAY)
cv2.imshow('SAN', input_img)
keypoints = StarFeatureDetector().detect(input_img)
cv2.drawKeypoints(input_img, keypoints, input_img,
flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow('Star features', input_img)
cv2.waitKey()
Star特徵,也被稱爲中心環繞極值(或CenSurE)功能,試圖解決提供哈爾角點或FAST特徵的局部化水平的問題,同時還提供尺度不變性。
今天暫時提供這麼多吧,都是一些比較基礎的,大佬們不要噴,這是我二刷了,想着記個筆記,最近比較忙,手頭有很多事情,這篇也寫了很久,大家一起加油吧!最後的最後:深度學習交流羣,大佬交流~
上海第二工業大學 智能科學與技術大二
周小夏(CV調包俠)