文章目录一、轮廓检测概述1.1 什么是轮廓检测1.2 边缘检测 vs 轮廓检测1.3 轮廓检测的基本流程二、核心 API 详解2.1 查找轮廓cv2.findContours()2.2 绘制轮廓cv2.drawContours()2.3 代码示例三、轮廓特征计算3.1 轮廓面积 cv2.contourArea()3.2 轮廓周长 cv2.arcLength()3.3 轮廓筛选与排序四、轮廓的外接几何形状4.1 轴对齐外接矩形4.2 最小外接圆4.3 代码示例五、轮廓近似cv2.approxPolyDP()5.1 什么是轮廓近似5.2 API 使用5.3 使用技巧5.4 代码示例六、模板匹配Template Matching6.1 什么是模板匹配6.2 核心函数 cv2.matchTemplate()6.3 匹配方法对比6.4 获取最佳匹配位置6.5 代码示例七、总结一、轮廓检测概述1.1 什么是轮廓检测在计算机视觉领域我们经常需要从图像中找到物体的位置、形状以及边界信息——例如找出图片中的硬币区域、检测工业零件是否完整。这些任务都离不开一个重要的技术轮廓检测Contour Detection。轮廓本质上是一系列点的集合这些点构成了图像中物体的边界。OpenCV 提供了一整套轮廓分析方法可以帮助我们提取图像中目标对象的边界并进一步进行形状分析。1.2 边缘检测 vs 轮廓检测这两个概念容易混淆但实际应用目标不同检测类型侧重点输出典型算法边缘检测检测图像中明暗变化剧烈梯度变化较大的像素点零散的边缘点集合Sobel、Laplacian、Canny轮廓检测检测图像中对象的完整边界有序的轮廓点序列findContours边缘检测主要关注图像中像素变化剧烈的位置轮廓检测关注图像中对象的边界。1.3 轮廓检测的基本流程轮廓检测通常是图像处理流程中的前置环节一般流程如下读取图片灰度化—— 将彩色图像转换为灰度图二值化—— 将图像转换为二值图像像素值仅为0和255findContours 查找轮廓—— 提取所有轮廓drawContours 绘制轮廓—— 在图像上可视化轮廓轮廓特征分析—— 计算面积、周长、外接矩形等二、核心 API 详解2.1 查找轮廓cv2.findContours()cv2.findContours()是轮廓检测最核心的函数用于从二值图像中提取所有轮廓。函数原型contours,hierarchycv2.findContours(image,mode,method)⚠️ 版本差异提醒OpenCV 3.x返回 image, contours, hierarchy 三个值OpenCV 4.x返回 contours, hierarchy 两个值兼容写法contours cv2.findContours(...)[-2]两个版本均适用参数详解参数说明image输入的二值图像像素值仅为 0 和 255不能是彩色图像mode轮廓检索模式method轮廓近似方法轮廓检索模式mode模式说明cv2.RETR_EXTERNAL只检测最外层轮廓所有内部子轮廓被忽略cv2.RETR_LIST检测所有轮廓但不建立等级关系所有轮廓处于同一层级cv2.RETR_CCOMP返回所有轮廓仅建立两级层次结构。对象外轮廓为第一级内部空洞轮廓为第二级cv2.RETR_TREE返回所有轮廓建立完整的树形层次结构最常用轮廓近似方法method方法说明cv2.CHAIN_APPROX_NONE存储轮廓上的所有像素点数据量大cv2.CHAIN_APPROX_SIMPLE压缩模式仅保留轮廓的拐点坐标。例如矩形轮廓只需 4 个顶点即可表示大幅减少数据量推荐使用返回值说明contours包含所有轮廓的列表每个轮廓是一个 numpy 数组存储轮廓上所有点的 (x, y) 坐标hierarchy轮廓的层次结构信息每个轮廓对应一个包含 4 个值的数组[Next, Previous, First_Child, Parent]Next同层级的下一个轮廓索引Previous同层级的上一个轮廓索引First_Child当前轮廓的第一个子轮廓索引Parent当前轮廓的父轮廓索引若无对应关系值为-12.2 绘制轮廓cv2.drawContours()cv2.drawContours()用于在图像上绘制查找到的轮廓。函数原型cv2.drawContours(image,contours,contourIdx,color,thicknessNone,lineTypeNone,hierarchyNone,maxLevelNone,offsetNone)关键参数image要绘制轮廓的目标图像会直接修改该图像建议先 copycontours轮廓列表由findContours返回contourIdx要绘制的轮廓索引-1表示绘制所有轮廓color轮廓颜色BGR 格式如(0, 255, 0)表示绿色thickness轮廓线粗细默认 1设为-1表示填充轮廓内部2.3 代码示例importcv2# 1. 读取图像并预处理imgcv2.imread(phone.png)img_graycv2.cvtColor(img,cv2.COLOR_BGR2GRAY)# 2. 二值化处理轮廓检测前必须二值化ret,binarycv2.threshold(img_gray,120,255,cv2.THRESH_BINARY)# 3. 查找轮廓兼容写法contourscv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)[-2]print(f检测到{len(contours)}个轮廓)# 4. 绘制所有轮廓img_copyimg.copy()cv2.drawContours(img_copy,contours,-1,(0,255,0),2)# 5. 显示全部轮廓cv2.imshow(All Contours,img_copy)cv2.waitKey(0)cv2.destroyAllWindows()效果展示三、轮廓特征计算获取轮廓后我们通常不会直接使用而是计算其几何特征用于筛选和识别。3.1 轮廓面积 cv2.contourArea()areacv2.contourArea(contour[,oriented])contour单个轮廓点集oriented定向区域标志默认False返回面积绝对值True时根据轮廓方向返回带符号数值轮廓面积的单位是像素的平方。3.2 轮廓周长 cv2.arcLength()lengthcv2.arcLength(curve,closed)curve输入的轮廓点集closed布尔值表示轮廓是否封闭轮廓周长又称弧长表示轮廓的闭合边界的总长度。3.3 轮廓筛选与排序实际应用中检测到的轮廓往往很多需要根据面积等特征进行筛选# 按面积筛选去除噪声保留主要目标filtered_contours[cntforcntincontoursifcv2.contourArea(cnt)1000]# 按面积从大到小排序sorted_contourssorted(contours,keycv2.contourArea,reverseTrue)largest_contoursorted_contours[0]# 取面积最大的轮廓四、轮廓的外接几何形状4.1 轴对齐外接矩形x,y,w,hcv2.boundingRect(contour)# 绘制矩形cv2.rectangle(img,(x,y),(xw,yh),(0,255,0),2)返回外接矩形的左上角坐标 (x, y) 以及宽高 (w, h)。4.2 最小外接圆(x,y),rcv2.minEnclosingCircle(contour)# 绘制圆形center(int(x),int(y))rint(r)cv2.circle(img,center,r,(0,255,0),2)表示能够完全包围轮廓的最小圆。4.3 代码示例importcv2 imgcv2.imread(phone.png)graycv2.cvtColor(img,cv2.COLOR_BGR2GRAY)ret,binarycv2.threshold(gray,120,255,cv2.THRESH_BINARY)contourscv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)[-2]# 取面积最大轮廓cntmax(contours,keycv2.contourArea)# 轮廓面积周长areacv2.contourArea(cnt)perimetercv2.arcLength(cnt,True)print(f面积:{area:.2f}, 周长:{perimeter:.2f})# ---------- 外接形状部分 ----------# 最小外接矩形x,y,w,hcv2.boundingRect(cnt)cv2.rectangle(img,(x,y),(xw,yh),(0,255,0),2)# 最小外接圆center,radiuscv2.minEnclosingCircle(cnt)cv2.circle(img,(int(center[0]),int(center[1])),int(radius),(255,0,0),2)cv2.imshow(外接形状矩形圆,img)cv2.waitKey(0)cv2.destroyAllWindows()效果展示五、轮廓近似cv2.approxPolyDP()5.1 什么是轮廓近似真实物体的边界可能包含大量点例如一个圆形可能有数百个边界点但我们可能只需要几个关键点来表示它。轮廓近似是指对轮廓进行多边形拟合用更少的点来近似表示轮廓形状。5.2 API 使用approxcv2.approxPolyDP(curve,epsilon,closed)参数说明curve输入的原始轮廓epsilon近似精度表示原始轮廓与近似轮廓之间的最大欧氏距离closed布尔值表示轮廓是否封闭核心规律epsilon越小 → 点越多 → 越接近实际轮廓越精确epsilon越大 → 点越少 → 越粗略5.3 使用技巧epsilon通常按轮廓周长的比例设置epsilon0.05*cv2.arcLength(contour,True)# 精度为周长的5%approxcv2.approxPolyDP(contour,epsilon,True)5.4 代码示例importcv2 phonecv2.imread(phone.png)phone_graycv2.cvtColor(phone,cv2.COLOR_BGR2GRAY)# 转换为灰度图ret,phone_threshcv2.threshold(phone_gray,120,255,cv2.THRESH_BINARY)# 二值化# 获取轮廓[-2]兼容新旧OpenCV版本contourscv2.findContours(phone_thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)[-2]# 按面积取最大目标轮廓cntmax(contours,keycv2.contourArea)# 设置近似精度epsilon越大顶点越少轮廓越粗糙epsilon0.005*cv2.arcLength(cnt,True)approxcv2.approxPolyDP(cnt,epsilon,True)phone_newphone.copy()# 绘制近似后的轮廓contourIdx-1代表绘制传入列表里全部轮廓cv2.drawContours(phone_new,[approx],-1,color(0,255,0),thickness2)cv2.imshow(approx contour,phone_new)cv2.waitKey(0)cv2.destroyAllWindows()效果展示六、模板匹配Template Matching6.1 什么是模板匹配模板匹配是一种经典的图像搜索方法其目标是在一幅大图中寻找与模板图像最相似的区域。基本原理将模板图像在输入图像上滑动类似于二维卷积在每个位置计算模板与下方图像块的相似程度。6.2 核心函数 cv2.matchTemplate()resultcv2.matchTemplate(image,templ,method)参数说明image待搜索的大图templ模板图像必须小于等于大图method匹配方法6.3 匹配方法对比方法说明匹配越好cv2.TM_SQDIFF平方差匹配值越小cv2.TM_SQDIFF_NORMED归一化平方差匹配值越小cv2.TM_CCORR相关匹配值越大cv2.TM_CCORR_NORMED归一化相关匹配值越大cv2.TM_CCOEFF相关系数匹配值越大cv2.TM_CCOEFF_NORMED归一化相关系数匹配值越大推荐使用推荐使用归一化方法对光照变化鲁棒性更好。6.4 获取最佳匹配位置min_val,max_val,min_loc,max_loccv2.minMaxLoc(result)根据匹配方法选择最佳位置平方差类TM_SQDIFF 等取 min_loc最小值位置相关 / 相关系数类TM_CCORR、TM_CCOEFF 等取 max_loc最大值位置# 以 TM_CCOEFF_NORMED 为例top_leftmax_loc# 左上角坐标就是最大值坐标bottom_right(top_left[0]w,top_left[1]h)cv2.rectangle(img,top_left,bottom_right,(0,255,0),2)6.5 代码示例importcv2# 读取原图和模板imgcv2.imread(img_01.png)templatecv2.imread(img_02.png)h,wtemplate.shape[:2]# 模板匹配resultcv2.matchTemplate(img,template,cv2.TM_CCOEFF_NORMED)# 获取最佳匹配位置# 最小值 最大值 最小值坐标 最大值坐标min_val,max_val,min_loc,max_loccv2.minMaxLoc(result)top_leftmax_loc bottom_right(top_left[0]w,top_left[1]h)# 在副本上绘制匹配框避免修改原图img_resultimg.copy()cv2.rectangle(img_result,top_left,bottom_right,(0,255,0),2)cv2.imshow(Template,template)cv2.imshow(Match Result,img_result)cv2.waitKey(0)cv2.destroyAllWindows()效果展示七、总结OpenCV 轮廓检测是计算机视觉中非常基础且重要的技术掌握它可以帮助我们解决从目标定位到形状识别的一系列实际问题。核心函数功能函数寻找轮廓cv2.findContours绘制轮廓cv2.drawContours计算面积cv2.contourArea计算周长cv2.arcLength轴对齐外接矩形cv2.boundingRect最小外接圆cv2.minEnclosingCircle轮廓近似cv2.approxPolyDP模板匹配cv2.matchTemplate获取极值位置cv2.minMaxLoc