OpenCV-Python教程(6)(7)(8): Sobel運算元 Laplacian運算元 Canny邊緣檢測

garfielder007發表於2016-05-05

OpenCV-Python教程(6、Sobel運算元)

本篇文章介紹如何用OpenCV-Python來使用Sobel運算元。

提示:

  • 轉載請詳細註明原作者及出處,謝謝!
  • 本文介紹使用OpenCV-Python實現基本的濾波處理
  • 本文不介詳細的理論知識,讀者可從其他資料中獲取相應的背景知識。筆者推薦清華大學出版社的《影象處理與計算機視覺演算法及應用(第2版) 》。

Sobel運算元

原型

Sobel運算元依然是一種過濾器,只是其是帶有方向的。在OpenCV-Python中,使用Sobel的運算元的函式原型如下:

[python] view plain copy
  1. dst = cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])  
函式返回其處理結果。

前四個是必須的引數:

  • 第一個引數是需要處理的影象;
  • 第二個引數是影象的深度,-1表示採用的是與原影象相同的深度。目標影象的深度必須大於等於原影象的深度;
  • dx和dy表示的是求導的階數,0表示這個方向上沒有求導,一般為0、1、2。

其後是可選的引數:

  • dst不用解釋了;
  • ksize是Sobel運算元的大小,必須為1、3、5、7。
  • scale是縮放導數的比例常數,預設情況下沒有伸縮係數;
  • delta是一個可選的增量,將會加到最終的dst中,同樣,預設情況下沒有額外的值加到dst中;
  • borderType是判斷影象邊界的模式。這個引數預設值為cv2.BORDER_DEFAULT

使用

在OpenCV-Python中,Sobel函式的使用如下:

[python] view plain copy
  1. #coding=utf-8  
  2. import cv2  
  3. import numpy as np    
  4.   
  5. img = cv2.imread("D:/lion.jpg"0)  
  6.   
  7. x = cv2.Sobel(img,cv2.CV_16S,1,0)  
  8. y = cv2.Sobel(img,cv2.CV_16S,0,1)  
  9.   
  10. absX = cv2.convertScaleAbs(x)   # 轉回uint8  
  11. absY = cv2.convertScaleAbs(y)  
  12.   
  13. dst = cv2.addWeighted(absX,0.5,absY,0.5,0)  
  14.   
  15. cv2.imshow("absX", absX)  
  16. cv2.imshow("absY", absY)  
  17.   
  18. cv2.imshow("Result", dst)  
  19.   
  20. cv2.waitKey(0)  
  21. cv2.destroyAllWindows()   

解釋

在Sobel函式的第二個引數這裡使用了cv2.CV_16S。因為OpenCV文件中對Sobel運算元的介紹中有這麼一句:“in the case of 8-bit input images it will result in truncated derivatives”。即Sobel函式求完導數後會有負值,還有會大於255的值。而原影象是uint8,即8位無符號數,所以Sobel建立的影象位數不夠,會有截斷。因此要使用16位有符號的資料型別,即cv2.CV_16S。

在經過處理後,別忘了用convertScaleAbs()函式將其轉回原來的uint8形式。否則將無法顯示影象,而只是一副灰色的視窗。convertScaleAbs()的原型為:

[python] view plain copy
  1. dst = cv2.convertScaleAbs(src[, dst[, alpha[, beta]]])  
其中可選引數alpha是伸縮係數,beta是加到結果上的一個值。結果返回uint8型別的圖片。

由於Sobel運算元是在兩個方向計算的,最後還需要用cv2.addWeighted(...)函式將其組合起來。其函式原型為:

[python] view plain copy
  1. dst = cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])  
其中alpha是第一幅圖片中元素的權重,beta是第二個的權重,gamma是加到最後結果上的一個值。

結果

原影象為:

結果為:


參考資料:

1、《Opencv2 Computer Vision Application Programming Cookbook》

2、《OpenCV References Manule》




OpenCV-Python教程(7、Laplacian運算元)

本篇文章介紹如何用OpenCV-Python來使用Laplacian運算元。

提示:

  • 轉載請詳細註明原作者及出處,謝謝!
  • 本文介紹使用在OpenCV-Python中使用Laplacian函式
  • 本文不介詳細的理論知識,讀者可從其他資料中獲取相應的背景知識。筆者推薦清華大學出版社的《影象處理與計算機視覺演算法及應用(第2版) 》。

Laplacian運算元

影象中的邊緣區域,畫素值會發生“跳躍”,對這些畫素求導,在其一階導數在邊緣位置為極值,這就是Sobel運算元使用的原理——極值處就是邊緣。如下圖(下圖來自OpenCV官方文件):


如果對畫素值求二階導數,會發現邊緣處的導數值為0。如下(下圖來自OpenCV官方文件):


Laplace函式實現的方法是先用Sobel 運算元計算二階x和y導數,再求和:(CSDN,你打水印,讓我的公式怎麼辦?)

函式原型

在OpenCV-Python中,Laplace運算元的函式原型如下:

[python] view plain copy
  1. dst = cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])  
如果看了上一篇Sobel運算元的介紹,這裡的引數應該不難理解。

前兩個是必須的引數:

  • 第一個引數是需要處理的影象;
  • 第二個引數是影象的深度,-1表示採用的是與原影象相同的深度。目標影象的深度必須大於等於原影象的深度;

其後是可選的引數:

  • dst不用解釋了;
  • ksize是運算元的大小,必須為1、3、5、7。預設為1。
  • scale是縮放導數的比例常數,預設情況下沒有伸縮係數;
  • delta是一個可選的增量,將會加到最終的dst中,同樣,預設情況下沒有額外的值加到dst中;
  • borderType是判斷影象邊界的模式。這個引數預設值為cv2.BORDER_DEFAULT

使用

這裡還是以Sobel一文中的石獅作為測試影象,下面是測試程式碼:

[python] view plain copy
  1. #coding=utf-8  
  2. import cv2  
  3. import numpy as np    
  4.   
  5. img = cv2.imread("D:/lion.jpg"0)  
  6.   
  7. gray_lap = cv2.Laplacian(img,cv2.CV_16S,ksize = 3)  
  8. dst = cv2.convertScaleAbs(gray_lap)  
  9.   
  10. cv2.imshow('laplacian',dst)  
  11. cv2.waitKey(0)  
  12. cv2.destroyAllWindows()  
為了讓結果更清晰,這裡的ksize設為3,效果圖如下:

有點像粉筆畫,是吧。這是因為原影象未經過去噪就直接處理了。可以通過濾波一文中,使用低通濾波一節中高斯模糊來先處理一下再用拉普拉斯函式。

參考資料:

1、《Opencv2 Computer Vision Application Programming Cookbook》

2、《OpenCV References Manule》




OpenCV-Python教程(8、Canny邊緣檢測Sobel運算元)

本篇文章介紹如何用OpenCV-Python來使用Canny運算元。

提示:

  • 轉載請詳細註明原作者及出處,謝謝!
  • 本文介紹使用OpenCV-Python實現基本的濾波處理
  • 本文不介詳細的理論知識,讀者可從其他資料中獲取相應的背景知識。筆者推薦清華大學出版社的《影象處理與計算機視覺演算法及應用(第2版) 》。

原型

OpenCV-Python中Canny函式的原型為:

[python] view plain copy
  1. edge = cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]])   
必要引數:

  • 第一個引數是需要處理的原影象,該影象必須為單通道的灰度圖;
  • 第二個引數是閾值1;
  • 第三個引數是閾值2。

其中較大的閾值2用於檢測影象中明顯的邊緣,但一般情況下檢測的效果不會那麼完美,邊緣檢測出來是斷斷續續的。所以這時候用較小的第一個閾值用於將這些間斷的邊緣連線起來。

可選引數中apertureSize就是Sobel運算元的大小。而L2gradient引數是一個布林值,如果為真,則使用更精確的L2範數進行計算(即兩個方向的倒數的平方和再開放),否則使用L1範數(直接將兩個方向導數的絕對值相加)。

具體的演算法可參見清華大學出版社的《影象處理與計算機視覺演算法及應用(第2版) 》第二章,其中有Canny演算法的詳細描述及實現。

函式返回一副二值圖,其中包含檢測出的邊緣。

使用

Canny函式的使用很簡單,只需指定最大和最小閾值即可。如下:

[python] view plain copy
  1. #coding=utf-8  
  2. import cv2  
  3. import numpy as np    
  4.   
  5. img = cv2.imread("D:/lion.jpg"0)  
  6.   
  7. img = cv2.GaussianBlur(img,(3,3),0)  
  8. canny = cv2.Canny(img, 50150)  
  9.   
  10. cv2.imshow('Canny', canny)  
  11. cv2.waitKey(0)  
  12. cv2.destroyAllWindows()  
首先,由於Canny只能處理灰度圖,所以將讀取的影象轉成灰度圖。

用高斯平滑處理原影象降噪。

呼叫Canny函式,指定最大和最小閾值,其中apertureSize預設為3。

處理結果如下:

更多

這個程式只是靜態的,在github上有一個可以在執行時調整閾值大小的程式。其程式碼如下:

[python] view plain copy
  1. import cv2  
  2. import numpy as np  
  3.   
  4. def CannyThreshold(lowThreshold):  
  5.     detected_edges = cv2.GaussianBlur(gray,(3,3),0)  
  6.     detected_edges = cv2.Canny(detected_edges,lowThreshold,lowThreshold*ratio,apertureSize = kernel_size)  
  7.     dst = cv2.bitwise_and(img,img,mask = detected_edges)  # just add some colours to edges from original image.  
  8.     cv2.imshow('canny demo',dst)  
  9.   
  10. lowThreshold = 0  
  11. max_lowThreshold = 100  
  12. ratio = 3  
  13. kernel_size = 3  
  14.   
  15. img = cv2.imread('D:/lion.jpg')  
  16. gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  
  17.   
  18. cv2.namedWindow('canny demo')  
  19.   
  20. cv2.createTrackbar('Min threshold','canny demo',lowThreshold, max_lowThreshold, CannyThreshold)  
  21.   
  22. CannyThreshold(0)  # initialization  
  23. if cv2.waitKey(0) == 27:  
  24.     cv2.destroyAllWindows()  
原地址在此,其中還有其他的初級影象處理的程式碼,大夥可以去看看。後續文章將介紹更多的OpenCV的函式使用,以及視訊的處理。

參考資料:

1、《Opencv2 Computer Vision Application Programming Cookbook》

2、《OpenCV References Manule》





from: http://blog.csdn.net/sunny2038/article/category/904451

相關文章