opencv for python的图像梯度算子以及canny边缘检测
opencv for python的圖像梯度算子以及canny邊緣檢測
- 一、圖像梯度算子:
- 二、Canny邊緣檢測(一個多級邊緣檢測算法):
一、圖像梯度算子:
1.概念簡介(部分引自百度百科):
圖像梯度:可以把圖像看成二維離散函數,圖像梯度其實就是這個二維離散函數的求導,圖像梯度可用來中值差分以及邊緣檢測。
差分函數(運算):差分的結果反映了離散量之間的一種變化,差分運算,相應于微分運算,是微積分中重要的一個概念,差分對應離散變量,微分對應連續變量。
Sobel算子:用來進行計算一階、二階或混合圖像差分。通過對圖像用相應的內核進行卷積操作來計算圖像差分;由于該算子不進行圖像尺度變換,所以和輸入圖像(數組)相比,輸出圖像(數組)的元素通常具有更大的絕對數值(即像素的位深)。為防止溢出,當輸入圖像是 8 位的,要求輸出圖像是 16 位的。所有輸入和輸出圖像都必須是單通道的,并且具有相同的圖像尺寸或者ROI尺寸。
Laplacian算子:主要用來計算圖像的二階微分算子。
2.需用函數:
cv2.Sobel(src,ddepth,dx,dy[,dst[,ksize[,scale[,delta[,borderType]]]]])→dst
5個常用參數分別代表:原圖像、圖像顏色深度即數據類型(一般用cv2.CV_64F,也可用-1使其數據類型與原圖像相同即為np.uint8)、x和y方向上的差分階數、soble核的大小(必須為1、3、5、7中的一個)
如果ksize=-1,會使用3x3的Scharr濾波器,效果要比3x3的Sobel濾波器好(而且速度相同,所以在使用3x3濾波器時應該盡量使用Scharr濾波器),當ksize=1時,采用卷積核為1X3的或3X1的。
常使用的參數組合為:
cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) 僅在x方向上求一階導數,最高可求二階
cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3) 僅在y方向上求一階導數,最高可求二階
cv2.Scharr(src,ddepth,dx,dy[,dst[,scale[,delta[,borderType]]]]])→dst
常用參數情況與cv2.Sobel類似,去除ksize參數即為默認其為-1且不可更改,其他用法和cv2.Sobel()函數完全相同,所以可用cv2.Sobel()函數在ksize=-1的情況下取代該函數
cv2.Laplacian(src,ddepth,dx,dy[,dst[,ksize[,scale[,delta[,borderType]]]]])→dst
只使用該函數求圖像的二階微分時只使用前兩個參數即可
cv2.convertScaleAbs(src[,dst[,alpha[,beta]]])→dst
x先將原圖像的全部值進行絕對值操作,然后將原圖像轉換為unsigned int8類型
3.代碼實現如下:
import cv2 import numpy as np img=cv2.imread(" /1.jpg",cv2.IMREAD_GRAYSCALE) #只能對單通道圖像進行處理,因此以灰度格式讀取該圖片,第二個參數也可為0#兩種選擇輸出圖像數組數據深度方式來生成目標圖像sobel_x=cv2.Sobel(img,cv2.CV_8U,1,0) sobel_y=cv2.Sobel(img,cv2.CV_8U,0,1) # 直接使用unsigned int8類型的圖像矩陣,這將會導致求方向導數后的某些負值或超過255的值損失 scharr_x=cv2.Sobel(img,cv2.CV_8U,1,0,ksize=-1) scharr_y=cv2.Sobel(img,cv2.CV_8U,0,1,ksize=-1) laplacian=cv2.Laplacian(img,cv2.CV_8U) #求圖像二階導數sobel_x=cv2.Sobel(img,cv2.CV_64F,1,0) sobel_y=cv2.Sobel(img,cv2.CV_64F,0,1) # 直接使用float32類型的圖像矩陣,不會使輸出圖像某些值的損失,但由于cv2.imshow()函數不支持輸出 # float32的圖像,因此需要通過cv2.convertScaleAbs()改變輸出圖像為uint8類型的 scharr_x=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=-1) scharr_y=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=-1) laplacian=cv2.Laplacian(img,cv2.CV_64F) cv2.convertScaleAbs(sobel_x) cv2.convertScaleAbs(sobel_y) cv2.convertScaleAbs(scharr_x) cv2.convertScaleAbs(scharr_x) cv2.convertScaleAbs(laplacian) #使用后者這種方法會發現比前者的線條和輪廓更加具體 #還可使用numpy模塊中的方法實現輸出圖像類型的轉變 #sobel_x=np.absolute(sobel_x),sobel_x=np.array(sobel_x,np.uint8)
二、Canny邊緣檢測(一個多級邊緣檢測算法):
1.邊緣檢測原理簡介:(大部分引自百度百科)
(1). 應用高斯濾波來平滑圖像。目的是去除噪聲,由于噪聲對邊緣檢測影響很大,因此需要先進行平滑操作去除部分噪聲
(2).尋找圖像的梯度強度。Canny算法的基本思想是尋找一幅圖像中灰度強度變化最強的位置。所謂變化最強,即指梯度方向。平滑后的圖像中每個像素點的梯度可以由Sobel算子來獲得。在變化劇烈的地方(邊界處),將獲得較大的梯度度量值G,對應的顏色為白色。然而,這些邊界通常非常粗,難以標定邊界的真正位置。為了做到這一點(需進行非極大值抑制),還必須存儲梯度方向,因此在這一步會存數兩塊數據,分別是梯度的強度信息和梯度的方向信息。
(3).進行非最大值抑制,使邊界線更細,找到邊界的真正位置即使模糊的邊界變得清晰。通俗的講,就是保留了每個像素點上梯度強度的極大值,而刪掉其他的值。對于每個像素點,進行如下操作:
a) 將其梯度方向近似為以下值中的一個(0,45,90,135,180,225,270,315)(即上下左右和45度方向)
b) 比較該像素點和其梯度方向正負方向相鄰像素點的梯度強度,如果該像素點梯度強度最大則保留,否則抑制(刪除,即置為0),邊界處的梯度方向總是指向垂直于邊界的方向,即最后會保留一條邊界處最亮的一條細線。
(4).應用雙閾值的方法來確定可能的邊界。高斯平滑后如還有少量噪聲,這些噪聲點會影響第二步和第三步的邊界確定,因此需通過該步驟更全面的確定邊界。Canny算法中應用雙閾值方法即設定一個閾值上界和閾值下界,圖像中的像素點如果大于閾值上界則認為必然是邊界(稱為強邊界),小于閾值下界則認為必然不是邊界,兩者之間的則認為是候選項(稱為弱邊界)。
(5).利用滯后技術來跟蹤邊界。和強邊界相連的弱邊界認為是邊界,其他的弱邊界則被抑制。
2.函數簡介;
OpenCV使用一個函數和多個參數來完成以上五個步驟
cv2.Canny(img,threshold1,threshold2,[,edges[,apertureSize[,L2gradient]]])→edges
參數分別代表:原圖像、下界閾值、上界閾值、卷積核尺寸大小(默認為3)、求梯度大小的方程(值為True和False,對應不同方法,默認為False),返回值為該圖像的邊界
3.代碼實現:
總結
以上是生活随笔為你收集整理的opencv for python的图像梯度算子以及canny边缘检测的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FFmpeg —— 将若干jpg图片转为
- 下一篇: linux下载nginx