OpenCV图像处理(下) 边缘检测+模板匹配+霍夫变换
OpenCV圖像處理(下)
- 一、邊緣檢測
- 1. 原理
- 2. Sobel檢測算子
- 2.1 方法
- 2.2 應(yīng)用
- 3. Laplacian算子
- 4. Canny邊緣檢測
- 4.1 原理
- 4.2 應(yīng)用
- 二、模版匹配和霍夫變換
- 1. 模板匹配
- 1.1 原理
- 1.2 實(shí)現(xiàn)
- 2. 霍夫變換
- 2.1 原理
- (1)原理
- (2)實(shí)現(xiàn)流程
- 2.2 霍夫線檢測
- 2.3 霍夫圓檢測[了解]
- (1)原理
- (2)API
- (3)實(shí)現(xiàn)
一、邊緣檢測
1. 原理
邊緣檢測是圖像處理和計(jì)算機(jī)視覺中的基本問題,邊緣檢測的目的是標(biāo)識數(shù)字圖像中亮度變化明顯的點(diǎn)。圖像屬性中的顯著變化通常反映了屬性的重要事件和變化。邊緣的表現(xiàn)形式如下圖所示:
圖像邊緣檢測大幅度地減少了數(shù)據(jù)量,并且剔除了可以認(rèn)為不相關(guān)的信息,保留了圖像重要的結(jié)構(gòu)屬性。有許多方法用于邊緣檢測,它們的絕大部分可以劃分為兩類:基于搜索和基于零穿越。
- 基于搜索:通過尋找圖像一階導(dǎo)數(shù)中的最大值來檢測邊界,然后利用計(jì)算結(jié)果估計(jì)邊緣的局部方向,通常采用梯度的方向,并利用此方向找到局部梯度模的最大值,代表算法是Sobel算子和Scharr算子。
- 基于零穿越:通過尋找圖像二階導(dǎo)數(shù)零穿越來尋找邊界,代表算法是Laplacian算子。
2. Sobel檢測算子
Sobel邊緣檢測算法比較簡單,實(shí)際應(yīng)用中效率比canny邊緣檢測效率要高,但是邊緣不如Canny檢測的準(zhǔn)確,但是很多實(shí)際應(yīng)用的場合,sobel邊緣卻是首選,Sobel算子是高斯平滑與微分操作的結(jié)合體,所以其抗噪聲能力很強(qiáng),用途較多。尤其是效率要求較高,而對細(xì)紋理不太關(guān)心的時(shí)候。
2.1 方法
對于不連續(xù)的函數(shù),一階導(dǎo)數(shù)可以寫作:
或
所以有:
假設(shè)要處理的圖像為II,在兩個(gè)方向求導(dǎo):
- 水平變化: 將圖像II 與奇數(shù)大小的模版進(jìn)行卷積,結(jié)果為GxG_xGx??? 。比如,當(dāng)模板大小為3時(shí), GxG_xGx?為:
- 垂直變化: 將圖像II與奇數(shù)大小的模板進(jìn)行卷積,結(jié)果為GyG_yGy???。比如,當(dāng)模板大小為3時(shí), GyG_yGy?為
在圖像的每一點(diǎn),結(jié)合以上兩個(gè)結(jié)果求出:
統(tǒng)計(jì)極大值所在的位置,就是圖像的邊緣。
注意:當(dāng)內(nèi)核大小為3時(shí), 以上Sobel內(nèi)核可能產(chǎn)生比較明顯的誤差, 為解決這一問題,我們使用Scharr函數(shù),但該函數(shù)僅作用于大小為3的內(nèi)核。該函數(shù)的運(yùn)算與Sobel函數(shù)一樣快,但結(jié)果卻更加精確,其計(jì)算方法為:
2.2 應(yīng)用
利用OpenCV進(jìn)行sobel邊緣檢測的API是:
Sobel_x_or_y = cv2.Sobel(src, ddepth, dx, dy, dst, ksize, scale, delta, borderType)參數(shù):
- src:傳入的圖像
- ddepth: 圖像的深度
- dx和dy: 指求導(dǎo)的階數(shù),0表示這個(gè)方向上沒有求導(dǎo),取值為0、1。
- ksize: 是Sobel算子的大小,即卷積核的大小,必須為奇數(shù)1、3、5、7,默認(rèn)為3。
注意:如果ksize=-1,就演變成為3x3的Scharr算子。 - scale:縮放導(dǎo)數(shù)的比例常數(shù),默認(rèn)情況為沒有伸縮系數(shù)。
- borderType:圖像邊界的模式,默認(rèn)值為cv2.BORDER_DEFAULT。
Sobel函數(shù)求完導(dǎo)數(shù)后會(huì)有負(fù)值,還有會(huì)大于255的值。而原圖像是uint8,即8位無符號數(shù),所以Sobel建立的圖像位數(shù)不夠,會(huì)有截?cái)唷R虼艘褂?6位有符號的數(shù)據(jù)類型,即cv2.CV_16S。處理完圖像后,再使用cv2.convertScaleAbs()函數(shù)將其轉(zhuǎn)回原來的uint8格式,否則圖像無法顯示。
Sobel算子是在兩個(gè)方向計(jì)算的,最后還需要用cv2.addWeighted( )函數(shù)將其組合起來
Scale_abs = cv2.convertScaleAbs(x) # 格式轉(zhuǎn)換函數(shù) result = cv2.addWeighted(src1, alpha, src2, beta) # 圖像混合示例:
import cv2 as cv import numpy as np from matplotlib import pyplot as plt # 1 讀取圖像 img = cv.imread('./image/horse.jpg',0) # 2 計(jì)算Sobel卷積結(jié)果 x = cv.Sobel(img, cv.CV_16S, 1, 0) y = cv.Sobel(img, cv.CV_16S, 0, 1) # 3 將數(shù)據(jù)進(jìn)行轉(zhuǎn)換 Scale_absX = cv.convertScaleAbs(x) # convert 轉(zhuǎn)換 scale 縮放 Scale_absY = cv.convertScaleAbs(y) # 4 結(jié)果合成 result = cv.addWeighted(Scale_absX, 0.5, Scale_absY, 0.5, 0) # 5 圖像顯示 plt.figure(figsize=(10,8),dpi=100) plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('原圖') plt.xticks([]), plt.yticks([]) plt.subplot(122),plt.imshow(result,cmap = plt.cm.gray),plt.title('Sobel濾波后結(jié)果') plt.xticks([]), plt.yticks([]) plt.show()將上述代碼中計(jì)算sobel算子的部分中將ksize設(shè)為-1,就是利用Scharr進(jìn)行邊緣檢測。
x = cv.Sobel(img, cv.CV_16S, 1, 0, ksize = -1) y = cv.Sobel(img, cv.CV_16S, 0, 1, ksize = -1)3. Laplacian算子
Laplacian是利用二階導(dǎo)數(shù)來檢測邊緣 。 因?yàn)閳D像是 “2維”, 我們需要在兩個(gè)方向求導(dǎo),如下式所示:
那不連續(xù)函數(shù)的二階導(dǎo)數(shù)是:
那使用的卷積核是:
API:
參數(shù):
- Src: 需要處理的圖像,
- Ddepth: 圖像的深度,-1表示采用的是原圖像相同的深度,目標(biāo)圖像的深度必須大于等于原圖像的深度;
- ksize:算子的大小,即卷積核的大小,必須為1,3,5,7。
示例:
import cv2 as cv import numpy as np from matplotlib import pyplot as plt # 1 讀取圖像 img = cv.imread('./image/horse.jpg',0) # 2 laplacian轉(zhuǎn)換 result = cv.Laplacian(img,cv.CV_16S) Scale_abs = cv.convertScaleAbs(result) # 3 圖像展示 plt.figure(figsize=(10,8),dpi=100) plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('原圖') plt.xticks([]), plt.yticks([]) plt.subplot(122),plt.imshow(Scale_abs,cmap = plt.cm.gray),plt.title('Laplacian檢測后結(jié)果') plt.xticks([]), plt.yticks([]) plt.show()4. Canny邊緣檢測
Canny 邊緣檢測算法是一種非常流行的邊緣檢測算法,是 John F. Canny 于 1986年提出的,被認(rèn)為是最優(yōu)的邊緣檢測算法。
4.1 原理
Canny邊緣檢測算法是由4步構(gòu)成,分別介紹如下:
- 第一步:噪聲去除
由于邊緣檢測很容易受到噪聲的影響,所以首先使用5?55*55?5高斯濾波器去除噪聲,在圖像平滑那一章節(jié)中已經(jīng)介紹過。
- 第二步:計(jì)算圖像梯度
對平滑后的圖像使用 Sobel 算子計(jì)算水平方向和豎直方向的一階導(dǎo)數(shù)(Gx 和 Gy)。根據(jù)得到的這兩幅梯度圖(Gx 和 Gy)找到邊界的梯度和方向,公式如下:
如果某個(gè)像素點(diǎn)是邊緣,則其梯度方向總是垂直與邊緣垂直。梯度方向被歸為四類:垂直,水平,和兩個(gè)對角線方向。
- 第三步:非極大值抑制
在獲得梯度的方向和大小之后,對整幅圖像進(jìn)行掃描,去除那些非邊界上的點(diǎn)。對每一個(gè)像素進(jìn)行檢查,看這個(gè)點(diǎn)的梯度是不是周圍具有相同梯度方向的點(diǎn)中最大的。如下圖所示:
A點(diǎn)位于圖像的邊緣,在其梯度變化方向,選擇像素點(diǎn)B和C,用來檢驗(yàn)A點(diǎn)的梯度是否為極大值,若為極大值,則進(jìn)行保留,否則A點(diǎn)被抑制,最終的結(jié)果是具有“細(xì)邊”的二進(jìn)制圖像。
- 第四步:滯后閾值
現(xiàn)在要確定真正的邊界。 我們設(shè)置兩個(gè)閾值: minVal 和 maxVal。 當(dāng)圖像的灰度梯度高于 maxVal 時(shí)被認(rèn)為是真的邊界, 低于 minVal 的邊界會(huì)被拋棄。如果介于兩者之間的話,就要看這個(gè)點(diǎn)是否與某個(gè)被確定為真正的邊界點(diǎn)相連,如果是就認(rèn)為它也是邊界點(diǎn),如果不是就拋棄。如下圖:
如上圖所示,A 高于閾值 maxVal 所以是真正的邊界點(diǎn),C 雖然低于 maxVal 但高于 minVal 并且與 A 相連,所以也被認(rèn)為是真正的邊界點(diǎn)。而 B 就會(huì)被拋棄,因?yàn)榈陀?maxVal 而且不與真正的邊界點(diǎn)相連。所以選擇合適的 maxVal 和 minVal 對于能否得到好的結(jié)果非常重要。
4.2 應(yīng)用
在OpenCV中要實(shí)現(xiàn)Canny檢測使用的API:
canny = cv2.Canny(image, threshold1, threshold2)參數(shù):
- image:灰度圖,
- threshold1: minval,較小的閾值將間斷的邊緣連接起來
- threshold2: maxval,較大的閾值檢測圖像中明顯的邊緣
示例:
import cv2 as cv import numpy as np from matplotlib import pyplot as plt # 1 圖像讀取 img = cv.imread('./image/horse.jpg',0) # 2 Canny邊緣檢測 lowThreshold = 0 max_lowThreshold = 100 canny = cv.Canny(img, lowThreshold, max_lowThreshold) # 3 圖像展示 plt.figure(figsize=(10,8),dpi=100) plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('原圖') plt.xticks([]), plt.yticks([]) plt.subplot(122),plt.imshow(canny,cmap = plt.cm.gray),plt.title('Canny檢測后結(jié)果') plt.xticks([]), plt.yticks([]) plt.show()二、模版匹配和霍夫變換
1. 模板匹配
1.1 原理
所謂的模板匹配,就是在給定的圖片中查找和模板最相似的區(qū)域,該算法的輸入包括模板和圖片,整個(gè)任務(wù)的思路就是按照滑窗的思路不斷的移動(dòng)模板圖片,計(jì)算其與圖像中對應(yīng)區(qū)域的匹配度,最終將匹配度最高的區(qū)域選擇為最終的結(jié)果。
實(shí)現(xiàn)流程:
- 準(zhǔn)備兩幅圖像:
1.原圖像(I):在這幅圖中,找到與模板相匹配的區(qū)域
2.模板(T):與原圖像進(jìn)行比對的圖像塊
- 滑動(dòng)模板圖像和原圖像進(jìn)行比對:
將模板塊每次移動(dòng)一個(gè)像素 (從左往右,從上往下),在每一個(gè)位置,都計(jì)算與模板圖像的相似程度。
-
對于每一個(gè)位置將計(jì)算的相似結(jié)果保存在結(jié)果矩陣(R)中。如果輸入圖像的大小(WxH)且模板圖像的大小(wxh),則輸出矩陣R的大小為(W-w + 1,H-h + 1)將R顯示為圖像,如下圖所示:
-
獲得上述圖像后,查找最大值所在的位置,那么該位置對應(yīng)的區(qū)域就被認(rèn)為是最匹配的。對應(yīng)的區(qū)域就是以該點(diǎn)為頂點(diǎn),長寬和模板圖像一樣大小的矩陣。
1.2 實(shí)現(xiàn)
我們使用OpenCV中的方法實(shí)現(xiàn)模板匹配。
API:
res = cv.matchTemplate(img,template,method)參數(shù):
- img: 要進(jìn)行模板匹配的圖像
- Template :模板
- method:實(shí)現(xiàn)模板匹配的算法,主要有:
- 平方差匹配(CV_TM_SQDIFF):利用模板與圖像之間的平方差進(jìn)行匹配,最好的匹配是0,匹配越差,匹配的值越大。
- 相關(guān)匹配(CV_TM_CCORR):利用模板與圖像間的乘法進(jìn)行匹配,數(shù)值越大表示匹配程度較高,越小表示匹配效果差。
- 利用相關(guān)系數(shù)匹配(CV_TM_CCOEFF):利用模板與圖像間的相關(guān)系數(shù)匹配,1表示完美的匹配,-1表示最差的匹配。
完成匹配后,使用cv.minMaxLoc()方法查找最大值所在的位置即可。如果使用平方差作為比較方法,則最小值位置是最佳匹配位置。
示例:
在該案例中,載入要搜索的圖像和模板,圖像如下所示:
模板如下所示:
通過matchTemplate實(shí)現(xiàn)模板匹配,使用minMaxLoc定位最匹配的區(qū)域,并用矩形標(biāo)注最匹配的區(qū)域。
import cv2 as cv import numpy as np from matplotlib import pyplot as plt # 1 圖像和模板讀取 img = cv.imread('./image/wulin2.jpeg') template = cv.imread('./image/wulin.jpeg') h,w,l = template.shape # 2 模板匹配 # 2.1 模板匹配 res = cv.matchTemplate(img, template, cv.TM_CCORR) # 2.2 返回圖像中最匹配的位置,確定左上角的坐標(biāo),并將匹配位置繪制在圖像上 min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res) # 使用平方差時(shí)最小值為最佳匹配位置 # top_left = min_loc top_left = max_loc bottom_right = (top_left[0] + w, top_left[1] + h) cv.rectangle(img, top_left, bottom_right, (0,255,0), 2) # 3 圖像顯示 plt.imshow(img[:,:,::-1]) plt.title('匹配結(jié)果'), plt.xticks([]), plt.yticks([]) plt.show()拓展:模板匹配不適用于尺度變換,視角變換后的圖像,這時(shí)我們就要使用關(guān)鍵點(diǎn)匹配算法,比較經(jīng)典的關(guān)鍵點(diǎn)檢測算法包括SIFT和SURF等,主要的思路是首先通過關(guān)鍵點(diǎn)檢測算法獲取模板和測試圖片中的關(guān)鍵點(diǎn);然后使用關(guān)鍵點(diǎn)匹配算法處理即可,這些關(guān)鍵點(diǎn)可以很好的處理尺度變化、視角變換、旋轉(zhuǎn)變化、光照變化等,具有很好的不變性。
2. 霍夫變換
霍夫變換常用來提取圖像中的直線和圓等幾何形狀,如下圖所示:
2.1 原理
(1)原理
在笛卡爾坐標(biāo)系中,一條直線由兩個(gè)點(diǎn)A=(x1,y1)A=(x_1,y_1)A=(x1?,y1?)和B=(x2,y2)B=(x_2,y_2)B=(x2?,y2?)確定,如下圖所示:
將直線y=kx+q可寫成關(guān)于(k,q)(k,q)的函數(shù)表達(dá)式:
對應(yīng)的變換通過圖形直觀的表示下:
變換后的空間我們叫做霍夫空間。即:笛卡爾坐標(biāo)系中的一條直線,對應(yīng)于霍夫空間中的一個(gè)點(diǎn)。反過來,同樣成立,霍夫空間中的一條線,對應(yīng)于笛卡爾坐標(biāo)系中一個(gè)點(diǎn),如下所示:
我們再來看下A、B兩個(gè)點(diǎn),對應(yīng)于霍夫空間的情形:
在看下三點(diǎn)共線的情況:
可以看出如果在笛卡爾坐標(biāo)系的點(diǎn)共線,那么這些點(diǎn)在霍夫空間中對應(yīng)的直線交于一點(diǎn)。
如果不止存在一條直線時(shí),如下所示:
我們選擇盡可能多的直線匯成的點(diǎn),上圖中三條直線匯成的A、B兩點(diǎn),將其對應(yīng)回笛卡爾坐標(biāo)系中的直線:
到這里我們似乎已經(jīng)完成了霍夫變換的求解。但如果像下圖這種情況時(shí):
上圖中的直線是x=2x=2x=2,那(k,q)怎么確定呢?
為了解決這個(gè)問題,我們考慮將笛卡爾坐標(biāo)系轉(zhuǎn)換為極坐標(biāo)。
在極坐標(biāo)下是一樣的,極坐標(biāo)中的點(diǎn)對應(yīng)于霍夫空間的線,這時(shí)的霍夫空間是不在是參數(shù)(k,q)(k,q)(k,q)的空間,而是(ρ,θ)(\rho,\theta)(ρ,θ)的空間,ρ\rhoρ是原點(diǎn)到直線的垂直距離,θ\thetaθ表示直線的垂線與橫軸順時(shí)針方向的夾角,垂直線的角度為0度,水平線的角度是180度。
我們只要求得霍夫空間中的交點(diǎn)的位置,即可得到原坐標(biāo)系下的直線。
(2)實(shí)現(xiàn)流程
假設(shè)有一個(gè)大小為100*?100的圖片,使用霍夫變換檢測圖片中的直線,則步驟如下所示:
-
直線都可以使用(ρ,θ)(\rho,\theta)(ρ,θ) 表示,首先創(chuàng)建一個(gè)2D數(shù)組,我們叫做累加器,初始化所有值為0,行表示ρ\rhoρ ,列表示θ\thetaθ 。
-
該數(shù)組的大小決定了結(jié)果的準(zhǔn)確性,若希望角度的精度為1度,那就需要180列。對于ρ\rhoρ,最大值為圖片對角線的距離,如果希望精度達(dá)到像素級別,行數(shù)應(yīng)該與圖像的對角線的距離相等。
-
取直線上的第一個(gè)點(diǎn)(x,y)(x,y)(x,y),將其帶入直線在極坐標(biāo)中的公式中,然后遍歷θ\thetaθ的取值:0,1,2,…,180,分別求出對應(yīng)的ρ\rhoρ值,如果這個(gè)數(shù)值在上述累加器中存在相應(yīng)的位置,則在該位置上加1.
-
取直線上的第二個(gè)點(diǎn),重復(fù)上述步驟,更新累加器中的值。對圖像中的直線上的每個(gè)點(diǎn)都直線以上步驟,每次更新累加器中的值。
-
搜索累加器中的最大值,并找到其對應(yīng)的(ρ,θ)(\rho,\theta)(ρ,θ),就可將圖像中的直線表示出來。
2.2 霍夫線檢測
在OpenCV中做霍夫線檢測是使用的API是:
cv.HoughLines(img, rho, theta, threshold)參數(shù):
- img: 檢測的圖像,要求是二值化的圖像,所以在調(diào)用霍夫變換之前首先要進(jìn)行二值化,或者進(jìn)行Canny邊緣檢測
- rho、theta: ρ\rhoρ 和θ\thetaθ的精確度
- threshold: 閾值,只有累加器中的值高于該閾值時(shí)才被認(rèn)為是直線。
霍夫線檢測的整個(gè)流程如下圖所示,這是在stackflow上一個(gè)關(guān)于霍夫線變換的解釋:
示例:
檢測下述圖像中的直線:
import numpy as np import random import cv2 as cv import matplotlib.pyplot as plt # 1.加載圖片,轉(zhuǎn)為二值圖 img = cv.imread('./image/rili.jpg')gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) edges = cv.Canny(gray, 50, 150)# 2.霍夫直線變換 lines = cv.HoughLines(edges, 0.8, np.pi / 180, 150) # 3.將檢測的線繪制在圖像上(注意是極坐標(biāo)噢) for line in lines:rho, theta = line[0]a = np.cos(theta)b = np.sin(theta)x0 = a * rhoy0 = b * rhox1 = int(x0 + 1000 * (-b))y1 = int(y0 + 1000 * (a))x2 = int(x0 - 1000 * (-b))y2 = int(y0 - 1000 * (a))cv.line(img, (x1, y1), (x2, y2), (0, 255, 0)) # 4. 圖像顯示 plt.figure(figsize=(10,8),dpi=100) plt.imshow(img[:,:,::-1]),plt.title('霍夫變換線檢測') plt.xticks([]), plt.yticks([]) plt.show()2.3 霍夫圓檢測[了解]
(1)原理
圓的表示式是:
其中aa和bb表示圓心坐標(biāo),rr表示圓半徑,因此標(biāo)準(zhǔn)的霍夫圓檢測就是在這三個(gè)參數(shù)組成的三維空間累加器上進(jìn)行圓形檢測,此時(shí)效率就會(huì)很低,所以O(shè)penCV中使用霍夫梯度法進(jìn)行圓形的檢測。
霍夫梯度法將霍夫圓檢測范圍兩個(gè)階段,第一階段檢測圓心,第二階段利用圓心推導(dǎo)出圓半徑。
-
圓心檢測的原理:圓心是圓周法線的交匯處,設(shè)置一個(gè)閾值,在某點(diǎn)的相交的直線的條數(shù)大于這個(gè)閾值就認(rèn)為該交匯點(diǎn)為圓心。
-
圓半徑確定原理:圓心到圓周上的距離(半徑)是相同的,確定一個(gè)閾值,只要相同距離的數(shù)量大于該閾值,就認(rèn)為該距離是該圓心的半徑。
原則上霍夫變換可以檢測任何形狀,但復(fù)雜的形狀需要的參數(shù)就多,霍夫空間的維數(shù)就多,因此在程序?qū)崿F(xiàn)上所需的內(nèi)存空間以及運(yùn)行效率上都不利于把標(biāo)準(zhǔn)霍夫變換應(yīng)用于實(shí)際復(fù)雜圖形的檢測中。霍夫梯度法是霍夫變換的改進(jìn),它的目的是減小霍夫空間的維度,提高效率。
(2)API
在OpenCV中檢測圖像中的圓環(huán)使用的是API是:
circles = cv.HoughCircles(image, method, dp, minDist, param1=100, param2=100, minRadius=0,maxRadius=0 )參數(shù):
-
image:輸入圖像,應(yīng)輸入灰度圖像
-
method:使用霍夫變換圓檢測的算法,它的參數(shù)是CV_HOUGH_GRADIENT
-
dp:霍夫空間的分辨率,dp=1時(shí)表示霍夫空間與輸入圖像空間的大小一致,dp=2時(shí)霍夫空間是輸入圖像空間的一半,以此類推
-
minDist為圓心之間的最小距離,如果檢測到的兩個(gè)圓心之間距離小于該值,則認(rèn)為它們是同一個(gè)圓心
-
param1:邊緣檢測時(shí)使用Canny算子的高閾值,低閾值是高閾值的一半。
-
param2:檢測圓心和確定半徑時(shí)所共有的閾值
-
minRadius和maxRadius為所檢測到的圓半徑的最小值和最大值
返回:
- circles:輸出圓向量,包括三個(gè)浮點(diǎn)型的元素——圓心橫坐標(biāo),圓心縱坐標(biāo)和圓半徑
(3)實(shí)現(xiàn)
由于霍夫圓檢測對噪聲比較敏感,所以首先對圖像進(jìn)行中值濾波。
import cv2 as cv import numpy as np import matplotlib.pyplot as plt # 1 讀取圖像,并轉(zhuǎn)換為灰度圖 planets = cv.imread("./image/star.jpeg") gay_img = cv.cvtColor(planets, cv.COLOR_BGRA2GRAY) # 2 進(jìn)行中值模糊,去噪點(diǎn) img = cv.medianBlur(gay_img, 7) # 3 霍夫圓檢測 circles = cv.HoughCircles(img, cv.HOUGH_GRADIENT, 1, 200, param1=100, param2=30, minRadius=0, maxRadius=100) # 4 將檢測結(jié)果繪制在圖像上 for i in circles[0, :]: # 遍歷矩陣每一行的數(shù)據(jù)# 繪制圓形cv.circle(planets, (i[0], i[1]), i[2], (0, 255, 0), 2)# 繪制圓心cv.circle(planets, (i[0], i[1]), 2, (0, 0, 255), 3) # 5 圖像顯示 plt.figure(figsize=(10,8),dpi=100) plt.imshow(planets[:,:,::-1]),plt.title('霍夫變換圓檢測') plt.xticks([]), plt.yticks([]) plt.show()總結(jié)
以上是生活随笔為你收集整理的OpenCV图像处理(下) 边缘检测+模板匹配+霍夫变换的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: xpath helper
- 下一篇: RedHat下载安装JDK的方法(方法二