目錄
一、圖像梯度計算
圖像梯度-sobal算子:
Scharr:權重變化更大(線條更加豐富,比Sobel更加細致捕捉更多梯度信息)
Laplacian算子:對噪音點敏感(可以和其他一起結合使用)
二、邊緣檢測:
Canny邊緣檢測:
?編輯
?三、圖像金字塔:
高斯金字塔:
?拉普拉斯金字塔
四、圖像輪廓:?
cv2.findContours(img, mode, method)
一、圖像梯度計算
圖像梯度-sobal算子:
為什么兩邊??2? ——因為我們關注的就是P5左右兩邊的梯度差,p6p4離得近,權重大
Gx | 右-左 |
Gy | 下-上 |
dst2 = cv2.Sobel(src,ddepth,dx,dy,ksize)
-ddepth:圖像的深度
-dx和dy:水平豎直方向
-kszie:是Sobel算子的大小
-不建議dxdy直接設置1,1;分開計算求和效果好
pie= cv2.imread('pie.png')
#結果有正負,只關系差異,正負取絕對值,現在看水平的,顯示有梯度的地方,邊界部分
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,kszie=3)
cv_show(sobelx,'sobelx')
#白->黑是正數;黑->白是負數,所有負數截斷為0,所以要取絕對值
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,kszie=3)
sobelx = cv2.convertScaleAbs(sobelx)
cv_show(sobelx,'sobelx')
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,kszie=3)
sobely = cv2.convertScaleAbs(sobely)
cv_show(sobely,'sobely')
#xy求和
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5)
cv_show(sobelxy,'sobelxy')
Scharr:權重變化更大(線條更加豐富,比Sobel更加細致捕捉更多梯度信息)
scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5)
Laplacian算子:對噪音點敏感(可以和其他一起結合使用)
laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)
二、邊緣檢測:
Canny邊緣檢測:
1)使用高斯濾波器,以平滑圖像,濾除噪聲。(中間點比較大)
2)計算圖像中每個像素點的梯度強度和方向。
3)應用非極大值抑制(NMSNon-Maximum Suppression),抑制以消除邊緣檢測帶來的雜散響應。(體現最明顯的)
A方法:c,g1,g2,g3,g4,想求兩個交點梯度,用線性插值法用權重;如果C比兩個交點梯度都大,才保留下來
B方法:
A與BC比較,A>BC,保存邊界
4)應用雙閾值(Double-Threshold)檢測來確定真實的和潛在的邊緣,只保留最真實的。
C與A邊界連接,暫且保留;B不與邊界連接,不保留
5)通過抑制孤立的弱邊緣最終完成邊緣檢測
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
#參數是minmaxvalue
v1 = cv2.Canny(img,80,150)#比較大,邊緣信息較小
v2 = cv2.Canny(img,50,100)#比較小,邊緣信息更多,有可能有噪音
res = np.hstack((v1,v2))
cv_show(res,'res')
?三、圖像金字塔:
高斯金字塔:
向下采樣(縮小)(往塔尖)
向上采樣(放大)(往塔底)
img = cv2.imread('AM.PNG')
cv_show(img,'img')
print(img.shape)
#放大
up = cv2.pyrUp(img)
cv_show(up,'up')
print(up.shape)
#變小
down = cv2.pyrDown(img)
cv_show(down,'down')
print(down.shape)
?拉普拉斯金字塔
#第一層
down = cv2.pyrDown(img)
down_up = cv2.pyrUp(down)
l=img-down_up
cv_show(l,'l')
四、圖像輪廓:?
背景:之前的邊緣可能包含一些線段,不能叫做輪廓,得是一個整體,才能是輪廓
cv2.findContours(img, mode, method)
mode
: 輪廓檢索模式
RETR_EXTERNAL:只檢測最外層的輪廓;
RETR_LIST:檢測所有輪廓,并將它們保存到同一層級中;
RETR_CCOMP:檢測所有輪廓,并將它們組織為兩層:頂層是外部邊界,第二層是空洞邊界;
RETR_TREE:檢測所有輪廓,并建立一個完整的輪廓層級結構(樹形層次)--常用
method
: 輪廓逼近方法
CHAIN_APPROX_NONE:保留所有的輪廓點(不做壓縮),輸出完整多邊形的頂點序列;
CHAIN_APPROX_SIMPLE:壓縮水平、垂直和對角線方向上的冗余點,僅保留端點;(邊緣簡單化,進行壓縮得到精簡結果)
- 為了準確性,使用二值圖像:
- 傳入二值,檢測輪廓
- 繪畫輪廓
img = cv2.imread('img.png')
gary = cv2.cvtColor(img,cv2.COLOR_BGRGRAY)
#二值處理,小的是0白,大的255黑
ret,thresh = cv2.threshhold(gray,127,255,cv2.THRESH_BINARY)
cv_show(thresh,'thresh')
#檢測函數,傳入二值圖像,檢測所有輪廓
#第一個值,二值結果
#第二個值:輪廓信息
#第三個值:層級
binary,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#繪制輪廓,需要copy,不然會覆蓋
draw_img = img.copy()
#第三個參數,輪廓畫第幾個,-1是所有
#倒數第二個參數BGR格式
#2:線條寬度
res = cv2.drawContours(draw_img,contours,-1,(0,0,255),2)
cv_show(res,'res')
輪廓特征
#需要先取出輪廓
cnt = contours[0]
#面積
cv2.contourArea(cnt)
#周長
cv2.arcLength(cnt,True)
輪廓近似:
img = cv2.imread('img.png')
gary = cv2.cvtColor(img,cv2.COLOR_BGRGRAY)
#二值處理,小的是0白,大的255黑
ret,thresh = cv2.threshhold(gray,127,255,cv2.THRESH_BINARY)
cv_show(thresh,'thresh')
binary,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = contours[0]
draw_img = img.copy()
res = cv2.drawContours(draw_img,contours,-1,(0,0,255),2)
cv_show(res,'res')
#周長*0.1,值越小和輪廓越貼合,越大遠離輪廓
epsilon = 0.1*cv2.arcLength(cnt,True)
#周長做閾值
approx = cv2.approxPolyDP(cnt,epsilon,True)
draw_img = img.copy()
res = cv2.drawContours(draw_img,contours,-1,(0,0,255),2)
cv_show(res,'res')
邊界矩形:
img = cv2.imread('img.png')
gary = cv2.cvtColor(img,cv2.COLOR_BGRGRAY)
ret,thresh = cv2.threshhold(gray,127,255,cv2.THRESH_BINARY)
cv_show(thresh,'thresh')
binary,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = contours[0]
x,y,w,h = cv2.boundingRect(cnt)
#外接矩形面積
rect_area = w*h
#輪廓與邊界矩形面積比
extent = float(area)/rect_area