opencv 圖像輪廓的實現示例
圖像輪廓
Contours:輪廓
輪廓是將沒有連著一起的邊緣連著一起。
邊緣檢測檢測出邊緣,邊緣有些未連接在一起。

注意問題
1.對象為二值圖像,首先進行閾值分割或者邊緣檢測。
2.查找輪廓需要更改原始圖像,通常使用原始圖像的一份進行拷貝。
3.在opencv里,是從黑色背景里找白色。因此對象必須是白色,背景為黑色。
方法
- cv2.findContours()
- cv2.drawContours()
通過cv2.findContours() 查找輪廓在哪里,再通過 cv2.drawContours()將查找的輪廓繪制出來。
contours,hierarchy=cv2.findContours(image,mode,method)
contours:輪廓
hierarchy:圖像的拓撲信息(輪廓層次)(存儲上一個輪廓,父輪廓…)
image:原始圖像
mode:輪廓檢索方式
method:輪廓的近似方法


r=cv2.drawContours(image, contours, contourIdx, color[, thickness])
r:目標圖像
image:原始圖像
contours: 所有的輸入輪廓邊緣數組
contourIdx :需要繪制的邊緣索引,如果全部繪制為-1。如果有多個目標,可以繪制第一個目標0,第二個目標1,第三個目標2.。。
color:繪制的顏色,為BGR格式的SCalar
thickness:可選,繪制的密度,即輪廓的畫筆粗細
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()#對原始圖像進行繪制
r=cv2.drawContours(co,contours,-1,(0,127,127),4)#co為復制圖像,輪廓會修改原始圖像
cv2.imshow("original",o)
cv2.imshow("contours",r)
cv2.waitKey()

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

代碼:
import numpy as np
import cv2 as cv
img=cv.imread("image.jpg",0)
#為了顯示方便,這里將圖片進行縮放
x,y=img.shape
img=cv.resize(img,(y//2,x//2))
#將圖片二值化,由于前景物體是黑色的,因此在二值化時采用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函數的參數要求是ndarray類型,因此這里將找到的
# 輪廓中的所有的點存放在一個列表中,然后使用這個列表創(chuàng)建數組
point_list=[]
for i in contour:
for j in i:
point_list.append(j[0])
point_array=np.array(point_list)
#使用最小外接圓函數,返回值為這個圓的圓心坐標和圓半徑長度
(x,y),radius=cv.minEnclosingCircle(point_array)
#圖片上的坐標均為整數,圓的半徑也要求是整數,因此將它們強制轉換為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()
程序結果:

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

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

通過上面兩幅圖的對比結果,我們可以看到:對象的組成像素點被正確地提取出來了。
到此這篇關于opencv 圖像輪廓的實現示例的文章就介紹到這了,更多相關opencv 圖像輪廓內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python獲取Windows或Linux主機名稱通用函數分享
這篇文章主要介紹了Python獲取Windows或Linux主機名稱通用函數分享,本文直接給出實現代碼,需要的朋友可以參考下2014-11-11
python pandas消除空值和空格以及 Nan數據替換方法
今天小編就為大家分享一篇python pandas消除空值和空格以及 Nan數據替換方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10
Python 訪問限制 private public的詳細介紹
在一個模塊中,我們可能會定義很多函數和變量。這篇文章主要介紹了Python 訪問限制 private public的詳細介紹,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-10-10
Python網絡編程之Socket和HTTP協(xié)議詳解
在當今互聯(lián)網時代,網絡編程是程序員不可或缺的一項技能,本文將介紹Python中兩種主要的網絡編程方式:Socket編程和基于HTTP協(xié)議的網絡編程,希望對大家有所幫助2024-04-04
python 3利用BeautifulSoup抓取div標簽的方法示例
這篇文章主要介紹了python 3利用BeautifulSoup抓取div標簽的方法,文中給出了詳細的示例代碼供大家參考學習,對大家具有一定的參考學習價值,需要的朋友們下面來一起看看吧。2017-05-05

