輪廓與邊緣
輪廓:是一系列相連的點組成的曲線,代表了物體的基本外形
輪廓是連續的,可以用來分析物體的形態,比如物體的周長和麪積等,可以說邊緣包括輪廓。
邊緣並不全都連續
尋找輪廓的操作一般用於二值化圖,所以通常會使用閾值分割或Canny邊緣檢測先得到二值圖。
尋找輪廓是針對白色物體的,一定要保證物體是白色,而背景是黑色,不然很多人在尋找輪廓時會找到圖片最外面的一個框。
輪廓尋找方式
import numpy as np
import cv2
#讀取圖片
img = cv2.imread('doge.jpg')
#二值化,canny檢測
binaryImg = cv2.Canny(img,50,200)
#尋找輪廓
#也可以這麼寫:
#binary,contours, hierarchy = cv2.findContours(binaryImg,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
#這樣,可以直接用contours表示
h = cv2.findContours(binaryImg,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#提取輪廓
contours = h[0]
#打印返回值,這是一個元組
print(type(h))
#打印輪廓類型,這是個列表
print(type(h[1]))
#查看輪廓數量
print (len(contours))
#創建白色幕布
temp = np.ones(binaryImg.shape,np.uint8)*255
#畫出輪廓:temp是白色幕布,contours是輪廓,-1表示全畫,然後是顏色,厚度
cv2.drawContours(temp,contours,-1,(0,255,0),3)
cv2.imshow("contours",temp)
cv2.waitKey(0)
cv2.destroyAllWindows()
RetrievalModes:
- RETR_LIST:不建立輪廓間的子屬關係,也就是所有輪廓都屬於同一層級
不建立輪廓間的子屬關係,也就是所有輪廓都屬於同一層級
- RETR_TREE:完整建立輪廓的層級從屬關係
- RETR_EXTERNAL:只尋找最高層級的輪廓
- RETR_CCOMP:它把所有的輪廓只分爲2個層級,不是外層的就是裏層的
ContourApproximationModes:
- cv2.CHAIN_APPROX_NONE
存儲所有輪廓點。
- cv2.CHAIN_APPROX_SIMPLE
儘可能少的像素點表示輪廓
- cv2.CHAIN_APPROX_TC89_L1
應用THCH-鏈近似算法的一個特徵
- cv2.CHAIN_APPROX_TC89_KCOS
應用THCH-鏈近似算法的一個特徵
查找輪廓
import cv2
img = cv2.imread('doge.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
ret, thresh = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,contours,-1,(0,0,255),3)
cv2.imshow("img", img)
cv2.waitKey(0)
輪廓特徵
函數介紹
- cv2.contourArea()算面積,cv2.arcLength()算周長,cv2.boundingRect()算外接矩。
- cv2.minAreaRect()算最小外接矩,cv2.minEnclosingCircle()算最小外接圓。
- cv2.matchShapes()進行形狀匹配。
多邊形逼近
import cv2
import numpy as np
# 1.先找到輪廓
import cv2
import numpy as np
# 1.先找到輪廓
img = cv2.imread('hand.png', 0)
_, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
contours, hierarchy = cv2.findContours(thresh, 3, 2)
cnt = contours[0]
# 2.進行多邊形逼近,得到多邊形的角點
approx = cv2.approxPolyDP(cnt, 3, True)
# 3.畫出多邊形
image = cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR)
cv2.polylines(image, [approx], True, (0, 255, 0), 2)
cv2.imshow("img",image)
cv2.waitKey(0)
凸包
凸包跟多邊形逼近很像,只不過它是物體最外層的”凸”多邊形:集合A內連接任意兩個點的直線都在A的內部,則稱集合A是凸形的。
# 1.先找到輪廓
img = cv2.imread('convex.jpg', 0)
_, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
image, contours, hierarchy = cv2.findContours(thresh, 3, 2)
cnt = contours[0]
# 2.尋找凸包,得到凸包的角點
hull = cv2.convexHull(cnt)
# 3.繪製凸包
image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
cv2.polylines(image, [hull], True, (0, 255, 0), 2)
點到輪廓距離
dist = cv2.pointPolygonTest(cnt, (100, 100), True) # -3.53