智能圖像處理:Python和OpenCV實現(xiàn)-課件 第九章 邊緣檢測_第1頁
智能圖像處理:Python和OpenCV實現(xiàn)-課件 第九章 邊緣檢測_第2頁
智能圖像處理:Python和OpenCV實現(xiàn)-課件 第九章 邊緣檢測_第3頁
智能圖像處理:Python和OpenCV實現(xiàn)-課件 第九章 邊緣檢測_第4頁
智能圖像處理:Python和OpenCV實現(xiàn)-課件 第九章 邊緣檢測_第5頁
已閱讀5頁,還剩61頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第九章邊緣檢測目錄CONTENTSRoberts算子9.2Prewitt算子9.3Sobel算子9.4Laplacian算子9.5Canny算子9.6Scharr算子9.7Kirsch和Robinson算子9.8高斯拉普拉斯(LoG)算子9.9高斯差分(DoG)算子9.10Hough變換9.11圖像金字塔9.12邊緣檢測簡介9.19.1邊緣檢測

邊緣檢測算法的目的是找到一幅圖像中或場景中最相關(guān)的邊緣。這些邊緣被連接成有意義的線和邊界,從而給出分割圖像中兩個或多個區(qū)域。邊緣檢測的類型分為:一階微分算子:Roberts交叉梯度算子、Prewitt算子、Sobel算子和Scharr算子;二階微分算子:Laplacian算子、LoG算子和DoG算子;非微分邊緣檢測算子:Canny算子等。9.1邊緣檢測邊緣一般是指圖像在某一局部強度劇烈變化的區(qū)域,可被定義為兩個根據(jù)某種特征(如灰度、彩色或紋理)存在顯著特點的圖像區(qū)域之間的邊界。邊緣大致可以分為兩種:一種是階躍狀邊緣,邊緣兩邊像素的灰度值明顯不同;另一種為屋頂狀邊緣,邊緣處于灰度值由小到大再到小的變化轉(zhuǎn)折點處。邊緣檢測的目的是找到具有階躍變化或屋頂變化的像素點的集合。既然邊緣是灰度變換最劇烈的位置,最直觀的方法是對其求導(dǎo)數(shù)。邊緣檢測方法?;趯ρ亓炼绕拭娴囊浑A或二階導(dǎo)數(shù)的計算。一階導(dǎo)數(shù)具有直接正比于跨越邊緣的亮度差別的期望性質(zhì),因此,一階導(dǎo)數(shù)的幅度可用來檢測在圖像中某個點處邊緣的存在性,二階導(dǎo)數(shù)的符號可用來確定一個像素是在一個邊緣暗的一邊還是亮的一邊。階躍狀邊緣的位置在一階導(dǎo)數(shù)的峰值點,在二階導(dǎo)數(shù)的過零點;屋頂狀邊緣(有一定的寬度范圍)的位置在一階導(dǎo)數(shù)的兩峰值之間,在二階導(dǎo)數(shù)的兩個過零點之間。9.2Roberts算子Roberts梯度算子利用對角方向相鄰兩像素值之差作為衡量標(biāo)準(zhǔn),其計算公式為:

Roberts梯度算子寫成卷積運算的形式,其模板分為水平方向和垂直方向,其卷積模板-10010-1109.2Roberts算子在OpenCv中提供了cv2.filter2D()函數(shù)來實現(xiàn)其運算。函數(shù)的語法格式:

dst=cv2.filter2D(src,ddepth,kernel[,anchor[,delta[,borderType]]])其中輸入輸出參數(shù)為:dst:表示目標(biāo)函數(shù)圖像;src:表示原始圖像;ddepth:表示輸出圖像的深度;kernel:表示卷積核,一個單通道浮點型矩陣;anchor:表示內(nèi)核的基準(zhǔn)點,其默認值為(-1,-1),位于中心位置;delta:表示在目標(biāo)函數(shù)上所附加的值,默認值為0;borderType:表示邊界樣式。9.2Roberts算子例9.1使用Roberts算子檢測圖像的邊緣,觀察圖像效果。程序代碼如下。importcv2importnumpyasnpimg=cv2.imread("D:/pics/lena.jpg")

#讀取圖像#img=cv2.imread("D:/pics/lenasp.jpg")#讀取帶有椒鹽噪聲的圖像grayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#灰度化處理圖像#Roberts算子kernelx=np.array([[-1,0],[0,1]],dtype=int)kernely=np.array([[0,-1],[1,0]],dtype=int)x=cv2.filter2D(grayImage,cv2.CV_16S,kernelx)y=cv2.filter2D(grayImage,cv2.CV_16S,kernely)#轉(zhuǎn)uint8absX=cv2.convertScaleAbs(x)absY=cv2.convertScaleAbs(y)Roberts=cv2.addWeighted(absX,0.5,absY,0.5,0)#顯示圖像cv2.imshow("Original",grayImage)cv2.imshow("Roberts",Roberts)cv2.waitKey()cv2.destroyAllWindows()9.2Roberts算子(a)原始灰度圖像(b)Robert算子邊緣檢測(無噪聲)(c)帶有椒鹽噪聲的圖像(d)

Robert算子邊緣檢測(有噪聲)可以看出,該算法對噪聲較敏感,無法抑制噪聲的影響。9.3Prewitt算子Prewitt算子是一階微分算子的邊緣檢測,其結(jié)合了差分運算與鄰域平均的方法。Prewitt算子是利用特定區(qū)域內(nèi)像素灰度值產(chǎn)生的差分實現(xiàn)檢測邊緣。其原理是在圖像空間利用兩個方向模板與圖像進行鄰域卷積來完成的,這兩個方向模板一個檢測水平邊緣,一個檢測垂直邊緣。-1-1-1000111-101-101-101Prewitt水平和垂直方向卷積模板9.3Prewitt算子例9.2使用Prewitt算子檢測圖像的邊緣,觀察圖像效果。程序代碼如下:importcv2importnumpyasnp

img=cv2.imread("D:/pics/lena.jpg")#讀取圖像#img=cv2.imread("D:/pics/lenasp.jpg")#讀取帶有椒鹽噪聲的圖像grayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#轉(zhuǎn)換成灰度圖像#Prewitt算子kernelx=np.array([[1,1,1],[0,0,0],[-1,-1,-1]],dtype=int)kernely=np.array([[-1,0,1],[-1,0,1],[-1,0,1]],dtype=int)x=cv2.filter2D(grayImage,cv2.CV_16S,kernelx)y=cv2.filter2D(grayImage,cv2.CV_16S,kernely)

absX=cv2.convertScaleAbs(x)#轉(zhuǎn)uint8absY=cv2.convertScaleAbs(y)Prewitt=cv2.addWeighted(absX,0.5,absY,0.5,0)#顯示圖像cv2.imshow("original",grayImage)cv2.imshow("prewitt",Prewitt)cv2.waitKey()cv2.destroyAllWindows()9.3Prewitt算子Prewitt算子采用中心點對稱的模板來計算邊緣方向,這些模板考慮了中心點兩端數(shù)據(jù)的性質(zhì),并攜帶有關(guān)于邊緣方向的更多信息。很明顯,Prewitt算子的邊緣檢測結(jié)果在水平方向和垂直方向均比Robert算子更加明顯。(a)原始灰度圖像(b)Prewitt算子邊緣檢測(c)帶有椒鹽噪聲的圖像(d)Prewitt算子邊緣檢測(有噪聲)9.4Sobel算子Sobel算子在Prewitt算子的基礎(chǔ)上增加了權(quán)重的概念,并結(jié)合了高斯平滑和微分求導(dǎo),認為相鄰點的距離遠近對當(dāng)前像素點的影響是不同的,距離越近的像素點對應(yīng)當(dāng)前像素的影響越大,從而實現(xiàn)圖像銳化并突出邊緣輪廓。-101-202-101-1-2-1000121Sobel算子的水平和垂直方向模板9.4Sobel算子在OpenCv中提供了cv2.Sobel()函數(shù)來實現(xiàn)Sobel算子的運算,其函數(shù)語法格式為:

dst=cv2.Sobel(src,ddepth,dx,dy[,ksize[,scale[,delta[,borderType]]]])

其中前四個是必須的參數(shù),其后是可選的參數(shù)。各參數(shù)含義如下:dst:表示輸出圖像;src:表示原始圖像;ddepth:表示輸出圖像的深度。-1表示采用的是與原圖像相同的深度。目標(biāo)圖像的深度必須大于等于原圖像的深度;dx:表示x方向上求導(dǎo)的階數(shù),0表示這個方向上沒有求導(dǎo),一般為0、1、2;dy:表示y方向上求導(dǎo)的階數(shù),0表示這個方向上沒有求導(dǎo),一般為0、1、2;ksize:表示Sobel核的大小,一般為奇數(shù),例如1、3、5、7。如果ksize=-1,就演變成為3×3的Scharr算子;scale:表示計算導(dǎo)數(shù)時的縮放因子,默認為1。delta:表示在目標(biāo)函數(shù)上所附加的值,默認值為0。borderType:表示圖像邊界模式。9.4Sobel算子例9.3使用Sobel算子檢測圖像的邊緣,觀察圖像效果。程序代碼如下:importcv2

image=cv2.imread("D:/pics/lena.jpg")#image=cv2.imread("D:/pics/lenasp.jpg")#讀取帶有椒鹽噪聲的圖像image=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)#Sobel邊緣檢測sobelX=cv2.Sobel(image,cv2.CV_16S,1,0)#對x求一階導(dǎo)sobelY=cv2.Sobel(image,cv2.CV_16S,0,1)#對y求一階導(dǎo)sobelX=cv2.convertScaleAbs(sobelX)#轉(zhuǎn)換為uint8sobelY=cv2.convertScaleAbs(sobelY)#轉(zhuǎn)換為uint8#兩幅圖像疊加sobelCombined=cv2.addWeighted(sobelX,0.5,sobelY,0.5,0)#顯示圖像cv2.imshow("Original",image)cv2.imshow("SobelX",sobelX)cv2.imshow("SobelY",sobelY)cv2.imshow("SobelCombined",sobelCombined)cv2.waitKey()cv2.destroyAllWindows()9.4Sobel算子(a)原始灰度圖像(b)水平方向上的邊緣圖像

(c)垂直方向上的邊緣圖像(d)Sobel算子邊緣檢測(e)帶有椒鹽噪聲的圖像(f)Sobel算子邊緣檢測(有噪聲)9.5Laplacian算子

拉普拉斯(Laplacian)算子是一種二階導(dǎo)數(shù)算子,將在邊緣處產(chǎn)生一個陡峭的零交叉,具有各方向同性的特點,能夠?qū)θ我夥较虻倪吘夁M行提取,具有無方向性的優(yōu)點。但對噪聲比較敏感,所以很少用該算子檢測邊緣,常需要配合高斯濾波一起使用。

9.5Laplacian算子

常用的兩個卷積模板:0101-410100101-810109.5Laplacian算子在OpenCv中提供了cv2.Laplacian()函數(shù)來實現(xiàn)Sobel算子的運算。函數(shù)的語法格式為:dst=cv2.Laplacian(src,ddepth,ksize[,scale[,delta[,borderType]]])其中輸入輸出參數(shù)為:dst:表示目標(biāo)函數(shù)圖像;src:表示原始圖像;ddepth:表示輸出圖像的深度;ksize:表示二階導(dǎo)數(shù)核的大小,必須為正奇數(shù),例如1,3;scale:表示計算導(dǎo)數(shù)時的縮放因子,默認值是1;delta:表示在目標(biāo)函數(shù)上所附加的值,默認為0;borderType:表示邊界樣式。9.5Laplacian算子例9.5先用高斯濾波器平滑圖像,再用Laplacian算子檢測圖像的邊緣,觀察圖像效果。程序代碼如下:importcv2importnumpyasnp

img=cv2.imread("D:/pics/lena.jpg")#img=cv2.imread("D:/pics/lenasp.jpg")#讀取帶有椒鹽噪聲的圖像img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#將圖像轉(zhuǎn)化為灰度圖像

#高斯濾波image=cv2.GaussianBlur(img,(3,3),0)#拉普拉斯邊緣檢測laplacian=cv2.Laplacian(image,cv2.CV_16S,ksize=3)laplacian=cv2.convertScaleAbs(laplacian)#顯示圖像cv2.imshow("Original",image)cv2.imshow("Laplacian",laplacian)cv2.waitKey()cv2.destroyAllWindows()9.5Laplacian算子(a)原始圖像(b)平滑的Laplacian算子(c)帶有椒鹽噪聲的圖像(d)Laplacian算子邊緣檢測(有噪聲)Laplacian算子是二階微分線性算子,在圖像邊緣處理中,二階微分的邊緣定位能力更強,銳化效果更好,因此在進行圖像邊緣處理時,直接采用二階微分算子而不使用一階微分。9.6Canny算子1986年,JohnF.Canny提出了一個多級邊緣檢測算法,即Canny邊緣檢測算法。雖然其算法復(fù)雜,但Canny檢測器是迄今為止討論過的邊緣檢測器中最優(yōu)秀的。Canny方法不容易受噪聲干擾,能夠檢測到真正的弱邊緣。優(yōu)點在于,使用兩種不同的閾值分別檢測強邊緣和弱邊緣,并且當(dāng)弱邊緣和強邊緣相連時,才將弱邊緣包含在輸出圖像中。9.6Canny算子Canny算子的檢測圖像邊緣的步驟如下:

9.6Canny算子在OpenCv中提供了cv2.Canny()函數(shù)來實現(xiàn)Canny算子的運算,函數(shù)的語法格式為:dst=cv2.Canny(src,threshold1,threshold2[,apertureSize[,L2gradient]])其中輸入輸出參數(shù)為:dst:表示輸出邊緣圖像,單通道8位圖像;src:表示原始圖像,即需要處理的圖像;threshold1:表示設(shè)置的低閾值;threshold1:表示設(shè)置的高閾值,一般設(shè)定為低閾值的3倍;apertureSize:表示Sobel算子的大小,默認為3;L2gradient:參數(shù)表示一個布爾值,如果為真,則使用更精確的L2范數(shù)進行計算(即兩個方向的倒數(shù)的平方和再開方),否則使用L1范數(shù)(直接將兩個方向?qū)?shù)的絕對值相加),默認是false。9.6Canny算子例9.6使用Canny算子檢測圖像的邊緣,觀察圖像效果。程序代碼如下:importcv2

img=cv2.imread("D:/pics/lena.jpg")#img=cv2.imread("D:/pics/lenasp.jpg")#讀取帶有椒鹽噪聲的圖像img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#轉(zhuǎn)化為灰度圖像img_gaus=cv2.GaussianBlur(img_gray,(3,3),0)

#高斯濾波

#Canny邊緣檢測,設(shè)置兩個閾值分別為100和200edge_output=cv2.Canny(img_gaus,100,200)dst=cv2.bitwise_and(img,img,mask=edge_output)

cv2.imshow("Original",img)cv2.imshow("canny",edge_output)cv2.imshow("ColorEdge",dst)cv2.waitKey()cv2.destroyAllWindows()9.6Canny算子

(a)原始圖像(b)Canny算子邊緣檢測(c)彩色邊緣圖像(d)帶有椒鹽噪聲的圖像(e)Canny算子邊緣檢測(有噪聲)(f)帶噪聲的彩色邊緣圖像9.6Canny算子例9.7使用Canny算子檢測圖像的邊緣,利用滑動條調(diào)節(jié)閾值大小,觀察圖像效果。程序代碼如下:importcv2importnumpyasnp

img=cv2.imread('d:/pics/lena.jpg',0)#讀取帶有椒鹽噪聲的圖像#img=cv2.imread("d:/pics/lenasp.jpg",0)img=cv2.GaussianBlur(img,(3,3),0)#高斯濾波去噪

defnothing(x):pass

#創(chuàng)建滑動窗口和滑動條dWindow('Canny',1)cv2.createTrackbar('minval','Canny',0,255,nothing)cv2.createTrackbar('maxval','Canny',0,255,nothing)

whileTrue:#讀取滑動條數(shù)值minval=cv2.getTrackbarPos('minval','Canny')maxval=cv2.getTrackbarPos('maxval','Canny')edges=cv2.Canny(img,minval,maxval)

#拼接原圖與邊緣監(jiān)測結(jié)果圖img_2=np.hstack((img,edges))cv2.imshow('Canny',img_2)

key=cv2.waitKey(1)ifkey==27:#按下Esc鍵,退出breakcv2.destroyAllWindows()9.6Canny算子

(a)Canny算子邊緣檢測(無噪聲)(b)Canny算子邊緣檢測(有噪聲)9.7Scharr算子

9.7Scharr算子OpenCV提供了圖像提取邊緣的Scahrr()函數(shù),該函數(shù)的語法格式為:dst=cv2.Scharr(src,ddepth,dx,dy[,scale[,delta[,borderType]]])其中輸入輸出參數(shù)如下:src:待提取邊緣的圖像;dst:輸出圖像,與輸入圖像src具有相同的尺寸和通道數(shù),數(shù)據(jù)類型由第三個參數(shù)ddepth控制;ddepth:輸出圖像的數(shù)據(jù)類型(深度),根據(jù)輸入圖像的數(shù)據(jù)類型不同擁有不同的取值范圍,當(dāng)賦值為-1時,輸出圖像的數(shù)據(jù)類型自動選擇;dx:X方向的差分階數(shù);dy:Y方向的差分階數(shù);scale:對導(dǎo)數(shù)計算結(jié)果進行縮放的縮放因子,默認系數(shù)為1,不進行縮放;delta:偏值,在計算結(jié)果中加上偏值;borderType:像素外推法選擇標(biāo)志,默認參數(shù)為BORDER_DEFAULT,表示不包含邊界值倒序填充。9.7Scharr算子例9.8使用Scharr算子檢測圖像的邊緣,程序代碼如下:importcv2img=cv2.imread('d:/pics/lena.jpg',0)

x=cv2.Scharr(img,cv2.CV_16S,1,0)#Scharr算子X方向y=cv2.Scharr(img,cv2.CV_16S,0,1)#Scharr算子Y方向absX=cv2.convertScaleAbs(x)absY=cv2.convertScaleAbs(y)scharr=cv2.addWeighted(absX,0.5,absY,0.5,0)

cv2.imshow('originimage',img)cv2.imshow('X_Scharr',absX)cv2.imshow('Y_Scharr',absY)cv2.imshow('Scharrresult',scharr)cv2.waitKey(0)cv2.destroyAllWindows()9.7Scharr算子

(a)原始圖像(b)X方向的Scharr圖像邊緣(c)Y方向的Scharr圖像邊緣(d)Scharr算子邊緣檢測圖像9.8Kirsch和Robinson算子

9.8Kirsch和Robinson算子

9.8Kirsch和Robinson算子例9.9使用Kirsch算子檢測圖像的邊緣,程序代碼如下:importcv2importnumpyasnpdefKirsch(gray):#定義Kirsch卷積模板m1=np.array([[5,5,5],[-3,0,-3],[-3,-3,-3]])m2=np.array([[-3,5,5],[-3,0,5],[-3,-3,-3]])m3=np.array([[-3,-3,5],[-3,0,5],[-3,-3,5]])m4=np.array([[-3,-3,-3],[-3,0,5],[-3,5,5]])m5=np.array([[-3,-3,-3],[-3,0,-3],[5,5,5]])m6=np.array([[-3,-3,-3],[5,0,-3],[5,5,-3]])m7=np.array([[5,-3,-3],[5,0,-3],[5,-3,-3]])m8=np.array([[5,5,-3],[5,0,-3],[-3,-3,-3]])graym=cv2.copyMakeBorder(gray,1,1,1,1,borderType=cv2.BORDER_REPLICATE)temp=list(range(8))gray1=np.zeros(graym.shape)foriinrange(1,gray.shape[0]-1):forjinrange(1,gray.shape[1]-1):temp[0]=np.abs((np.dot(np.array([1,1,1]),(m1*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[1]=np.abs((np.dot(np.array([1,1,1]),(m2*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[2]=np.abs((np.dot(np.array([1,1,1]),(m3*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[3]=np.abs((np.dot(np.array([1,1,1]),(m4*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[4]=np.abs((np.dot(np.array([1,1,1]),(m5*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[5]=np.abs((np.dot(np.array([1,1,1]),(m6*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[6]=np.abs((np.dot(np.array([1,1,1]),(m7*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[7]=np.abs((np.dot(np.array([1,1,1]),(m8*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))

gray1[i,j]=np.max(temp)ifgray1[i,j]>255:gray1[i,j]=255else:gray1[i,j]=0gray2=cv2.resize(gray1,(gray.shape[0],gray.shape[1]))Kirsch=gray2returnKirsch

9.8Kirsch和Robinson算子img=cv2.imread('d:/pics/lena.jpg',0)result=Kirsch(img)cv2.imshow('Originimage',img)cv2.imshow('Kirschresult',result)cv2.waitKey(0)cv2.destroyAllWindows()a)原始圖像b)Kirsch算子圖像9.8Kirsch和Robinson算子例9.10使用Robinson算子檢測圖像的邊緣,程序代碼如下:importcv2importnumpyasnp

defRobinson(gray):#定義Robinson卷積模板m1=np.array([[1,2,1],[0,0,0],[-1,-2,-1]])m2=np.array([[0,1,2],[-1,0,1],[-2,-1,0]])m3=np.array([[-1,0,1],[-2,0,2],[-1,0,1]])m4=np.array([[-2,-1,0],[-1,0,1],[0,1,2]])m5=np.array([[-1,-2,-1],[0,0,0],[1,2,1]])m6=np.array([[0,-1,-2],[1,0,-1],[2,1,0]])m7=np.array([[1,0,-1],[2,0,-2],[1,0,-1]])m8=np.array([[2,1,0],[1,0,-1],[0,-1,2]])graym=cv2.copyMakeBorder(gray,1,1,1,1,borderType=cv2.BORDER_REPLICATE)temp=list(range(8))gray1=np.zeros(graym.shape)foriinrange(1,gray.shape[0]-1):forjinrange(1,gray.shape[1]-1):temp[0]=np.abs((np.dot(np.array([1,1,1]),(m1*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[1]=np.abs((np.dot(np.array([1,1,1]),(m2*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[2]=np.abs((np.dot(np.array([1,1,1]),(m3*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[3]=np.abs((np.dot(np.array([1,1,1]),(m4*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[4]=np.abs((np.dot(np.array([1,1,1]),(m5*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[5]=np.abs((np.dot(np.array([1,1,1]),(m6*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[6]=np.abs((np.dot(np.array([1,1,1]),(m7*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))temp[7]=np.abs((np.dot(np.array([1,1,1]),(m8*gray[i-1:i+2,j-1:j+2]))).dot(np.array([[1],[1],[1]])))

gray1[i,j]=np.max(temp)ifgray1[i,j]>255:gray1[i,j]=255else:gray1[i,j]=0

gray2=cv2.resize(gray1,(gray.shape[0],gray.shape[1]))Kirsch=gray2returnKirsch9.8Kirsch和Robinson算子img=cv2.imread('d:/pics/lena.jpg',0)result=Robinson(img)cv2.imshow('Originimage',img)cv2.imshow('Robinsonresult',result)cv2.waitKey(0)cv2.destroyAllWindows()(a)原始圖像(b)

Robinson算子圖像邊緣9.9高斯拉普拉斯(LoG)算子高斯拉普拉斯LoG(Laplacian-of-Gaussian)邊緣檢測算子是DavidCourtnayMarr和EllenHildreth(1980)共同提出的。因此,稱為邊緣檢測算法或Marr&Hildreth算子。該算法首先對圖像做高斯濾波,然后再求其拉普拉斯(Laplacian)二階導(dǎo)數(shù),根據(jù)二階導(dǎo)數(shù)的過零點來檢測圖像的邊界,即通過檢測濾波結(jié)果的零交叉(Zerocrossings)來獲得圖像的邊緣。

LoG算子常用的卷積模板有3×3或5×5的模板1000-1-2-10-1-216-2-10-1-2-1000-1009.9高斯拉普拉斯(LoG)算子例9.11使用LoG算子檢測圖像的邊緣,程序代碼如下:importcv2#LoG算子deflog(gray):#先通過高斯濾波降噪gaussian=cv2.GaussianBlur(gray,(3,3),0)#再通過拉普拉斯算子做邊緣檢測dst=cv2.Laplacian(gaussian,cv2.CV_16S,ksize=3)log=cv2.convertScaleAbs(dst)#原圖像轉(zhuǎn)換為uint8類型returnlog

#img=cv2.imread('d:/pics/lena.jpg',0)img=cv2.imread("D:/pics/lenasp.png",0)#讀取帶有椒鹽噪聲的圖像result=log(img)cv2.imshow('Originimage',img)cv2.imshow('LoGresult',result)cv2.waitKey(0)cv2.destroyAllWindows()9.9高斯拉普拉斯(LoG)算子(a)原圖像

(b)LoG算子邊緣檢測(c)帶有椒鹽噪聲的圖像(d)LoG算子邊緣檢測(有噪聲)9.10高斯差分(DoG)算子

9.9高斯差分(DoG)算子例9.12使用DoG算子檢測圖像的邊緣,程序代碼如下:importcv2importnumpyasnpfromscipyimportsignal

#二維高斯卷積核,進行卷積defgaussConv2(image,size,sigma):H,W=sizer,c=np.mgrid[0:H:1.0,0:W:1.0]c-=(W-1.0)/2.0r-=(H-1.0)/2.0sigma2=np.power(sigma,2.0)norm2=np.power(r,2.0)+np.power(c,2.0)LoGKernel=(1/(2*np.pi*sigma2))*np.exp(-norm2/(2*sigma2))image_conv=signal.convolve2d(image,LoGKernel,'same','symm')returnimage_conv

defDoG(image,size,sigma,k=1.1):Is=gaussConv2(image,size,sigma)Isk=gaussConv2(image,size,sigma*k)DoG=Isk-IsDoG/=(np.power(sigma,2.0)*(k-1))returnDoGif__name__=="__main__":img=cv2.imread("d:/pics/lena.jpg",0)sigma=1k=1.1size=(7,7)DoG_edge=DoG(img,size,sigma,k)DoG_edge[DoG_edge>255]=255DoG_edge[DoG_edge<0]=0DoG_edge=DoG_edge/np.max(DoG_edge)DoG_edge=DoG_edge*255DoG_edge=DoG_edge.astype(np.uint8)

cv2.imshow(“original",img)cv2.imshow("DoG_edge",DoG_edge)cv2.waitKey(0)cv2.destroyAllWindows()9.10高斯差分(DoG)算子(a)原圖像

(b)DoG算子邊緣檢測9.11霍夫(Hough)變換)在數(shù)字圖像中,往往存在著一些特殊形狀的幾何圖形,像檢測路邊一條直線,檢測人眼的圓形等等,有時我們需要把這些特定圖形檢測出來,Hough變換就是這樣一種檢測的工具。Hough變換的基本原理在于利用點與線的對偶性,將原始圖像空間給定的曲線通過曲線表達形式變?yōu)閰?shù)空間的一個點。這樣就把原始圖像中給定曲線的檢測問題轉(zhuǎn)化為尋找參數(shù)空間中的峰值問題,也即把檢測整體特性轉(zhuǎn)化為檢測局部特性。9.11Hough變換

9.11.1Hough變換檢測直線:OpenCV提供了兩種用于直線檢測的Hough變換形式。一個是cv2.HoughLines()函數(shù),在二值圖像中查找直線;第二個是cv2.HoughLinesP()函數(shù),查找直線段。函數(shù)cv2.HoughLines的語法格式為:lines=cv2.HoughLines(img,rho,theta,threshold)其中輸入輸出參數(shù)如下:img:是輸入二值圖像,在進行霍夫變換之前需要通過閾值方法的邊緣檢測進行圖像的二值化;rho和theta:分別是r、θ對應(yīng)的精度;threshold:是閾值,一條直線所需最少的曲線交點,因此這個閾值代表了檢測到的直線最短長度。lines:輸出,儲存檢測到的直線參數(shù)(r,theta)。9.11Hough變換例9.13使用Hough變換檢測圖像中的直線,程序代碼如下:importcv2importnumpyasnporiginal_img=cv2.imread("d:/pics/road.jpg")img=cv2.resize(original_img,None,fx=0.8,fy=0.8,interpolation=cv2.INTER_CUBIC)img=cv2.GaussianBlur(img,(3,3),0)edges=cv2.Canny(img,50,150,apertureSize=3)lines=cv2.HoughLines(edges,1,np.pi/180,150)#最后一個參數(shù)使用了經(jīng)驗型的值print("LineNum:",len(lines))

result=img.copy()forlineinlines: rho=line[0][0]#第一個元素是距離rho theta=line[0][1]#第二個元素是角度theta if(theta<(np.pi/4.))or(theta>(3.*np.pi/4.0)):#垂直直線 pt1=(int(rho/np.cos(theta)),0)#該直線與第一行的交點 #該直線與最后一行的焦點 pt2=(int((rho-result.shape[0]*np.sin(theta))/np.cos(theta)),result.shape[0]) cv2.line(result,pt1,pt2,(0,255,0))#繪制一條綠色線 else:#水平直線 pt1=(0,int(rho/np.sin(theta)))#該直線與第一列的交點 #該直線與最后一列的交點 pt2=(result.shape[1],int((rho-result.shape[1]*np.cos(theta))/np.sin(theta))) cv2.line(result,pt1,pt2,(0,0,255),1)#繪制一條紅色直線9.11Hough變換(a)原圖像

(b)Hough變換檢測出的直線cv2.imshow('Origin',img)cv2.imshow('Canny',edges)cv2.imshow('Result',result)cv2.waitKey(0)cv2.destroyAllWindows()在該例中,首先使用Canny算子獲得圖像邊緣,然后使用Hough變換檢測直線。其中HoughLines函數(shù)的參數(shù)2和3對應(yīng)直線搜索的步長,函數(shù)將通過步長為1的半徑和步長為π/180的角來搜索所有可能的直線。最后一個參數(shù)是經(jīng)過某一點曲線數(shù)量的閾值,超過這個閾值,就表示這個交點所代表的參數(shù)對(rho,theta)在原圖像中為一條直線,這個參數(shù)使用了經(jīng)驗值。9.11Hough變換在OpenCV中用函數(shù)cv2.HoughLinesP()實現(xiàn),其語法格式為:lines=cv2.HoughLinesP(image,rho,theta,threshold[,minLineLength[,maxLineGap]]])其中輸入輸出參數(shù)如下:image:必須是二值圖像,推薦使用canny邊緣檢測的結(jié)果圖像;rho:線段以像素為單位的距離精度,double類型的,推薦用1.0;theta:線段以弧度為單位的角度精度,推薦用numpy.pi/180;threshod:累加平面的閾值參數(shù),int類型,超過設(shè)定閾值才被檢測出線段,值越大,基本上意味著檢出的線段越長,檢出的線段個數(shù)越少;minLineLength:線段以像素為單位的最小長度,根據(jù)應(yīng)用場景設(shè)置;maxLineGap:同一方向上兩條線段判定為一條線段的最大允許間隔(斷裂),超過了設(shè)定值,則把兩條線段當(dāng)成一條線段,值越大,允許線段上的斷裂越大,越有可能檢出潛在的直線段;lines:輸出,儲存檢測到的直線參數(shù)(r,theta)。9.11Hough變換例9.14使用Hough變換檢測圖像中的線段,程序代碼如下:importcv2importnumpyasnp

img=cv2.imread("d:/pics/road.jpg")img=cv2.GaussianBlur(img,(3,3),0)edges=cv2.Canny(img,50,150,apertureSize=3)

#Hough變換

minLineLength=500maxLineGap=40lines=cv2.HoughLinesP(edges,1,np.pi/180,80,minLineLength,maxLineGap)print("LineNum:",len(lines))

#畫出檢測的線段forlineinlines:forx1,y1,x2,y2inline:cv2.line(img,(x1,y1),(x2,y2),(0,0,255),1)

cv2.imshow('Result',img)cv2.waitKey(0)cv2.destroyAllWindows()

9.11Hough變換函數(shù)cv2.HoughLinesP()是一種概率直線檢測,從原理上講hough變換是一個耗時耗力的算法,尤其是每一個點計算,即使經(jīng)過了Canny轉(zhuǎn)換有的時候點的個數(shù)依然是龐大的,這個時候我們采取一種概率挑選機制,不是所有的點都計算,而是隨機的選取一些點來計算,相當(dāng)于降采樣了,這樣的話我們的閾值設(shè)置上也要降低一些。在參數(shù)輸入輸出上,輸入多了兩個參數(shù):minLineLengh和MaxLineCap。輸出上也變了,不再是直線參數(shù)的,而直接就是直線點的坐標(biāo)位置,這樣可以省去一系列for循環(huán)中的由參數(shù)空間到圖像的實際坐標(biāo)點的轉(zhuǎn)換。

9.11Hough變換

9.11.2Hough變換檢測圓:一個圓環(huán)需要3個參數(shù)(中心坐標(biāo)點x、y,圓半徑)來確定,所以進行圓環(huán)檢測的累加器必須是三維的,這樣效率就會很低。OpenCV使用了霍夫變換梯度法來檢測邊界的梯度信息,從而提升了計算的效率。OpenCV中進行Hough變換檢測圓環(huán)的函數(shù)是cv2.HoughCircles(),其語法格式為:circles=cv2.HoughCircles(image,method,dp,minDist,param1,param2,minRadius,maxRadius)其中輸入輸出參數(shù)如下:image:8位單通道圖像。如果使用彩色圖像,需要先轉(zhuǎn)換為灰度圖像;method:定義檢測圖像中圓的方法。目前唯一實現(xiàn)的方法是cv2.HOUGH_GRADIENT;dp:累加器分辨率與圖像分辨率的反比。dp獲取越大,累加器數(shù)組越??;minDist:檢測點到圓的中心(x,y)坐標(biāo)之間的最小距離。如果minDist太小,則可能導(dǎo)致檢測到多個相鄰的圓。如果minDist太大,則可能導(dǎo)致很多圓檢測不到;param1:用于處理邊緣檢測的梯度值方法;param2:cv2.HOUGH_GRADIENT方法的累加器閾值。閾值越小,檢測到的圈子越多;minRadius:半徑的最小尺寸(以像素為單位);maxRadius:半徑的最大尺寸(以像素為單位),要根據(jù)檢測圓的大小調(diào)整半徑尺寸;circles:輸出。9.11Hough變換例9.15利用Hough變換檢測圖像中的圓環(huán)。程序代碼如下::importcv2importnumpyasnp

img=cv2.imread('d:/pics/yinyuan.png')gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)cv2.imshow('origin_img',gray)

#hough變換circles1=cv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,1,100,param1=100,param2=30,minRadius=180,maxRadius=200)circles=circles1[0,:,:]#提取為二維circles=np.uint16(np.around(circles))#四舍五入,取整foriincircles[:]:cv2.circle(img,(i[0],i[1]),i[2],(255,0,0),5)#畫圓圈cv2.circle(img,(i[0],i[1]),2,(255,0,255),10)#畫圓心

cv2.imshow('result',img)cv2.waitKey(0)cv2.destroyAllWindows()

9.10Hough變換(a)原圖像(b)Hough變換檢測出的圓環(huán)9.11Hough變換例9.16利用hough變換,檢測棋盤上的圍棋,并識別圍棋顏色。程序代碼如下:importcv2importnumpyasnpfromcollectionsimportCounter

#檢測棋子的顏色defdetect_weiqi(img):txt='black'gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)ret,threshold=cv2.threshold(gray,100,255,cv2.THRESH_BINARY)c=Counter(list(threshold.flatten()))print(c.most_common())ifc.most_common()[0][0]!=0:txt='white'returntxt,thresholdimg=cv2.imread('d:/pics/weiqi3.png')img=cv2.medianBlur(img,3)gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)cv2.imshow('Origin',img)circles=cv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,1,20,param1=100,param2=30,minRadius=10,maxRadius=50)

ifcirclesisNone:exit(-1)circles=np.uint16(np.around(circles))print(circles)

cv2.waitKey(0)9.11Hough變換font=cv2.FONT_HERSHEY_SIMPLEXforiincircles[0,:]:cv2.circle(img,(i[0],i[1]),i[2],(0,255,0),2)cv2.circle(img,(i[0],i[1]),2,(0,0,255),3)

x,y,r=icrop_img=img[y-r:y+r,x-r:x+r]#檢測圍棋棋子txt,threshold=detect_weiqi(crop_img)print('顏色','黑色'iftxt=='black'else'白色')

cv2.putText(threshold,text=txt,org=(0,0),fontFace=font,fontScale=0.5,color=(0,255,0),thickness=2)cv2.imshow('threshold',threshold)

cv2.imshow('crop_img',crop_img)cv2.moveWindow('crop_img',x=0,y=img.shape[0])

cv2.imshow('detectedchess',img)cv2.moveWindow('detectedchess',y=0,x=img.shape[1])

cv2.waitKey(500)

cv2.waitKey(0)cv2.destroyAllWindows()

(a)圍棋原圖像(b)檢測出圓環(huán)的圍棋棋子9.12圖像金字塔圖像金字塔是圖像多尺度表達的一種,是一種以多分辨率來解釋圖像的有效但概念簡單的結(jié)構(gòu)。一幅圖像的金字塔是一系列以金字塔形狀排列的分辨率逐步降低,且來源于同一張原始圖的圖像集合。其通過梯次下采樣獲得,直到達到某個終止條件才停止采樣。一個圖像金字塔就是一系列以金字塔形狀排列的、分辨率逐步降低的圖像集合,層級越高,則圖像越小,分辨率越低。圖像金字塔方法的總體思想主要是:將參加融合的每幅圖像分解為多尺度的金字塔圖像序列,將低分辨率的圖像在上層,高分辨率的圖像在下層,上層圖像的大小為前一層圖像大小的1/4。層數(shù)為0、1、2、……N。將所有圖像的金字塔在相應(yīng)層上以一定的規(guī)則融合,就可得到合成金字塔,再將該合成金字塔按照金字塔生成的逆過程進行重構(gòu),得到融合金字塔。9.11圖像金字塔圖像金字塔一般有高斯金字塔(Gaussianpyramid)和拉普拉斯金字塔(Laplacianpyramid)。9.12.1高斯金字塔高斯金字塔是由底部的最大分辨率圖像逐次下采樣得到的一系列圖像。最下面的圖像分辨率最高,越往上圖像分辨率越低。OpenCV對圖像向下采樣pyrDown函數(shù),其語法格式為:

dst=pyrDown(src,dstsize=None,borderType=None)其中輸入輸出參數(shù)為:src:表示輸入圖像;dst:表示輸出圖像,它與src類型、大小相同;dstsize:表示降采樣之后的目標(biāo)圖像的大?。籦orderType:表示表示圖像邊界的處理方式。9.12圖像金字塔例9.17利用高斯金字塔函數(shù),將圖像下采樣,程序代碼如下:importcv2

#高斯金字塔defpyramid_demo(image):level=3temp=image.copy()pyramids_images=[]#空列表foriinrange(level):dst=cv2.pyrDown(temp)#先對圖像進行高斯平滑,然后再進行下采樣pyramids_images.append(dst)#在列表末尾添加新的對象cv2.imshow("pyramid_down_"+str(i),dst)temp=dst.copy()returnpyramids_images

if__name__=="__main__":img=cv2.imread("d:/pics/lena.jpg")dWindow("inputimage",cv2.WINDOW_AUTOSIZE)cv2.imshow("inputimage",img)pyramid_demo(img)cv2.waitKey(0)cv2.destroyAllWindows()

9.12圖像金字塔

(a)第0層圖像(b)第1層圖像(c)第2層圖像(d)第

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論