目录
1.相关概念
轮廓是图像中连续的、有相同颜色 / 灰度值的像素点组成的曲线,代表物体的边界。
与边缘的区别:边缘是离散的像素突变点,轮廓是连续的闭合曲线,更强调 “连接性”。
轮廓检测的前提必须输入二值图像(黑白图像)
2.核心函数
cv2.findContours():用于从二值图像中提取轮廓,返回轮廓列表和层级信息
# OpenCV 4.x/2.x 版本
contours, hierarchy = cv2.findContours(binary_img, mode, method)
# OpenCV 3.x 版本(多一个返回值,通常用_忽略)
_, contours, hierarchy = cv2.findContours(binary_img, mode, method)
参数::
mode
(轮廓检索模式):决定轮廓的层级关系(父子关系)cv2.RETR_EXTERNAL
:只保留最外层轮廓(常用,减少干扰)。cv2.RETR_TREE
:保留所有轮廓并构建完整层级树(适合分析嵌套轮廓,如 “同心圆”)。cv2.RETR_LIST
:保留所有轮廓,但不构建层级(简单场景用)。
method
(轮廓逼近方法):决定轮廓点的存储方式cv2.CHAIN_APPROX_NONE
:存储所有轮廓点(精确但占内存)。v2.CHAIN_APPROX_SIMPLE
:压缩冗余点(如矩形只保留 4 个角点,节省内存,常用)。
3.常见的几种操作处理
绘制轮廓,轮廓特征,边界矩形,外接圆,轮廓近似
import cv2
import matplotlib.pyplot as plt
import numpy as np
#为了更高的准确率,采用二值图像
img=cv2.imread('stru2.jpg')
def cv_show(name,imag):
cv2.imshow(name,imag)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv_show('stru',img)
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
res,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY) #二值处理
cv_show('thresh',thresh)
#轮廓特征(求轮廓的面积和周长)
con=contours[1]#[1]表示轮廓列表的第一个
area=cv2.contourArea(con)#求面积
arc=cv2.arcLength(con,True)#求周长,True表示轮廓是闭合的
print(area,' ',arc)
#边界矩形
x,y,w,h=cv2.boundingRect(con)#cv2.boundingRect() 是 OpenCV 中用于计算轮廓最小外接矩形(边界矩形)的函数
#x:矩形左上角的 x 坐标,y:矩形左上角的 y 坐标,w:矩形的宽度,h:矩形的高度
imag=cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
#cv2.rectangle() 是 OpenCV 中用于在图像上绘制矩形的函数,常与 cv2.boundingRect() 配合使用,
#(x,y)是矩形的左上角坐标,(x+w,y+h)是矩形的右下角坐标
cv_show('imag',imag)
#外接圆
'''
v2.minEnclosingCircle()是计算轮廓 con 的最小外接圆(能完全包围轮廓的最小圆形)
其中,(x1,y1)是圆心坐标,是浮点数类型,r是半径也是浮点数类型
'''
(x1,y1),r=cv2.minEnclosingCircle(con)
center=(int(x1),int(y1))
r=int(r)
imag1=cv2.circle(draw_img,center,r,(0,255,0),2)#cv2.circle()是OpenCV中用于在图像上绘制圆形的函数,可用于标记目标中心、绘制轮廓外接圆等场景
cv_show('imag1',imag1)
#轮廓近似
con1=contours[2]
arc1=cv2.arcLength(con1,True)
epsilon=0.1*arc1#精度(0.1)越小,近似结果越接近原始轮廓;精度越大,轮廓越简化。
approx=cv2.approxPolyDP(con1,epsilon,True)
draw_img1=img.copy()
res1=cv2.drawContours(draw_img1,[approx],-1,(0,0,255),2)
cv_show('res1',res1)
#用for循环遍历所有的轮廓并进行轮廓近似
draw_img2 = img.copy()
for i,contour in enumerate(contours):
'''
i:接收当前轮廓的索引(从 0 开始的整数),用于标识当前处理的是第几个轮廓。
contour:接收 contours 列表中的每个轮廓元素(即单个轮廓的坐标数据)。不这样用:contour=contours[i]
enumerate() 是 Python 内置函数,用于将一个可迭代对象(这里是 contours 轮廓列表)转换为一个枚举对象。
'''
arc2=cv2.arcLength(contour,True)
epsilon2=0.2*arc
approx2=cv2.approxPolyDP(contour,epsilon2,True)
cv2.drawContours(draw_img2,[approx2],-1,(0,0,255),2)
cv_show('draw_all',draw_img2)