opencv-學習筆記(6)圖像梯度Sobel以及canny邊緣檢測
這章講了
- sobel算子
- scharr算子
- Laplacion拉普拉斯算子
- 圖像深度問題
- Canny檢測
圖像梯度
- sobel算子和scharr算子
sobel算子是高斯平滑與微分操作的結合體,所以它的抗噪聲能力很強
我們可以設定求導的方向xorder或者yorder。也可以設置卷積核的大學
Ps當我們設置卷積核的大小為ksize=-1時候,這個函數會用
3*3的scharr算子如下
官方推薦在使用3*3濾波器時候要用scharr濾波器
Laplacion算子
拉普拉斯算子可以使用二階導數的形式定義,可假設其離散實現類型於二階Sobel導數實際上,
Opencv在計算拉普拉斯算子時直接調用Sobel算子。
計算公式如下
拉普拉斯濾波器使用的卷積核
Opencv在計算拉普拉斯算子時候是直接調用sobel算子的
import cv2 import numpy as np from matplotlib import pyplot as plt img=cv2.imread('1.jpg',0) #cv2.CV_64F 輸出圖像的深度(數據類型),可以使用-1與源圖像保持一致 np.uint8
laplacian=cv2.Laplacian(img,cv2.CV_64F) #參數1,0為只在x方向求一階導數,最大可以求2階導數,卷積核5*5 #對x濾波就顯示y波形
sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5) #參數0,1為只在y方向求一階導數,最大可以求2階導數,卷積核5*5 #對y濾波就顯示x波形
sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5) cv2.imshow('one',img) cv2.imshow('lap',laplacian) cv2.imshow('sx',sobelx) cv2.imshow('sy',sobely) cv2.waitKey(0)
圖像深度問題
看下面2個例子,
都是用5*5的卷積核,只是輸出圖像的深度不同,第四張是原圖深度
水平的導數都消失了
從第三章可以看出來,導數小於0的地方沒有消失,但是圖24消失了導數小於0的地方
Canny邊緣檢測
- 首先我們要去除噪聲5*5的高斯濾波器
- 我們計算圖像的梯度計算圖像x和y方向的一階導數,根據兩幅梯度體系找到邊界的梯度大小和方向,(梯度一般總是和邊界垂直,梯度方向被歸為四類,垂直水平和對角線)
這是計算梯度大小和方向的函數
- 非極大值抑制,去除非邊界的點,對每一個像素檢查,看這個點梯度是不是周圍具有相同梯度方向的點中最大的。
- 滯后閥值----設置兩個閥值minVal和maxVal當圖像的灰度梯度高於maxVal時候被認為是真的邊界,低於minVal就被拋棄,如果在兩者之間的話就看這個點時候和某個被確認為真正邊界的點相連,如果是就認為他也是邊界,,否則拋棄。
- 如下圖
-
圖中A高於maxVal被認為是真正的邊界帶你,C雖然低於maxVal但是高於minVAl且和A相連,所以C也是邊界點。B被拋棄
這一步中一些小的噪聲點被去除,因為我們假設邊界都是一些長的線段
在opencv里面我們用一個函數來完成上面所有步驟
cv2.Canny()
Cv2.canny(圖像對象,minVal,maxVal,用來計算梯度的Sobel卷積核大小Size=3,L2gradient)
如果L2gradient是True就會用到上面的步驟
如果L2gradient是false就會edge_graddient=|Gx^2|+|Gy^2|來代替
代碼如下,這里使用的是size=3的默認卷積核以及,L2gradient=True
import cv2 import numpy as np from matplotlib import pyplot as plt img=cv2.imread('new.jpg',1) minval=100 maxval=200 edges=cv2.Canny(img,minval,maxval,False) edges2=cv2.Canny(img,minval,maxval,True) cv2.imshow('dsd',img) cv2.imshow('s',edges) cv2.imshow('s2',edges2) k=cv2.waitKey(0) cv2.destroyAllWindows()