opencv 圖像輪廓的實(shí)現(xiàn)示例
圖像輪廓
Contours:輪廓
輪廓是將沒有連著一起的邊緣連著一起。
邊緣檢測(cè)檢測(cè)出邊緣,邊緣有些未連接在一起。

注意問題
1.對(duì)象為二值圖像,首先進(jìn)行閾值分割或者邊緣檢測(cè)。
2.查找輪廓需要更改原始圖像,通常使用原始圖像的一份進(jìn)行拷貝。
3.在opencv里,是從黑色背景里找白色。因此對(duì)象必須是白色,背景為黑色。
方法
- cv2.findContours()
- cv2.drawContours()
通過cv2.findContours() 查找輪廓在哪里,再通過 cv2.drawContours()將查找的輪廓繪制出來。
contours,hierarchy=cv2.findContours(image,mode,method)
contours:輪廓
hierarchy:圖像的拓?fù)湫畔ⅲㄝ喞獙哟危ù鎯?chǔ)上一個(gè)輪廓,父輪廓…)
image:原始圖像
mode:輪廓檢索方式
method:輪廓的近似方法


r=cv2.drawContours(image, contours, contourIdx, color[, thickness])
r:目標(biāo)圖像
image:原始圖像
contours: 所有的輸入輪廓邊緣數(shù)組
contourIdx :需要繪制的邊緣索引,如果全部繪制為-1。如果有多個(gè)目標(biāo),可以繪制第一個(gè)目標(biāo)0,第二個(gè)目標(biāo)1,第三個(gè)目標(biāo)2.。。
color:繪制的顏色,為BGR格式的SCalar
thickness:可選,繪制的密度,即輪廓的畫筆粗細(xì)
import cv2
import numpy as np
o = cv2.imread('lena256.bmp')
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)#BGR-灰度
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)#二值圖像
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
co=o.copy()#對(duì)原始圖像進(jìn)行繪制
r=cv2.drawContours(co,contours,-1,(0,127,127),4)#co為復(fù)制圖像,輪廓會(huì)修改原始圖像
cv2.imshow("original",o)
cv2.imshow("contours",r)
cv2.waitKey()

cv2.cvtColor(input_image, flag)用于顏色空間轉(zhuǎn)換。
input_image:需要轉(zhuǎn)換的圖像
flag:轉(zhuǎn)換類型
cv2.COLOR_BGR2GRAY : BGR -灰度
cv2.COLOR_BGR2RGB:BGR-RGB
cv2.COLOR_BGR2HSV:BGR-HSV
最小外接圓
函數(shù)cv2.minEnclosingCircle() 可以幫我們找到一個(gè)對(duì)象的外切圓。它是所有能夠包括對(duì)象的圓中面積最小的一個(gè)。
案例:現(xiàn)有下面這樣一張圖片,要求將圖片中心的花朵標(biāo)記出來。

代碼:
import numpy as np
import cv2 as cv
img=cv.imread("image.jpg",0)
#為了顯示方便,這里將圖片進(jìn)行縮放
x,y=img.shape
img=cv.resize(img,(y//2,x//2))
#將圖片二值化,由于前景物體是黑色的,因此在二值化時(shí)采用cv.THRESH_TOZERO_INV這種方式
ret,thresh=cv.threshold(img,127,255,cv.THRESH_TOZERO_INV)
#尋找圖片中的輪廓,mode=cv.RETR_EXTERNAL,這是為了尋找最外層的輪廓
im,contour,hierarchy=cv.findContours(thresh,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
#cv.minEnclosingCircle函數(shù)的參數(shù)要求是ndarray類型,因此這里將找到的
# 輪廓中的所有的點(diǎn)存放在一個(gè)列表中,然后使用這個(gè)列表創(chuàng)建數(shù)組
point_list=[]
for i in contour:
for j in i:
point_list.append(j[0])
point_array=np.array(point_list)
#使用最小外接圓函數(shù),返回值為這個(gè)圓的圓心坐標(biāo)和圓半徑長(zhǎng)度
(x,y),radius=cv.minEnclosingCircle(point_array)
#圖片上的坐標(biāo)均為整數(shù),圓的半徑也要求是整數(shù),因此將它們強(qiáng)制轉(zhuǎn)換為int類型
center=(int(x),int(y))
color=cv.cvtColor(img,cv.COLOR_GRAY2BGR)
color=cv.circle(color,center,radius=int(radius),color=(0,0,255),thickness=2)
#顯示圖片
cv.imshow("color",color)
cv.waitKey(0)
cv.destroyAllWindows()
程序結(jié)果:

凸包
凸包與輪廓近似相似,但不同,雖然有些情況下它們給出的結(jié)果是一樣的。函數(shù)cv2.convexHull() 可以用來檢測(cè)一個(gè)曲線是否具有凸性缺陷,并能糾正缺陷。一般來說,凸性曲線總是凸出來的,至少是平的。在opencv中使用函數(shù)cv.convexhull來尋找輪廓的凸包,該函數(shù)的定義為:
hull=cv.convexHull( points[, hull[, clockwise[, returnPoints]]])
這個(gè)函數(shù)的參數(shù)如下:
Points:我們需要傳入的輪廓
Hull:輸出,通常不需要
clockwise: 取向標(biāo)志,如果為True,凸包的方向是順時(shí)針方向,否則為逆時(shí)針方向;
returnPoints: 默認(rèn)為True. 它會(huì)返回凸包上點(diǎn)的坐標(biāo)。如果設(shè)置為False,就會(huì)返回與凸包點(diǎn)對(duì)應(yīng)的輪廓上的點(diǎn)。
還是上面的這副圖片,我們對(duì)上面的代碼稍加修改,可以得到凸包的形狀,代碼如下:
import numpy as np
import cv2 as cv
img=cv.imread("image.jpg",0)
#為了顯示方便,這里將圖片進(jìn)行縮放
x,y=img.shape
img=cv.resize(img,(y//2,x//2))
#將圖片二值化,由于前景物體是黑色的,因此在二值化時(shí)采用cv.THRESH_TOZERO_INV這種方式
ret,thresh=cv.threshold(img,127,255,cv.THRESH_TOZERO_INV)
#尋找圖片中的輪廓,mode=cv.RETR_EXTERNAL,這是為了尋找最外層的輪廓
im,contour,hierarchy=cv.findContours(thresh,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
#cv.minEnclosingCircle函數(shù)的參數(shù)要求是ndarray類型,因此這里將找到的
# 輪廓中的所有的點(diǎn)存放在一個(gè)列表中,然后使用這個(gè)列表創(chuàng)建數(shù)組
point_list=[]
for i in contour:
for j in i:
point_list.append(j[0])
point_array=np.array(point_list)
#尋找凸包,返回值是凸包上的點(diǎn)
hull=cv.convexHull(point_array,returnPoints=True)
color=cv.cvtColor(img,cv.COLOR_GRAY2BGR)
#將凸包繪制出來,需要注意的是:這里需要將凸包上點(diǎn)的坐標(biāo)寫成一個(gè)
#列表傳入函數(shù)cv.ploylines,否則繪制出來的只是凸包上的一系列點(diǎn)
color=cv.polylines(color,[hull],True,(0,0,255),2)
#顯示圖片
cv.imshow("color",color)
cv.waitKey(0)
cv.destroyAllWindows()
程序運(yùn)行結(jié)果為:

圖像掩模和像素點(diǎn)
有時(shí)我們需要構(gòu)成對(duì)象的所有像素點(diǎn),我們可以將圖像的所有輪廓提取出來,然后使用函數(shù)cv.drawContours()將輪廓內(nèi)的區(qū)域填充為指定的顏色。然后使用cv.findNonZeros()函數(shù)將非零像素點(diǎn)的坐標(biāo)提取出來,這樣就得到了構(gòu)成對(duì)象的像素點(diǎn)。我們還是在上面的圖片上進(jìn)行操作,代碼如下:
import numpy as np
import cv2 as cv
img=cv.imread("image.jpg",0)
#為了顯示方便,這里將圖片進(jìn)行縮放
x,y=img.shape
img=cv.resize(img,(y//2,x//2))
#將圖片二值化,由于前景物體是黑色的,因此在二值化時(shí)采用cv.THRESH_TOZERO_INV這種方式
ret,thresh=cv.threshold(img,127,255,cv.THRESH_TOZERO_INV)
#尋找圖片中的輪廓,mode=cv.RETR_EXTERNAL,這是為了尋找最外層的輪廓
im,contour,hierarchy=cv.findContours(thresh,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
#創(chuàng)建一個(gè)填充輪廓內(nèi)像素點(diǎn)的畫板,背景顏色為黑色,這里我們使用numpy創(chuàng)建一個(gè)全零的二維數(shù)組
mask=np.zeros(img.shape,dtype=np.uint8)
#將參數(shù)thickness設(shè)置為-1,這樣cv.drawContours函數(shù)就會(huì)將輪廓內(nèi)的像素點(diǎn)填充為指定的顏色
mask=cv.drawContours(mask,contour,contourIdx=-1,color=(255,255,255),thickness=-1)
#尋找mask內(nèi)非零像素點(diǎn),將其存放為一個(gè)numpy數(shù)組
NonZeroPoints=np.array(cv.findNonZero(mask))
#形狀變換,將其改變?yōu)橐粋€(gè)二維數(shù)組,數(shù)組的每一行存放一個(gè)非零像素點(diǎn)的坐標(biāo)
NonZeroPoints=NonZeroPoints.reshape((-1,2))
#驗(yàn)證我們提取出來的像素點(diǎn)坐標(biāo)是否正確,我們使用變量
#column和row分別存放非零像素點(diǎn)在圖像中坐標(biāo)的列數(shù)和行數(shù)
column=NonZeroPoints[:,0]
row=NonZeroPoints[:,1]
#在新的畫板上將這些點(diǎn)繪制出來,將這些坐標(biāo)對(duì)應(yīng)的像素點(diǎn)的值設(shè)為255
mask1=np.zeros(img.shape)
mask1[row,column]=255
#顯示結(jié)果
cv.imshow("mask",mask)
cv.imshow("mask1",mask1)
cv.waitKey(0)
cv.destroyAllWindows()
程序運(yùn)行結(jié)果:

通過上面兩幅圖的對(duì)比結(jié)果,我們可以看到:對(duì)象的組成像素點(diǎn)被正確地提取出來了。
到此這篇關(guān)于opencv 圖像輪廓的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)opencv 圖像輪廓內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python獲取Windows或Linux主機(jī)名稱通用函數(shù)分享
這篇文章主要介紹了Python獲取Windows或Linux主機(jī)名稱通用函數(shù)分享,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下2014-11-11
Python?實(shí)現(xiàn)多表和工作簿合并及一表按列拆分
這篇文章主要介紹了Python?實(shí)現(xiàn)多表和工作簿合并及一表按列拆分,文章圍繞主題展開詳細(xì)的資料介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-05-05
python部署chineseocr_lite的實(shí)現(xiàn)示例
本文主要介紹了python部署chineseocr_lite的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
python pandas消除空值和空格以及 Nan數(shù)據(jù)替換方法
今天小編就為大家分享一篇python pandas消除空值和空格以及 Nan數(shù)據(jù)替換方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-10-10
解決pycharm回車之后不能換行或不能縮進(jìn)的問題
今天小編就為大家分享一篇解決pycharm回車之后不能換行或不能縮進(jìn)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-01-01
Python 訪問限制 private public的詳細(xì)介紹
在一個(gè)模塊中,我們可能會(huì)定義很多函數(shù)和變量。這篇文章主要介紹了Python 訪問限制 private public的詳細(xì)介紹,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-10-10
Python網(wǎng)絡(luò)編程之Socket和HTTP協(xié)議詳解
在當(dāng)今互聯(lián)網(wǎng)時(shí)代,網(wǎng)絡(luò)編程是程序員不可或缺的一項(xiàng)技能,本文將介紹Python中兩種主要的網(wǎng)絡(luò)編程方式:Socket編程和基于HTTP協(xié)議的網(wǎng)絡(luò)編程,希望對(duì)大家有所幫助2024-04-04
python 3利用BeautifulSoup抓取div標(biāo)簽的方法示例
這篇文章主要介紹了python 3利用BeautifulSoup抓取div標(biāo)簽的方法,文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-05-05

