前言:Hello大家好,我是小哥談。圖形檢測是計(jì)算機(jī)視覺的一項(xiàng)重要功能。通過圖形檢測可以分析圖像中可能存在的形狀,然后對這些形狀進(jìn)行描繪,例如搜索并繪制圖像的邊緣,定位圖像的位置,判斷圖像中有沒有直線、有沒有圓形等。雖然圖形檢測涉及非常深?yuàn)W的數(shù)學(xué)算法,但是OpenCV已經(jīng)將這些算法封裝成了簡單的方法,開發(fā)者只要學(xué)會(huì)如何調(diào)用方法、如何調(diào)整參數(shù)即可很好的實(shí)現(xiàn)檢測功能。本節(jié)課就介紹如何檢測圖像的形狀、圖像所占的區(qū)域,以及如何查找圖像中出現(xiàn)的幾何圖形等。??
?前期回顧:
? ? ? ? ?史上最全OpenCV常用方法及使用說明匯總,建議收藏!
? ? ? ???OpenCV基礎(chǔ)知識(shí)(1)— OpenCV概述
? ? ? ? ?OpenCV基礎(chǔ)知識(shí)(2)— 圖像處理的基本操作(讀取圖像、顯示圖像、保存圖像和獲取圖像屬性)
? ? ? ? ?OpenCV基礎(chǔ)知識(shí)(3)— 圖像數(shù)字化基礎(chǔ)(像素、色彩空間)
? ? ? ? ?OpenCV基礎(chǔ)知識(shí)(4)— 繪制圖形(線段、矩形、圓形、多邊形和文字)
? ? ? ???OpenCV基礎(chǔ)知識(shí)(5)— 幾何變換(縮放、翻轉(zhuǎn)、旋轉(zhuǎn)和透視)
? ? ? ? ?OpenCV基礎(chǔ)知識(shí)(6)— 濾波器(均值濾波器、中值濾波器、高斯濾波器和雙邊濾波器)
? ? ? ? ?OpenCV基礎(chǔ)知識(shí)(7)— 腐蝕與膨脹
? ? ? ? ?目錄
??1.圖像的輪廓?
??2.輪廓的擬合
????2.1 矩形包圍框
????2.2?圓形包圍框
??3.Canny邊緣檢測
??4.霍夫變換
????4.1?直線檢測
????4.2?圓環(huán)檢測
??5.總結(jié)
??1.圖像的輪廓?
輪廓,是指圖像中圖形或物體的外邊緣線條。簡單的幾何圖形輪廓是由平滑的線構(gòu)成的,容易識(shí)別,但不規(guī)則的輪廓可能有許多個(gè)點(diǎn)構(gòu)成,識(shí)別起來比較困難。
OpenCV提供的findContours()方法可以通過計(jì)算圖像梯度來判斷出圖像的邊緣,然后將邊緣的點(diǎn)封裝成數(shù)組返回。??
findContours()方法的語法格式如下:
contours,hierarchy = cv2.findContours(image,mode,method)
參數(shù)說明:
image:被檢測的圖像,必須是8位單通道二值圖像。如果原始圖像是彩色圖像,必須轉(zhuǎn)為灰度圖像,并經(jīng)過二值化閾值處理。
mode:輪廓的檢索模式,具體值詳見表。
參數(shù)值 | 含義 |
cv2.RETR_EXTERNAL | 只檢測外輪廓 |
CV2.RETR_LIST | 檢測所有輪廓,但不建立層次關(guān)系。 |
CV2.RETR_CCOMP | 檢測所有輪廓,并建立兩級層次關(guān)系。 |
CV2.RETR_TREE | 檢測所有輪廓,并建立樹狀結(jié)構(gòu)的層次關(guān)系。 |
method:檢測輪廓時(shí)使用的方法,具體值詳見表。
參數(shù)值 | 含義 |
cv2.CHAIN_APPROX_NONE | 儲(chǔ)存輪廓上的所有點(diǎn) |
cv2.CHAIN_APPROX_SIMPLE | 只保存水平、垂直或?qū)蔷€輪廓的端點(diǎn) |
CV2.CHAIN_APPROX_TC89_L1 | Ten-Chin1近似算法的一種 |
CV2.CHAIN_APPROX_TC89_KCOS | Ten-Chin1近似算法的一種 |
返回值說明:
contours:檢測出的所有輪廓,list類型,每一個(gè)元素都是某個(gè)輪廓的像素坐標(biāo)數(shù)組。
hierarchy:輪廓之間測層次關(guān)系。
通過findContours()方法找到圖像輪廓之后,為了方便開發(fā)人員觀測,最好能把輪廓畫出來,于是OpenCV方法提供了drawContours()方法專門用來繪制這些輪廓。??
drawContours()方法的語法如下:
image = cv2.drawContours(image,contours,contourIdx,color,thickness,lineType,hierarchy,maxLevel,offse)
參數(shù)說明:
image:被繪制輪廓的原始圖像,可以是多通道圖像。
contours:findContours()方法得出的輪廓列表。
contourIdx:繪制輪廓的索引,如果為-1則繪制所有輪廓。
color:繪制顏色,使用RGB格式。
thickness:可選參數(shù),畫筆的粗細(xì)程度,如果該值為-1則繪制實(shí)心輪廓。
lineType:可選參數(shù),繪制輪廓的線型。
hierarchy:可選參數(shù),findContours()方法得出的層次關(guān)系。
maxLevel:可選參數(shù),繪制輪廓的層次深度,最深繪制第maxLevel層。
offse:可選參數(shù),偏移量,可以改變繪制結(jié)果的位置。
返回值說明:
image:同參數(shù)中的image,方法執(zhí)行后原始圖像中就包含繪制的輪廓了,可以不使用此返回值保存結(jié)果。
案例1:
繪制幾何圖像的輪廓,具體代碼如下:
import cv2
img = cv2.imread("shape1.png") # 讀取原圖
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 彩色圖像轉(zhuǎn)為變成單通道灰度圖像
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 灰度圖像轉(zhuǎn)為二值圖像
# 檢測圖像中出現(xiàn)的所有輪廓,記錄輪廓的每一個(gè)點(diǎn)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
# 繪制所有輪廓,寬度為5,顏色為紅色
cv2.drawContours(img, contours, -1, (0, 0, 255), 5)
cv2.imshow("img", img) # 顯示繪制結(jié)果
cv2.waitKey() # 按下任何鍵盤按鍵后
cv2.destroyAllWindows() # 釋放所有窗體
運(yùn)行效果如圖所示:
案例2:
繪制花朵的輪廓。
繪制之前首先要降低圖像中的噪聲干擾,先進(jìn)行濾波處理,再將圖像處理成二值灰度圖像,并檢測出輪廓,再利用繪制輪廓的方法在原始圖像中繪制輪廓。??
具體代碼如下:
import cv2
img = cv2.imread("flower.jpg") # 讀取原圖
cv2.imshow("img", img) # 顯示原圖
img = cv2.medianBlur(img, 5) # 使用中值濾波去除噪點(diǎn)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 原圖從彩圖變成單通道灰度圖像
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 灰度圖像轉(zhuǎn)化為二值圖像
cv2.imshow("binary", binary) # 顯示二值化圖像
# 獲取二值化圖像中的輪廓極輪廓層次數(shù)據(jù)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
cv2.drawContours(img, contours, -1, (0, 0, 255), 2) # 在原圖中繪制輪廓
cv2.imshow("contours", img) # 顯示繪有輪廓的圖像
cv2.waitKey() # 按下任何鍵盤按鍵后
cv2.destroyAllWindows() # 釋放所有窗體
運(yùn)行效果如圖所示:
??2.輪廓的擬合
擬合,是指將平面上的一系列點(diǎn),用一條光滑的曲線連接起來。輪廓的擬合就是將凹凸不平的輪廓用平整的幾何圖形體現(xiàn)出來。
下面就為大家介紹如何按照輪廓繪制矩形包圍框和圓形包圍框。??
????2.1 矩形包圍框
矩形包圍框是指圖像輪廓的最小矩形邊界。OpenCV提供的boundingRect()方法可以自動(dòng)計(jì)算出輪廓最小矩形邊界的坐標(biāo)和寬高。??
boundingRect()方法的語法如下:
retval = cv2.boundingRect(array)
參數(shù)說明:
array:輪廓數(shù)組
返回值說明:
retval:元組類型,包含四個(gè)整數(shù)值,分別是最小矩形包圍框左上角頂點(diǎn)的橫坐標(biāo)、左上角頂點(diǎn)的縱坐標(biāo)、矩形的寬和矩形的高。所以也可以寫成x,y,w,h = cv2.boundingRect(array)的形式。
案例:
為爆炸圖形繪制矩形包圍框。具體代碼如下:
import cv2
img = cv2.imread("shape2.png") # 讀取原圖
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 從彩色圖像變成單通道灰度圖像
# 將灰度圖像進(jìn)行二值化閾值處理
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 獲取二值化圖像中的輪廓極輪廓層次數(shù)據(jù)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
x, y, w, h = cv2.boundingRect(contours[0]) # 獲取第一個(gè)輪廓的最小矩形邊框,記錄坐標(biāo)和寬高
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2) # 繪制紅色矩形
cv2.imshow("img", img) # 顯示繪制結(jié)果
cv2.waitKey() # 按下任何鍵盤按鍵后
cv2.destroyAllWindows() # 釋放所有窗體
運(yùn)行效果如圖所示:
????2.2?圓形包圍框
圓形包圍框與矩形包圍框同理,是圖像輪廓的最小圓形邊界。OpenCV提供的minEnclosingCircle()方法可以自動(dòng)計(jì)算出輪廓最小圓形邊界的圓心和半徑。
minEnclosingCircle()方法的語法格式如下:
center,radius = cv2.minEnclosingCircle(points)
參數(shù)說明:
points:輪廓數(shù)組
返回值說明:
center:元組類型,包含兩個(gè)浮點(diǎn)值,是最小圓形包圍框圓心的橫坐標(biāo)和縱坐標(biāo)。
radius:浮點(diǎn)類型,最小圓形包圍框的半徑。
案例:
為爆炸圖形繪制圓形包圍框。具體代碼如下:
import cv2
img = cv2.imread("shape2.png") # 讀取原圖
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 從彩色圖像變成單通道灰度圖像
# 將灰度圖像進(jìn)行二值化閾值處理
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 獲取二值化圖像中的輪廓極輪廓層次數(shù)據(jù)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
center, radius = cv2.minEnclosingCircle(contours[0]) # 獲取最小圓形邊框的圓心點(diǎn)和半徑
x = int(round(center[0])) # 圓心點(diǎn)橫坐標(biāo)轉(zhuǎn)為近似整數(shù)
y = int(round(center[1])) # 圓心點(diǎn)縱坐標(biāo)轉(zhuǎn)為近似整數(shù)
cv2.circle(img, (x, y), int(radius), (0, 0, 255), 2) # 繪制圓形
cv2.imshow("img", img) # 顯示繪制結(jié)果
cv2.waitKey() # 按下任何鍵盤按鍵后
cv2.destroyAllWindows() # 釋放所有窗體
?運(yùn)行效果如圖所示:
??3.Canny邊緣檢測
Canny邊緣檢測算法是John F.Canny 于1986年開發(fā)出來的一個(gè)多級邊緣檢測算法,該算法根據(jù)像素的梯度變化尋找圖像邊緣,最終可以繪制出十分精細(xì)的二值邊緣圖像。??
OpenCV將Canny邊緣檢測算法封裝在Canny()方法中,該方法的語法如下:
edgrs = cv2.Canny(image,threshold1,threshold2,apertureSize,L2gradient)
參數(shù)說明:
image:檢測的原始圖像
threshold1:計(jì)算過程中使用的第一個(gè)閾值,可以是最小閾值,也可以是最大閾值,通常用來設(shè)置最小閾值。
threshold2:計(jì)算過程中使用的第二個(gè)閾值,通常用來設(shè)置最大閾值。
apertureSize:可選參數(shù),Sobel算子的孔徑大小。
L2gradient:可選參數(shù),計(jì)算圖像梯度的標(biāo)識(shí),默認(rèn)值為False。值為True時(shí)會(huì)采用更精準(zhǔn)的算法進(jìn)行計(jì)算。
返回值說明:
edges:計(jì)算后得出的邊緣圖像,是一個(gè)二值灰度圖像。
說明:??????
在開發(fā)過程中可以通過調(diào)整最小閾值和最大閾值來控制邊緣檢測的精細(xì)程度。當(dāng)兩個(gè)閾值都較小的時(shí)候,會(huì)檢測出更多的細(xì)節(jié);當(dāng)兩個(gè)閾值都較大的時(shí)候,會(huì)忽略較多的細(xì)節(jié)。
案例:
使用Canny算法檢測美女圖像,具體代碼如下:
import cv2
img = cv2.imread("1.webp") # 讀取原圖
r1 = cv2.Canny(img, 10, 50); # 使用不同的閾值進(jìn)行邊緣檢測
cv2.imshow("img", img) # 顯示原圖
cv2.imshow("r1", r1) # 顯示邊緣檢測結(jié)果
cv2.waitKey() # 按下任何鍵盤按鍵后
cv2.destroyAllWindows() # 釋放所有窗體
運(yùn)行效果如圖所示:
??4.霍夫變換
?霍夫變換是一種特征檢測,通過算法識(shí)別圖像的特征,從而判斷出圖像中的特殊形狀,例如直線和圓。下面就為大家介紹如何檢測圖像中的直線和圓。
????4.1?直線檢測
霍夫直線變換是通過霍夫坐標(biāo)系的直線與笛卡爾坐標(biāo)系的點(diǎn)之間的映射關(guān)系來判斷圖像中的點(diǎn)是否構(gòu)成直線。OpenCV將此封裝成了兩個(gè)方法,分別是cv2.HoughLines()方法和
cv2.HoughLinesP()方法,前者用于檢測無線延長的直線,后者用于檢測線段。??
本節(jié)就介紹比較常用的HoughLinesP()方法。
HoughLinesP()方法名稱最后有一個(gè)大寫的P,該方法只能檢測二值灰度圖像,也就是只有兩種像素值的黑白圖像。方法最后會(huì)把找出的所有線段的兩個(gè)端點(diǎn)坐標(biāo)保存成一個(gè)數(shù)組。
HoughLinesP()方法的語法如下:
lines = cv2.HoughLinesP(image,rho,theta,threshold,minLineLength,maxLineGap)
參數(shù)說明:
image:檢測的原始圖像
rho:檢測直線使用的半徑步長,值為1時(shí),表示檢測所有可能的半徑步長。
theta:搜索直線的角度,值為π/180時(shí),表示檢測的所有角度。
threshold:閾值,該值越小,檢測的直線就越多。
minLineLength:線段的最小長度,小于該長度的直線不會(huì)記錄到結(jié)果中。
maxLineGap:線段之間的最小距離。
返回值說明:
lines:一個(gè)數(shù)組,元素為所有檢測出的線段,每個(gè)線段也是一個(gè)數(shù)組,內(nèi)容為線段兩個(gè)端點(diǎn)的橫縱坐標(biāo),格式為[[[x1,y1,x2,y2],[x1,y1,x2,y2]]]。
說明:?????????????
使用該方法前需要先為原始圖像進(jìn)行降噪處理,否則會(huì)影響檢測結(jié)果。
案例:
檢測筆圖像中出現(xiàn)的直線,具體代碼如下:
import cv2
import numpy as np
img = cv2.imread("pen.jpg") # 讀取原圖
o = img.copy() # 復(fù)制原圖
o = cv2.medianBlur(o, 5) # 使用中值濾波進(jìn)行降噪
gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY) # 從彩色圖像變成單通道灰度圖像
binary = cv2.Canny(o, 50, 150) # 繪制邊緣圖像
# 檢測直線,精度為1,全角度,閾值為15,線段最短100,最小間隔為18
lines = cv2.HoughLinesP(binary, 1, np.pi / 180, 15, minLineLength=100, maxLineGap=18)
for line in lines: # 遍歷所有直線
x1, y1, x2, y2 = line[0] # 讀取直線兩個(gè)端點(diǎn)的坐標(biāo)
cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) # 在原始圖像上繪制直線
cv2.imshow("canny", binary) # 顯示二值化邊緣圖案
cv2.imshow("img", img) # 顯示繪制結(jié)果
cv2.waitKey() # 按下任何鍵盤按鍵后
cv2.destroyAllWindows() # 釋放所有窗體
運(yùn)行效果如圖所示:
????4.2?圓環(huán)檢測
霍夫圓環(huán)變換的原理與霍夫直線變換類似。OpenCV提供的HoughCircle()方法用于檢測圖像中的圓,該方法在檢測過程中進(jìn)行兩輪篩選:第一輪篩選會(huì)找出可能的是圓的圓心坐標(biāo),第二輪篩選會(huì)計(jì)算出這些圓心坐標(biāo)可能的對應(yīng)的半徑長度。方法最后會(huì)將圓心坐標(biāo)和半徑長度封裝成一個(gè)浮點(diǎn)型數(shù)組。??
HoughCircle()方法的語法格式如下:
circles = cv2.HoughCircle(image,method,dp,minDist,param1,param2,minRadius,maxRadius)
參數(shù)說明:
image:檢測的原始圖像
method:檢測方法
dp:累加器分辨率與原始圖像分辨率之比的倒數(shù)。值為1時(shí),累加器與原始圖像具有相同的分辨率;值為2時(shí),累加器的分辨率為原始圖像的1/2。通常使用1作為參數(shù)。
minDist:圓心之間的最小距離
param1:可選參數(shù),Canny邊緣檢測使用的最大閾值。
param2:可選參數(shù),檢測圓環(huán)結(jié)果的投票數(shù)。第一輪篩選時(shí)投票數(shù)超過該值的圓才會(huì)進(jìn)入第二輪篩選。值越大,檢測出的圓越小,但越精準(zhǔn)。
minRadius:可選參數(shù),圓的最小半徑。
maxRadius:可選參數(shù),圓的最大半徑。
返回值說明:
circles:一個(gè)數(shù)組,元素為所有檢測出的圓,每個(gè)圓也是一個(gè)數(shù)組,內(nèi)容為圓心的橫、縱坐標(biāo)和半徑長度,格式為[[[x1,y1,r1],[x2,y2,r2]]]。
說明:????????????????????
使用該方法前需要先為原始圖像進(jìn)行降噪處理,否則會(huì)影響檢測結(jié)果。
案例:
繪制硬幣圖像的圓環(huán)和對應(yīng)圓心,具體代碼如下:
import cv2
import numpy as np
img = cv2.imread("coin.jpg") # 讀取原圖
o = img.copy() # 復(fù)制原圖
o = cv2.medianBlur(o, 5) # 使用中值濾波進(jìn)行降噪
gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY) # 從彩色圖像變成單通道灰度圖像
# 檢測圓環(huán),圓心最小間距為70,Canny最大閾值為100,投票數(shù)超過25。最小半徑為10,最大半徑為50
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 70, param1=100, param2=25, minRadius=10, maxRadius=50)
circles = np.uint(np.around(circles)) # 將數(shù)組元素四舍五入成整數(shù)
for c in circles[0]: # 遍歷圓環(huán)結(jié)果
x, y, r = c # 圓心橫坐標(biāo)、縱坐標(biāo)和圓半徑
cv2.circle(img, (x, y), r, (0, 0, 255), 3) # 繪制圓環(huán)
cv2.circle(img, (x, y), 2, (0, 0, 255), 3) # 繪制圓心
cv2.imshow("img", img) # 顯示繪制結(jié)果
cv2.waitKey() # 按下任何鍵盤按鍵后
cv2.destroyAllWindows() # 釋放所有窗體
運(yùn)行效果如圖所示:
??5.總結(jié)
總結(jié):
??(1)圖像的輪廓:先對圖像做二值化處理,cv2.findContours()檢測輪廓,cv2.drawContours()繪制輪廓。
??(2)輪廓的擬合:包括矩形包圍框和圓形包圍框。
??(3)Canny邊緣檢測:最實(shí)用、最簡單、效果最好的邊緣檢測方法。閾值越小,邊緣越多。
??(4)霍夫變換:包括直線檢測和圓環(huán)檢測。其中,直線檢測是檢測之前先降噪,再做二值化閾值處理,圓環(huán)檢測是檢測之前先降噪,再轉(zhuǎn)為單通道灰度圖像。文章來源:http://www.zghlxwxcb.cn/news/detail-676458.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-676458.html
到了這里,關(guān)于OpenCV基礎(chǔ)知識(shí)(8)— 圖形檢測的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!