1. cv2.Canny(src, thresh1, thresh2) 進行canny邊緣檢測
參數說明: src表示輸入的圖片, thresh1表示最小閾值,thresh2表示最大閾值,用於進一步刪選邊緣信息
Canny邊緣檢測步驟:
第一步:使用高斯濾波器進行濾波,去除噪音點
第二步:使用sobel算子,計算出每個點的梯度大小和梯度方向
第三步:使用非極大值抑制(只有最大的保留),消除邊緣檢測帶來的雜散效應
第四步:應用雙閾值,來確定真實和潛在的邊緣
第五步:通過抑制弱邊緣來完成最終的邊緣檢測
第一步:高斯濾波進行濾波操作
這是3*3的歸一化后的高斯核,將當前核與圖片中的9個位置對應位置求和,表示當前位置的像素值,進行平滑處理,去除一些噪聲點的干擾
第二步:使用sobel算子,計算各個點的梯度大小和梯度方向
使用的sobel算子存在兩個方向,即x軸和y軸方向,分別計算x軸的梯度為Gx, 計算y軸的梯度為Gy
當前點的梯度大小 = sqrt(Gx ^ 2 + Gy ^ 2)
梯度的方向:Θ = arctan(Gx / Gy)
第三步:使用非極大值抑制,消除雜散效應

非極大值抑制第一種方式,如圖所示,g1表示的是坐上角一點的梯度值,g2為當前點上面一點的梯度值,斜線表示的是梯度的方向,我們需要計算出斜線與g1,g2交點的近似梯度值,使用線性差值表示:即M(dtmp1) = w*M(g2) + (1-w) * M(g1) w = distance(dtmp1, g2) / distance(g1, g2)
同理計算出M(dtmp2) 即斜線與g3,g4的交點的近似梯度值
將C點的梯度值與M(dtmp1) 和 M(dtmp2)的大小做一個比較,如果比兩者都大就保留,否者就去除

非極大值抑制第二種方式,如圖所示, 我們可以直接比較梯度方向的斜線與哪條直線比較接近,就與哪個方向上的梯度值進行比較,我們可以初步的知道角度的區間是
(30, 45, 60, 90) , 舉例說明,如果斜線靠近45度角的斜線,那么就與對角線上的兩個點的梯度做比較,如果都大於則保留,否者剔除
第四步:使用雙閾值來獲得真實邊緣和潛在的邊緣

進行進一步刪選,如果當前梯度值大於給定的maxVal,判斷為邊界, 如果當前梯度值小於minval則舍棄,如果當前梯度值在給定的最大值和最小值之間,如果其周圍的點是邊界點,那么當前點保留,否者舍棄
從上圖我們可以看出,當minval和maxval越小時,所保留的邊緣信息更多
第一步:載入lena圖片
第二步:使用兩組閾值,對結果作圖做比較
第三步:載入汽車的圖
第四步: 使用兩組閾值,對結果作圖做比較
import cv2 import numpy as np img = cv2.imread('lena.jpg') v1 = cv2.Canny(img, 80, 150) v2 = cv2.Canny(img, 50, 100) ret = np.hstack((v1, v2)) cv2.imshow('img', ret) cv2.waitKey(0) cv2.destroyAllWindows()
在最大閾值和最小閾值都偏小的情況下,我們可以看出右邊這幅圖比左邊這幅圖擁有更多的輪廓信息,同樣的也容易存在一些非邊緣點的信息
car = cv2.imread('car.png') v1 = cv2.Canny(car, 120, 250) v2 = cv2.Canny(car, 50, 100) ret = np.hstack((v1, v2)) cv2.imshow('car', ret) cv2.waitKey(0) cv2.destroyAllWindows()
右邊的圖的邊緣信息更多,左邊的圖很多房子的線條沒有了
