網站建設公司有多少家百度上怎么免費開店
文章目錄
- 7. 圖像輪廓
- 7.1 什么是圖像輪廓
- 7.2 查找輪廓
- 7.3 繪制輪廓
- 7.4 輪廓的面積和周長
- 7.5 多邊形逼近與凸包
- 7.6 外接矩形
OpenCV官網
7. 圖像輪廓
7.1 什么是圖像輪廓
圖像輪廓是具有相同顏色或灰度的連續(xù)點的曲線. 輪廓在形狀分析和物體的檢測和識別中很有用。
輪廓的作用:
- 用于圖形分析
- 物體的識別和檢測
注意點:
- 為了檢測的準確性,需要先對圖像進行二值化或Canny操作。
- 畫輪廓時會修改輸入的圖像, 如果之后想繼續(xù)使用原始圖像,應該將原始圖像儲存到其他變量中。
7.2 查找輪廓
-
findContours(image, mode, method[, contours[, hierarchy[, offset]]])
-
mode 查找輪廓的模式
-
RETR_EXTERNAL = 0, 表示只檢測外圍輪廓
-
RETR_LIST = 1, 檢測的輪廓不建立等級關系, 即檢測所有輪廓, 較為常用
- RETR_CCOMP = 2, 每層最多兩級, 從小到大, 從里到外.
- RETR_TREE = 3, 按照樹型存儲輪廓, 從大到小, 從右到左.
-
-
method 輪廓近似方法也叫ApproximationMode
- CHAIN_APPROX_NONE 保存所有輪廓上的點
- CHAIN_APPROX_SIMPLE, 只保存角點, 比如四邊形, 只保留四邊形的4個角, 存儲信息少, 比較常用
-
返回 contours和hierachy 即輪廓和層級
-
import cv2
import numpy as np# 該圖像顯示效果是黑白的, 但是實際上卻是3個通道的彩色圖像.
img = cv2.imread('./contours1.jpeg')# 變成單通道的黑白圖片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 二值化, 注意有2個返回值, 閾值和結果
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)# cv2.imshow('img', img)
# cv2.imshow('binary', binary)# 輪廓查找, 新版本返回兩個結果, 輪廓和層級, 老版本返回3個參數, 圖像, 輪廓和層級
result, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 打印輪廓
print(contours)
cv2.waitKey(0)
cv2.destroyAllWindows()
7.3 繪制輪廓
- drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])
- image 要繪制的輪廓圖像
- contours輪廓點
- contourIdx 要繪制的輪廓的編號. -1 表示繪制所有輪廓
- color 輪廓的顏色, 如 (0, 0, 255)表示紅色
- thickness線寬, -1 表示全部填充
import cv2
import numpy as np# 該圖像顯示效果是黑白的, 但是實際上卻是3個通道的彩色圖像.
img = cv2.imread('./contours1.jpeg')# 變成單通道的黑白圖片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 二值化, 注意有2個返回值, 閾值和結果
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)# 輪廓查找, 新版本返回兩個結果, 輪廓和層級, 老版本返回3個參數, 圖像, 輪廓和層級
result, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 繪制輪廓, 注意, 繪制輪廓會改變原圖
cv2.drawContours(img, contours, 1, (0, 0, 255), 2)cv2.imshow('img', img)cv2.waitKey(0)
cv2.destroyAllWindows()
7.4 輪廓的面積和周長
輪廓面積是指每個輪廓中所有的像素點圍成區(qū)域的面積,單位為像素。
輪廓面積是輪廓重要的統(tǒng)計特性之一,通過輪廓面積的大小可以進一步分析每個輪廓隱含的信息,例如通過輪廓面積區(qū)分物體大小識別不同的物體。
在查找到輪廓后, 可能會有很多細小的輪廓, 我們可以通過輪廓的面積進行過濾.
- contourArea(contour)
- arcLength(curve, closed)
- curve即輪廓
- closed是否是閉合的輪廓
import cv2
import numpy as np# 該圖像顯示效果是黑白的, 但是實際上卻是3個通道的彩色圖像.
img = cv2.imread('./contours1.jpeg')# 變成單通道的黑白圖片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 二值化, 注意有2個返回值, 閾值和結果
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)# 輪廓查找, 新版本返回兩個結果, 輪廓和層級, 老版本返回3個參數, 圖像, 輪廓和層級
result, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 繪制輪廓, 注意, 繪制輪廓會改變原圖
cv2.drawContours(img, contours, 1, (0, 0, 255), 2)# 計算面積
area = cv2.contourArea(contours[1])
print('area: ', area)
cv2.imshow('img', img)# 計算周長
perimeter = cv2.arcLength(contours[1], True)
print('perimeter:', perimeter)cv2.waitKey(0)
cv2.destroyAllWindows()
7.5 多邊形逼近與凸包
? findContours后的輪廓信息contours可能過于復雜不平滑,可以用approxPolyDP函數對該多邊形曲線做適當近似,這就是輪廓的多邊形逼近.
apporxPolyDP就是以多邊形去逼近輪廓,采用的是Douglas-Peucker算法(方法名中的DP)
DP算法原理比較簡單,核心就是不斷找多邊形最遠的點加入形成新的多邊形,直到最短距離小于指定的精度。
- approxPolyDP(curve, epsilon, closed[, approxCurve])
- curve 要近似逼近的輪廓
- epsilon 即DP算法使用的閾值
- closed輪廓是否閉合
import cv2
import numpy as npimg = cv2.imread('./hand.png')gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 二值化, 注意有2個返回值, 閾值和結果
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)# 輪廓查找, 新版本返回兩個結果, 輪廓和層級, 老版本返回3個參數, 圖像, 輪廓和層級
result, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 繪制輪廓, 注意, 繪制輪廓會改變原圖
cv2.drawContours(img, contours, 0, (0, 0, 255), 2)
# 展示沒有進行多邊形逼近之前的輪廓# 進行多邊形逼近, 返回的是多邊形上一系列的點, 即多邊形逼近之后的輪廓
approx = cv2.approxPolyDP(contours[0], 20, True)
# print(type(approx))
# print(approx)
# print('--------------------------------------')
# print(contours[0])# 把多邊形逼近的輪廓畫出來.
cv2.drawContours(img, [approx], 0, (0, 255, 0), 2)
cv2.imshow('img', img)cv2.waitKey(0)
cv2.destroyAllWindows()
逼近多邊形是輪廓的高度近似,但是有時候,我們希望使用一個多邊形的凸包來簡化它。凸包跟逼近多邊形很像,只不過它是物體最外層的凸多邊形。凸包指的是完全包含原有輪廓,并且僅由輪廓上的點所構成的多邊形。凸包的每一處都是凸的,即在凸包內連接任意兩點的直線都在凸包的內部。在凸包內,任意連續(xù)三個點的內角小于180°。
- convexHull(points[, hull[, clockwise[, returnPoints]]])
- points 即輪廓
- colckwise 順時針繪制
import cv2
import numpy as npimg = cv2.imread('./hand.png')gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 二值化, 注意有2個返回值, 閾值和結果
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)# 輪廓查找, 新版本返回兩個結果, 輪廓和層級, 老版本返回3個參數, 圖像, 輪廓和層級
result, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 繪制輪廓, 注意, 繪制輪廓會改變原圖
cv2.drawContours(img, contours, 0, (0, 0, 255), 2)# 進行多邊形逼近, 返回的是多邊形上一系列的點, 即多邊形逼近之后的輪廓
approx = cv2.approxPolyDP(contours[0], 20, True)# 把多邊形逼近的輪廓畫出來.
cv2.drawContours(img, [approx], 0, (0, 255, 0), 2)# 計算凸包
hull = cv2.convexHull(contours[0])
cv2.drawContours(img, [hull], 0, (255, 0, 0), 2)cv2.imshow('img', img)cv2.waitKey(0)
cv2.destroyAllWindows()
7.6 外接矩形
外接矩形分為最小外接矩形和最大外接矩形.
下圖中紅色矩形是最小外接矩形, 綠色矩形為最大外接矩形.
-
minAreaRect(points) 最小外接矩陣
- points 即為輪廓
- 返回元組, 內容是一個旋轉矩形(RotatedRect)的參數: 矩形的起始坐標x,y, 矩形的寬度和高度, 矩形的選擇角度.
-
boundingRect(points) 最大外接矩陣
- points 即為輪廓
import cv2
import numpy as npimg = cv2.imread('./hello.jpeg')gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)result, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 最外面的輪廓是整個圖像, contours[1]表示圖像里面的圖形輪廓
# 注意返回的內容是一個旋轉的矩形, 包含矩形的起始坐標, 寬高和選擇角度
(x, y), (w, h), angle = cv2.minAreaRect(contours[1])print(x, y)
print(w, h)
print(angle)
r = cv2.minAreaRect(contours[1])# 快速把rotatedrect轉化為輪廓數據
box = cv2.boxPoints(r)
print(box)
# 輪廓必須是整數, 不能是小數, 所以轉化為整數
box = np.round(box).astype('int64')
print(box)
# 繪制最小外接矩形
cv2.drawContours(img, [box], 0, (255, 0, 0), 2)# 返回矩形的x,y和w,h
x,y, w, h = cv2.boundingRect(contours[1])
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()