什么是物體輪廓
輪廓可以簡單地理解為連接所有連續(xù)點(diǎn)(沿物體邊界)的曲線,這些點(diǎn)通常具有相同的顏色或強(qiáng)度。 輪廓在圖像分析中具有重要意義,是物體形狀分析和對象檢測和識(shí)別的有用工具,是理解圖像語義信息的重要依據(jù)。
cv2.findContours
通常,為了提高物體輪廓檢測的準(zhǔn)確率,首先要將彩色圖像或者灰度圖像處理成二值圖像(黑白圖像)或者使用Canny邊緣檢測算法對原圖像進(jìn)行一次濾波處理,這樣可以在不丟失輪廓信息的前提下降低圖像語義信息的復(fù)雜度,更有助于我們準(zhǔn)確地分析物體輪廓。因此,在opencv里邊,尋找輪廓的過程更像是在黑色背景中尋找白色物體。
下邊是一段使用opencv-python里的cv2.findConttours()檢測物體輪廓的代碼。
import numpy as np
import cv2
im = cv2.imread('test.jpg')
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
從上邊的代碼中,我們可以看到cv2.findContours()有三個(gè)參數(shù):thresh、cv2.RETR_TREE、cv2.CHAIN_APPROX_SIMPLE。
參數(shù)說明:
- thresh:圖像數(shù)據(jù)(二值圖像或經(jīng)過Canny算法處理之后的圖像)
- cv2.RETR_TREE:輪廓檢索方式,還有cv2.RETR_LIST、cv2.RETR_EXTERNAL、cv2.RETR_CCOMP
- cv2.CHAIN_APPROX_SIMPLE:輪廓的估計(jì)方法,除此之外還有 cv2.CHAIN_APPROX_NONE
第二個(gè)參數(shù)指定的不同輪廓檢索方法有什么區(qū)別呢?
輪廓檢索方法 | 作用 |
---|---|
cv2.RETR_LIST | 這是最簡單的一種尋找方式,它不建立輪廓間的子屬關(guān)系,也就是所有輪廓都屬于同一層級(jí) |
cv2.RETR_TREE | 完整建立輪廓的層級(jí)從屬關(guān)系 |
cv2.RETR_EXTERNAL | 只尋找最高層級(jí)的輪廓 |
cv2.RETR_CCOMP | 把所有的輪廓只分為2個(gè)層級(jí),不是外層的就是里層的 |
詳情請參考 cv2.findContours()的輪廓層級(jí)關(guān)系.
前邊說了物體輪廓是具有相同灰度值的形狀的邊界。它是以形狀邊界上的點(diǎn)的坐標(biāo)(x,y)儲(chǔ)存的,但是cnts里邊是儲(chǔ)存了邊界上所有點(diǎn)的坐標(biāo)嗎?還是只儲(chǔ)存了個(gè)別點(diǎn)的坐標(biāo)?這是由第三個(gè)參數(shù)輪廓的估計(jì)方法指定的。如果傳遞 cv2.CHAIN_APPROX_NONE,則存儲(chǔ)所有邊界點(diǎn)。 但實(shí)際上我們需要所有的點(diǎn)嗎? 例如,您找到了一條直線的輪廓。 你需要線上的所有點(diǎn)來代表那條線嗎? 不,我們只需要那條線的兩個(gè)端點(diǎn)。 這就是 cv.CHAIN_APPROX_SIMPLE 所做的。 它去除所有冗余點(diǎn)并壓縮輪廓,從而節(jié)省內(nèi)存。如圖1所示。
圖1. 不同輪廓估計(jì)方法的效果圖
cv2.findContours()返回了兩個(gè)變量:contours, hierarchy。
輸出變量說明:
- contours:一個(gè)包含了圖像中所有輪廓的list對象。其中每一個(gè)獨(dú)立的輪廓信息以邊界點(diǎn)坐標(biāo)(x,y)的形式儲(chǔ)存在numpy數(shù)組中。
- hierarchy:一個(gè)包含4個(gè)值的數(shù)組:[Next, Previous, First Child, Parent]。
Next:與當(dāng)前輪廓處于同一層級(jí)的下一條輪廓
Previous:與當(dāng)前輪廓處于同一層級(jí)的上一條輪廓
First Child:當(dāng)前輪廓的第一條子輪廓
Parent:當(dāng)前輪廓的父輪廓
因?yàn)橐话悴皇褂胔ierarchy,所以這里不討論輪廓的層級(jí)關(guān)系,想深入研究的朋友請移步:cv2.findContours()的輪廓層級(jí)關(guān)系.
cv2.drawContours
計(jì)算得到圖像中物體輪廓之后,我們需要將輪廓在圖像中繪制出來才能更直觀地體驗(yàn)到。這時(shí)候需要用到cv2.drawContours()方法。它的第一個(gè)參數(shù)是圖像,第二個(gè)參數(shù)是儲(chǔ)存輪廓信息的python 列表,第三個(gè)參數(shù)是輪廓的索引(在繪制單個(gè)輪廓時(shí)很有用。要繪制所有輪廓,傳遞 -1),其余參數(shù)是顏色、厚度 等等。
繪制檢索到的所有輪廓
cv.drawContours(img, contours, -1, (0,255,0), 3)
繪制檢索到的所有輪廓中的第四個(gè)
cv.drawContours(img, contours, 3, (0,255,0), 3)
但是更多時(shí)候我們使用下邊這種方法繪制單獨(dú)的某一個(gè)輪廓。
第二種方法繪制檢索到的所有輪廓中的第四個(gè)文章來源:http://www.zghlxwxcb.cn/news/detail-450975.html
cnt = contours[4]
cv.drawContours(img, [cnt], 0, (0,255,0), 3)
代碼示例
import cv2
import imutils
import numpy as np
# 讀取圖片
img_dir = r'C:\Users\Lei\Desktop\8.jpg'
img = cv2.imread(img_dir)
# 圖像預(yù)處理
img = imutils.resize(img, height=500)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
binary = cv2.Canny(gray, 30, 120)
# 輪廓檢索
contours, hierarchy = cv2.findContours(binary,
cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cv2.imshow('origin', img)
if cv2.waitKey(0) & 0xFF == ord('q'):
cv2.destroyWindow('origin')
cv2.imshow('binary', binary)
if cv2.waitKey(0) & 0xFF == ord('q'):
cv2.destroyWindow('binary')
# 輪廓過濾以及繪制
draw_img = img.copy()
for i in range(len(contours)):
# 篩掉面積過小的輪廓
area = cv2.contourArea(contours[i])
if area < 800:
continue
# 找到包含輪廓的最小矩形框
rect = cv2.minAreaRect(contours[i])
# 計(jì)算矩形框的四個(gè)頂點(diǎn)坐標(biāo)
box = cv2.boxPoints(rect)
box = np.int0(box)
# 繪制輪廓
cv2.drawContours(draw_img, [box], 0, (0, 0, 255), 5)
cv2.imshow('origin with contours', draw_img)
if cv2.waitKey(0) & 0xFF == ord('q'):
cv2.destroyWindow('origin with contours')
代碼中首先對讀取的RGB圖像(圖2)轉(zhuǎn)灰度圖,然后進(jìn)行高斯濾波去噪,再使用Canny算子進(jìn)行邊緣檢測得到黑白圖像(圖3)。對黑白圖像進(jìn)行輪廓檢索,檢索到的輪廓再根據(jù)cv2.contourArea()計(jì)算得到的面積大小進(jìn)行一次篩選,去掉因噪聲引起的檢測。根據(jù)檢測到的輪廓信息,使用cv2.minAreaRect()得到包含輪廓信息的最小矩形框rect,再使用cv2.boxPoints()計(jì)算出rect的四個(gè)頂點(diǎn)。最后,使用cv2.drawContours()繪制出rect(圖4)。
圖2. RGB原圖像
圖3. Canny算子得到的黑白圖像
圖4. 使用矩形框顯示輪廓檢測結(jié)果文章來源地址http://www.zghlxwxcb.cn/news/detail-450975.html
到了這里,關(guān)于opencv-python3 | cv2.findContours()檢測圖像中物體輪廓的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!