【课题总结】OpenCV 抠图项目实战(7)边缘检测
Python 小白的課題報告—OpenCV 摳圖項目實戰(7)
本系列是 Python 小白的課題作業《基于OpenCV 的圖像分割和摳圖》。
需要說明的是,本系列并不能算是 OpenCV 的摳圖項目教程,只是以此為主題的課題報告。其中包括了一個較為完整的 PyQt 項目。
歡迎關注『Python 小白的項目實戰 @ youcans』 原創作品
Python 小白的課題報告—OpenCV 摳圖項目實戰(1)目錄摘要
Python 小白的課題報告—OpenCV 摳圖項目實戰(2)摳圖緒論
Python 小白的課題報告—OpenCV 摳圖項目實戰(3)摳圖綜述
Python 小白的課題報告—OpenCV 摳圖項目實戰(4)固定閾值摳圖
Python 小白的課題報告—OpenCV 摳圖項目實戰(5)自適應閾值摳圖
Python 小白的課題報告—OpenCV 摳圖項目實戰(6)色彩范圍摳圖
Python 小白的課題報告—OpenCV 摳圖項目實戰(7)邊緣檢測
Python 小白的課題報告—OpenCV 摳圖項目實戰(8)圖像輪廓
Python 小白的課題報告—OpenCV 摳圖項目實戰(9)評價指標
Python 小白的課題報告—OpenCV 摳圖項目實戰(10)PyQt5 使用
Python 小白的課題報告—OpenCV 摳圖項目實戰(11)算法實驗平臺
Python 小白的課題報告—OpenCV 摳圖項目實戰(12)源程序代碼
第四章 圖像分割
4.1 邊緣檢測
邊緣是指圖像中兩個不同區域的邊界線上連續的像素點的集合,是圖像局部特征不連續性的反映,體現了灰度、顏色、紋理等圖像特性的突變。
邊緣檢測是圖像處理和計算機視覺中的基本問題,邊緣檢測的目的是標識數字圖像中亮度變化明顯的點。
邊緣的灰度值呈現出階躍型或屋頂型變化。階躍型邊緣兩邊像素點的灰度值存在著明顯的差異,而屋頂型邊緣則位于灰度值上升或下降的轉折處。
梯度指出了像素值的最大變化率的方向,使用微分算子可以進行邊緣檢測:
- 恒定灰度區域,一階導數為零,二階導數為零;
- 灰度臺階或斜坡起點區域,一階導數非零,,二階導數非零;
- 灰度斜坡區域,一階導數非零,二階導數為零。
一階導數、二階導數的有限差分公式為:
?f/?x=f(x+1)?f(x)(?2f)/(?x2)=f(x+1)?2f(x)+f(x?1)?f/?x=f(x+1)-f(x)\\ (?^2 f)/(?x^2 )=f(x+1)-2f(x)+f(x-1) ?f/?x=f(x+1)?f(x)(?2f)/(?x2)=f(x+1)?2f(x)+f(x?1)
圖像梯度提取方法簡單直接,能夠有效的描述圖像的原始狀態,因此發展出多種圖像梯度算子,常用的有Laplacian、Soble和Canny算子。
1. 拉普拉斯算子(Laplacian)
最簡單的各向同性導數算子(卷積核)是拉普拉斯算子(Laplacian)。
Laplace 是導數算子,會突出圖像中的急劇灰度變化,抑制灰度緩慢變化區域,往往會產生暗色背景下的灰色邊緣和不連續圖像。將拉普拉斯圖像與原圖疊加,可以得到保留銳化效果的圖像。
拉普拉斯卷積核很容易通過卷積操作 cv. filter_2d 實現,OpenCV 也提供了拉普拉斯算子 cv.Laplacian 來實現。
函數說明:
cv.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst參數說明:
- src:輸入圖像,可以是灰度圖像,也可以是多通道的彩色圖像
- ddepth:輸出圖片的數據深度:
- dst:輸出圖像,大小和類型與 src 相同
- ksize:計算二階導數濾波器的孔徑大小,必須為正奇數,可選項
- scale:縮放比例因子,可選項,默認值為 1
- delta:輸出圖像的偏移量,可選項,默認值為 0
- borderType:邊界擴充的類型,注意不支持對側填充(BORDER_WRAP)
使用Laplacian算子進行邊緣檢測的基本程序如下:
# MattingLaplacian.py # edge detection by Laplacian # Copyright 2021 youcans, XUPT # Crated:2021-12-10import cv2 as cv from matplotlib.figure import Figureimg = cv2.imread("../images/Fig0338a.tif", flags=0) # NASA 月球影像圖# 使用 cv2.Laplacian 實現 Laplace 卷積算子 imgLaplace2 = cv2.Laplacian(img, -1, ksize=3) imgRecovery = cv2.add(img, imgLaplace2) # 恢復原圖像# 二值化邊緣圖再卷積 ret, binary = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_TRIANGLE) imgLaplace3 = cv2.Laplacian(binary, cv2.CV_64F) imgLaplace3 = cv2.convertScaleAbs(imgLaplace3)plt.figure(figsize=(9, 6)) plt.subplot(131), plt.axis('off'), plt.title("Original") plt.imshow(img, cmap='gray', vmin=0, vmax=255) plt.subplot(132), plt.axis('off'), plt.title("cv.Laplacian") plt.imshow(imgLaplace2, cmap='gray', vmin=0, vmax=255) plt.subplot(133), plt.axis('off'), plt.title("thresh-Laplacian") plt.imshow(imgLaplace3, cmap='gray', vmin=0, vmax=255) plt.tight_layout() plt.show()使用Laplacian算子進行邊緣檢測的結果如下圖所示。
圖4.1 Laplacian算子進行邊緣檢測
2. 索貝爾梯度算子(Sobel)
Sobel 算子是一種離散的微分算子,是高斯平滑和微分求導的聯合運算,抗噪聲能力強。
Sobel 梯度算子利用局部差分尋找邊緣,計算得到梯度的近似值。先計算水平、垂直方向的梯度,再求總梯度。編程實現時,可以用絕對值近似平方根。
OpenCV 也提供了函數 cv.Sobel() 實現 Sobel 梯度算子。
函數說明:
cv.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst參數說明:
- src:輸入圖像,灰度圖像,不適用彩色圖像
- dst:輸出圖像,大小和類型與 src 相同
- ddepth:輸出圖片的數據深度,由輸入圖像的深度進行選擇
- dx:x 軸方向導數的階數,1 或 2
- dy:y 軸方向導數的階數,1 或 2
- ksize:Sobel算子卷積核的大小
- scale:縮放比例因子,可選項,默認值為 1
- delta:輸出圖像的偏移量,可選項,默認值為 0
使用Sobel算子進行邊緣檢測的基本程序如下:
# MattingSobel.py # edge detection by Sobel # Copyright 2021 youcans, XUPT # Crated:2021-12-10import cv2 as cv from matplotlib.figure import Figureimg = cv2.imread("../images/imgGaia.tif", flags=0)# 使用函數 filter2D 實現 Sobel 算子 kernSobelX = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) # SobelX kernel kernSobelY = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]]) # SobelY kernel imgSobelX = cv2.filter2D(img, -1, kernSobelX, borderType=cv2.BORDER_REFLECT) imgSobelY = cv2.filter2D(img, -1, kernSobelY, borderType=cv2.BORDER_REFLECT)# 使用 cv2.Sobel 實現 Sobel 算子 SobelX = cv2.Sobel(img, cv2.CV_16S, 1, 0) # 計算 x 軸方向 SobelY = cv2.Sobel(img, cv2.CV_16S, 0, 1) # 計算 y 軸方向 absX = cv2.convertScaleAbs(SobelX) # 轉回 uint8 absY = cv2.convertScaleAbs(SobelY) # 轉回 uint8 SobelXY = cv2.addWeighted(absX, 0.5, absY, 0.5, 0) # 用絕對值近似平方根plt.figure(figsize=(10, 6)) plt.subplot(141), plt.axis('off'), plt.title("Original") plt.imshow(img, cmap='gray', vmin=0, vmax=255) plt.subplot(142), plt.axis('off'), plt.title("SobelX") plt.imshow(SobelX, cmap='gray', vmin=0, vmax=255) plt.subplot(143), plt.axis('off'), plt.title("SobelY") plt.imshow(SobelY, cmap='gray', vmin=0, vmax=255) plt.subplot(144), plt.axis('off'), plt.title("SobelXY") plt.imshow(SobelXY, cmap='gray') plt.tight_layout() plt.show()使用Sobel算子進行邊緣檢測的結果如下圖所示。
圖4.2 Sobel算子進行邊緣檢測
3. Canny 邊緣檢測
Canny邊緣檢測是由Jhon F.Canny提出的算法,具有低錯誤率、定位良好、最小響應的特點。
Canny算子在過濾噪聲、計算梯度的同時實現非最大值抑制,不容易受噪聲的干擾。采用雙閾值法可以分別檢測到強邊緣和弱邊緣,并且僅當弱邊緣與強邊緣相連時,才將弱邊緣包含在輸出結果中,這就保障了檢測到真正的弱邊緣。
Canny算法的工作原理為:
(1)使用高斯濾波器對圖像進行平滑去噪;
(2)計算輸入圖像梯度;
(3)在邊緣上使用非極大值抑制(NMS)進行過濾;
(4)在檢測到的邊緣上使用雙閾值法去除假陽性;
(5)分析所有的邊緣及其連接,以保留真正的邊緣并消除不明顯的邊緣;
OpenCV 也提供了函數 cv.Sobel() 實現 Sobel 梯度算子。
函數說明:
cv.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]) → edges參數說明:
- image:輸入圖像,灰度圖像,不適用彩色圖像
- edges:輸出圖像,單通道 8bit圖像,大小與images相同
- threshold1:滯后過程的較小閾值,用于邊緣連接
- threshold2:滯后過程的較大閾值,用于查找明顯的邊緣
- apertureSize:Sobel算子的卷積核大小
- L2gradient:標志,使用 L1范數或 L2范數正則化
使用 Canny()進行邊緣檢測的基本程序如下:
# MattingCanny.py # edge detection by Cann # Copyright 2021 youcans, XUPTy # Crated:2021-12-10import cv2 as cv from matplotlib.figure import FigureimgOri = cv2.imread("../images/imgGaia.tif", flags=0)# canny(): 邊緣檢測 imgBlur = cv2.GaussianBlur(imgOri, (3, 3), 0) imgCanny = cv2.Canny(imgBlur, 50, 150)# 形態學:邊緣檢測 _, imgThr = cv2.threshold(imgOri, 200, 255, cv2.THRESH_BINARY) # 固定閾值二值化 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) # 定義矩形結構元素 gradient = cv2.morphologyEx(Thr_img, cv2.MORPH_GRADIENT, kernel) # 梯度plt.figure(figsize=(9, 6)) plt.subplot(221), plt.axis('off'), plt.title("Original") plt.imshow(imgOri, cmap='gray', vmin=0, vmax=255) plt.subplot(222), plt.axis('off'), plt.title("GaussianBlur") plt.imshow(imgBlur, cmap='gray', vmin=0, vmax=255) plt.subplot(223), plt.axis('off'), plt.title("Canny detection") plt.imshow(imgCanny, cmap='gray', vmin=0, vmax=255) plt.subplot(224), plt.axis('off'), plt.title("Gradient detection") plt.imshow(gradient, cmap='gray') plt.tight_layout() plt.show()使用Canny算子進行邊緣檢測的結果如下圖所示。
圖4.3 Canny 算子進行邊緣檢測
【本節完】
版權聲明:
歡迎關注『Python 小白的項目實戰 @ youcans』 原創作品
原創作品,轉載必須標注原文鏈接:https://blog.csdn.net/youcans/article/details/122296231
Copyright 2022 youcans, XUPT
Crated:2022-01-05
歡迎關注『Python 小白的項目實戰 @ youcans』 原創作品
Python 小白的課題報告—OpenCV 摳圖項目實戰(1)目錄摘要
Python 小白的課題報告—OpenCV 摳圖項目實戰(2)摳圖緒論
Python 小白的課題報告—OpenCV 摳圖項目實戰(3)摳圖綜述
Python 小白的課題報告—OpenCV 摳圖項目實戰(4)固定閾值摳圖
Python 小白的課題報告—OpenCV 摳圖項目實戰(5)自適應閾值摳圖
Python 小白的課題報告—OpenCV 摳圖項目實戰(6)色彩范圍摳圖
Python 小白的課題報告—OpenCV 摳圖項目實戰(7)邊緣檢測
Python 小白的課題報告—OpenCV 摳圖項目實戰(8)圖像輪廓
Python 小白的課題報告—OpenCV 摳圖項目實戰(9)評價指標
Python 小白的課題報告—OpenCV 摳圖項目實戰(10)PyQt5 使用
Python 小白的課題報告—OpenCV 摳圖項目實戰(11)算法實驗平臺
Python 小白的課題報告—OpenCV 摳圖項目實戰(12)源程序代碼
總結
以上是生活随笔為你收集整理的【课题总结】OpenCV 抠图项目实战(7)边缘检测的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html页div引入pano2显示一半,
- 下一篇: 从一个点云里面创建一个深度图