<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
圖形檢測在計算機視覺開發中是一項非常重要的操作,演演算法通過對影象的檢測,分析出影象中可能存在哪些形狀。除此之外,除了讓計算機識別輪廓之外,輪廓也需要讓人看到,這就需要再分別讀這些輪廓的形狀進行描繪。
cv2.findContours() & cv2.drawContours() 方法
在Python中OpenCV提供了findContours() 方法來判斷影象的輪廓,drawContours()方法來繪製輪廓。
cv2.findComtours()方法的語法如下
cv2.contours, hierarchy = findContours(image, mode, method)
其中
contours是一個列表,列表的每一個元素都是由某個輪廓的畫素的座標組成的陣列。
hierarchy是輪廓與輪廓之間的層次關係。
mode取值表
mode值 | 描述 |
---|---|
cv2.RETR_EXTERNAL | 只檢測外輪廓 |
cv2.RETR_LIST | 檢測所有輪廓,但不建立層次關係 |
cv2.RETR_CCOMP | 檢測所有輪廓,並建立兩級層次關係 |
cv2.RETR_TREE | 建立所有輪廓,並建立樹狀結構的層次關係 |
method取值表
cv2.PATH_APPROX_ | 儲存輪廓上所有點 |
---|---|
cv2.PATH_APPROX_NONE | 只儲存水平、垂直或對角線輪廓的端點 |
cv2.PATH_APPROX_SIMPLE | Ten-Chinl |
cv2.PATH_APPROX_TC89_L1 | Ten-Chinl近似演演算法的一種 |
cv2.PATH_APPROX_TC89_KCOS | Ten-Chinl近似演演算法的一種 |
cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)
drawContours() 方法返回的是一個影象(陣列)。
以隊此小鳥圖操作為例(test1.jpg):
import cv2 img = cv2.imread("test1.jpg") # 彩色影象轉為變成單通道灰度影象 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化處理 t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 檢測影象中出現的所有輪廓,記錄輪廓的每一個點 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) cv2.waitKey() cv2.destroyAllWindows()
程式執行結果展示如下,圖中所有能夠識別出的輪廓被描出:
輪廓擬合,即,將凹凸不平的輪廓用平整的幾何圖形體現出來。這裡展示使用矩形和圓形擬合兩種方法。
在Python中OpenCV提供了cv2.boundingRect()來計算輪廓的最小矩形邊界的座標 ,其語法如下
retval = cv2.boundingRect(array)
其中引數array為輪廓陣列。即,cv2.findComtours()方法的執行結果中的contours中的元素。
返回值retval是一個包含著四個整數值的元組,四個值依次是左上角頂點的橫座標,左上角頂點的縱座標,矩形的寬,矩形的高。
常常也可以寫成x,y,w,h = retval = cv2.boundingRect(array)
還以這張小鳥圖片(test1.jpg)為例,在上一個部分的範例中,我們找出並繪製出了圖中所有的輪廓,經過偵錯,發現被識別出的輪廓共有94個。
我們要從陣列列表中,選擇出表示小鳥輪廓的位置的陣列。
從上圖中可以看出,小鳥的輪廓是所有輪廓中最大的。即該陣列的 shape[0] 最大。即我們只用找出 shape[0]最大的即可。
import cv2 img = cv2.imread("test1.jpg") # 從彩色影象變成單通道灰度影象 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 將灰度影象進行二值化閾值處理 t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 獲取二值化影象中的輪廓極輪廓層次資料 contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) # 找出小鳥的輪廓 n1 = 1 n2 = 0 index = 0 for arr in contours: if len(arr) > n1: n1 = len(arr) index = n2 n2 += 1 print(index) x, y, w, h = cv2.boundingRect(contours[index]) # 繪製紅色矩形 cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2) cv2.imshow("img", img) cv2.waitKey() cv2.destroyAllWindows()
繪製出矩形包圍框效果如下:
在Python中OpenCV提供了cv2.minEnclosingCircle()來計算輪廓的最小圓形邊界的圓心和半徑 ,其語法如下
center,radius = minEnclosingCircle(points)
其中
同樣的演演算法,只是這次呼叫cv2.minEnclosingCircle()方法,其他不變:
import cv2 img = cv2.imread("test1.jpg") # 讀取原圖 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 從彩色影象變成單通道灰度影象 # 將灰度影象進行二值化閾值處理 t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 獲取二值化影象中的輪廓極輪廓層次資料 contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) n1 = 1 n2 = 0 index = 0 for arr in contours: if len(arr) > n1: n1 = len(arr) index = n2 n2 += 1 center, radius = cv2.minEnclosingCircle(contours[index]) # 圓心點橫座標轉為近似整數 x = int(round(center[0])) # 圓心點縱座標轉為近似整數 y = int(round(center[1])) cv2.circle(img, (x, y), int(radius), (0, 0, 255), 2) cv2.imshow("img", img) cv2.waitKey() cv2.destroyAllWindows()
繪製出圓形包圍框效果如下(因為尺寸問題,只畫出了一部分):
使用矩形框和圓形框對圖形的貼合程度往往都會較差。為了提高這個貼合程度,我們可以使用“凸包”。
所謂凸包,就是最逼近輪廓的多邊形。
在Python中OpenCV提供了 cv2.bonvexHull()方法來計算凸包
cv2.bonvexHull()方法語法如下:
hull = convexHull(points, clockwise=None, returnPoints=None)
其中
返回值hull是凸包的點陣陣列
依然以“test1.jpg為例”,為圖中的小鳥繪製凸包:
import cv2 img = cv2.imread("test1.jpg") # 轉為灰度影象 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化閾值處理 ret, binary = cv2.threshold(gray, 127, 225, cv2.THRESH_BINARY) # 檢測影象中出現的所有輪廓 contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) n1 = 1 n2 = 0 index = 0 for arr in contours: if len(arr) > n1: n1 = len(arr) index = n2 n2 += 1 hull = cv2.convexHull(contours[index]) cv2.polylines(img, [hull], True, (0, 0, 255), 2) cv2.imshow("img", img) cv2.waitKey() cv2.destroyAllWindows()
Canny邊緣檢測演演算法是John F.Canny在1986年開發的一個多級邊緣檢測演演算法。
Canny邊緣檢測演演算法通過畫素的梯度變化尋找影象的邊緣,最終可以繪製出十分精細的二值邊緣影象
edges = cv2.Canny(image, threshold1, threshold2, apertureSize=None, L2gradient=None)
其中
關於這兩個閾值怎麼用,這涉及到了演演算法的底層邏輯,還請自行探索。這裡一種可以接受的解釋是:低於閾值1的畫素點,會被認為不構成邊緣,而高於閾值2的畫素點,會被認為構成邊緣。
最後返回值edges是一個二值的灰度影象。
下邊對test1.jpg以三組不同的閾值來做Canny邊緣檢測,根據處理結果感受演演算法效果:
- 當閾值為 10-50 時
import cv2 img = cv2.imread("test1.jpg") r1 = cv2.Canny(img, 10, 50) cv2.imshow("r1", r1) cv2.waitKey() cv2.destroyAllWindows()
- 當閾值為100-200時
import cv2 img = cv2.imread("test1.jpg") r2 = cv2.Canny(img, 100, 200) cv2.imshow("r2", r2) cv2.waitKey() cv2.destroyAllWindows()
- 當閾值為400-600時
import cv2 img = cv2.imread("test1.jpg") r3 = cv2.Canny(img, 400, 600) cv2.imshow("r3", r3) cv2.waitKey() cv2.destroyAllWindows()
霍夫變換是一種特徵檢測,通過霍夫變換可以檢測出影象中存在的特殊的形狀。比如,直線,圓等。
霍夫變換檢測直線時,演演算法有兩個,
一個是cv2.HoughLines() 方法,用於檢測無限延長的直線;
另一個是cv2.HoughLinesP() 方法,用於檢測線段。
霍夫變換檢測圓,使用的是**cv2.HoughCircles()**方法。
使用這三個方法前,都要先對影象進行降噪處理(使用濾波器),以去除干擾。
cv2.HoughLines()語法如下:
lines = cv.HoughLines( image, rho, theta, threshold[,srn][,stn])
其中
返回值lines,是一個陣列,shape為(n, 1, 2),n表示檢測出的所有線段數目,每個線段用極座標(ρ, θ)表示。
以此跨海大橋圖(test2.jpg)為例,對其使用cv2.HoughLines()方法,並繪製直線:
import cv2 import numpy as np img = cv2.imread("test2.jpg") o = img.copy() # 使用中值濾波進行降噪 o = cv2.medianBlur(o, 5) # 從彩色影象變成單通道灰度影象 gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY) # 繪製邊緣影象 binary = cv2.Canny(o, 50, 150) # 檢測直線 不限步長,不限角度,至少50個點確定一條線 lines = cv2.HoughLines(binary, 1, np.pi / 180, 50) # print(lines) # print(lines.shape) for line in lines: rho, theta = line[0] a = np.cos(theta) b = np.sin(theta) x0 = a * rho y0 = b * rho x1 = int(x0 + 1000 * (-b)) y1 = int(y0 + 1000 * (a)) x2 = int(x0 - 1000 * (-b)) y2 = int(y0 - 1000 * (a)) cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imshow("img", img) cv2.waitKey() cv2.destroyAllWindows()
識別效果如下,可以自行調節引數進行改良,並在這個過程中具體感受每個引數的作用。
當選擇至少50個點確定一條線時,一共檢測出168根直線:
當選擇至少100個點確定一條線時,一共檢測出35根直線:
當選擇至少300個點確定一條直線時,符合要求的直線有3根:
當選擇至少380個點確定一條直線時,這樣的直線還剩一根:
相比檢測直線,檢測線段的cv2.HoughLinesP()相對要更常用些。
lines = cv2.HoughLinesP(image, rho, theta, threshold, minLineLength=None, maxLineGap=None)
檢測線段
返回值lines,是一個陣列,shape為(n, 1, 4),n表示檢測出的所有線段數目,4指的是每個線段的兩端端點的笛卡爾座標(x, y) 座標的四個點。
其中minLineLength(最小線段長度)和maxLineGap(最小線段距離)兩個引數,都是越大,識別的線段越少。
import cv2 import numpy as np img = cv2.imread("test2.jpg") o = img.copy() # 使用中值濾波進行降噪 o = cv2.medianBlur(o, 5) # 從彩色影象變成單通道灰度影象 gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY) # 繪製邊緣影象 binary = cv2.Canny(o, 50, 150) # 檢測線段,不限步長,不限角度,至少100個點確定一條線。最大將距離為200的線段連城一條線。 lines = cv2.HoughLinesP(binary, 1, np.pi / 180, 50, minLineLength=100, maxLineGap=200) print(lines.shape) for line in lines: x1, y1, x2, y2 = line[0] cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imshow("canny", binary) cv2.imshow("img", img) cv2.waitKey() cv2.destroyAllWindows()
二值化邊緣圖案效果:
描繪線段效果(minLineLength=100)至少100個點確定一條線段(上邊程式碼),最大將距離為200的線段連線起來
共描繪了23條線:
描繪線段效果(minLineLength=500)至少500個點確定一條線段,最大將距離為200的線段連線起來
共描繪了6條線段:
描繪線段效果(minLineLength=720)至少720個點確定一條線段,最大將距離為200的線段連線起來
共描繪了一條線:
circles = HoughCircles(image, method, dp, minDist, circles=None, param1=None, param2=None, minRadius=None, maxRadius=None)
其中
返回值circles是一個陣列,陣列內是所有檢測出的圓環,shape為(n,1,3)。其中3表示圓心的x座標,圓心的y座標和半徑長度三個指標。
瞭解完語法,
接下來我們來檢測下圖(test3.jpg)中的客家土樓中的圓形。
import cv2 import numpy as np img = cv2.imread("test3.jpg") # 使用中值濾波進行降噪 o = cv2.medianBlur(img, 11) # 從彩色影象變成單通道灰度影象 gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY) # 展示灰度影象 cv2.imshow('gray', gray) # 檢測圓環,圓心最小間距為50,Canny最大閾值為40,投票數超過63。最小半徑為10,最大半徑為50 circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 50, param1=40, param2=63, minRadius=10, maxRadius=100) # 將陣列元素四捨五入成整數 circles = np.uint(np.around(circles)) # 遍歷圓環結果 for c in circles[0]: # 圓心橫座標、縱座標和圓半徑 x, y, r = c # 繪製圓環 cv2.circle(img, (x, y), r, (0, 0, 255), 3) # 繪製圓心 cv2.circle(img, (x, y), 2, (0, 0, 255), 3) cv2.imshow("img", img) cv2.waitKey() cv2.destroyAllWindows()
降過噪的灰度影象如下:
識別結果呈現如下,如圖成功識別出了圖中所有土樓的圓形:
以上就是Python OpenCV實現圖形檢測範例詳解的詳細內容,更多關於Python OpenCV圖形檢測的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45