当前位置: 首页 > news >正文

opencv基础(轮廓检测、绘制与特征)

一、轮廓检测

轮廓定义:图像中具有相同颜色 / 灰度的连续像素点连接形成的闭合曲线,代表前景与背景的边界,与边缘(单像素灰度突变)不同,轮廓更强调整体外形与连通性。

cv2.findContours是 OpenCV 用于从二值图像中提取轮廓的函数,其核心作用是扫描二值图像的像素,追踪连续的边界点并组织成轮廓集合,同时可返回轮廓间的层级关系(如嵌套、并列)

cv2.findContours(image, mode, method)

参数:

image:必须是单通道二值图(前景白色 255,背景黑色 0),若输入彩色 / 灰度图需先二值化

mode:轮廓检索模式

1.cv2.RETR_EXTERNAL:只提取最外层轮廓(忽略嵌套轮廓),适合只关注主体的场景(如检测单个物体)

2.cv2.RETR_LIST:提取所有轮廓,不建立层级关系(最简洁)

3.cv2.RETR_CCOMP:提取所有轮廓,建立两层层级(外层 + 内层)

4.cv2.RETR_TREE:提取所有轮廓,建立完整层级树(最常用,可区分嵌套 / 并列轮廓)

method:轮廓逼近方法

1.cv2.CHAIN_APPROX_NONE:保留所有轮廓点(每个点都存储,数据量大)

2.cv2.CHAIN_APPROX_SIMPLE:压缩水平 / 垂直 / 对角线方向的冗余点(如矩形只存 4 个顶点,最常用)

代码:

phone=cv2.imread('phone.png')#读取原图 phone_gray=cv2.cvtColor(phone,cv2.COLOR_BGR2GRAY)#灰度图的处理 cv2.imshow('phone_b',phone_gray) cv2.waitKey(0) #phone_gray=cv2.imread('phone.png',b)#读取灰度图 ret,phone_binary =cv2.threshold(phone_gray,120,255,cv2.THRESH_BINARY)#阀值处理为二值 cv2.imshow('phone_binary',phone_binary) cv2.waitKey(0) # _,contours,hierarchy =cv2.findContours(phone_binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) contours = cv2.findContours(phone_binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)[-2] # 通用 # print(hierarchy) print(len(contours))

1.通过cv2.cvtColor(phone,cv2.COLOR_BGR2GRAY)将图像变成灰度图

2.通过cv2.threshold将灰度值大于 120 的像素设为 255(白色,前景),小于等于 120 的像素设为 0(黑色,背景),最终得到一张黑白二值图。

3.最后用cv2.findContours对二值图像phone_binary提取所有轮廓(含层级)、保留所有轮廓点,最终只取返回结果中的[轮廓列表]

二、轮廓绘制

函数cv2.drawContours(image, contours,contourIdx,color, thickness=None,
LineType=None,hierarchy=None,maxLevel=None,offset=None)
参数含义如下:
image:要在其上绘制轮廊的输入图像。
contours:轮廊列表,通常由cv2.findContours(函数返回。
contourIdx:要绘制的轮序的索引。如果为负数,则绘制所有轮廓。-1
color:轮廓的颜色,以BGR格式表示。例如,(0,255,0)表示绿色。
thickness:轮廓线的粗细。默认值为1。
lineType:轮廊线的类型。默认值为cv2.LINE_8。
hierarchy:轮廓层次结构。通常由cv2.findContours(函数返回。
maxLevel:绘制的最大轮廊层级。默认值为None,表示绘制所有层级。
offset:轮廓点的偏移量。默认值为None。

代码:

image_copy = phone.copy() cv2.drawContours(image=image_copy,contours=contours,contourIdx=6,color=(255,255,0),thickness=3) cv2.imshow('Contours_show',image_copy) cv2.waitKey(0)

通过drawContours方法在图像的复制本上绘制轮廓用上面轮廓检测得到的contours轮廓列表

得到的图像:

三、轮廓特征

1.轮廓面积

cv2.contourArea()用于计算单个轮廓所包围的像素面积,面积值反映了轮廓对应的物体大小,是筛选有效轮廓、分析形状的基础。

area = cv2.contourArea(contour, oriented=False)

contour:顶点构成的二维向量组(如轮廓列表contours中的一个轮廓)

oriented:默认为False:返回绝对值面积

2.轮廓周长

cv2.arcLength()用于计算轮廓的弧长 / 周长,对于闭合轮廓返回周长,对于非闭合轮廓返回弧长,是判断轮廓形状、计算圆形度等特征的关键参数。

length = cv2.arcLength(contour, closed)

contour:单个轮廓(来自cv2.findContours返回的contours列表元素)

closed:True:认为轮廓是闭合的(首尾相连),计算完整周长;False:认为轮廓是开放的(首尾不连),计算从起点到终点的弧长

3.轮廓外接圆

cv2.minEnclosingCircle()用于计算单个轮廓的最小外接圆(能完全包围轮廓的最小圆形),返回圆心坐标和半径。

(x_center, y_center), radius = cv2.minEnclosingCircle(contour)

contour:单个轮廓(来自cv2.findContours返回的contours列表元素)

(x_center, y_center):最小外接圆的圆心坐标

radius:最小外接圆的半径

4.轮廓外接矩形

x,y,w,h=cv2.boundingRect(cnt)计算轮廓的最小外接矩形

x,y:是轮廓的最小外接矩形的左上角

w,h:是矩形的宽和高

四、轮廓近似

approx = cv2.approxPolyDP(curve,epsilon,closed)
参数说明:
curve:输入轮廓。
epsilon:近似精度,即两个轮廓之间最大的欧式距离。该参数越小,得到的近似结果越接近实际轮廓:反之,得到的近似结果会更加粗略。
closed:布尔类型的参数,表示是否封闭轮廓。如果是True,表示输入轮廓是封闭的,近似结果也会是封闭的:否则表示输入轮廓不是封闭的,
返回值:approx:近似结果,是一个ndarray数组,为1个近似后的轮廓,包含了被近似出来的轮廓上的点的坐标

代码:

phone = cv2.imread('phone.png') phone_gray=cv2.cvtColor(phone,cv2.COLOR_BGR2GRAY)#转换为灰度图 ret,phone_thresh=cv2.threshold(phone_gray,120,255,cv2.THRESH_BINARY) #二值化 #image,contours,hierarchy=cv2.findContours(phone_thresh,cv2.RETR_TREE,cv2.CHAIN_APPRox_NoNE)#获取轮廓 contours=cv2.findContours(phone_thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)[-2] epsilon= 0.01 * cv2.arcLength(contours[0],True) #设置近似精度.[h要<e;ε越小,点越多,越精确】 approx=cv2.approxPolyDP(contours[0],epsilon,True)#对轮廓进行近似 print(contours[1].shape) print(approx.shape) phone_new = phone.copy() image_contours=cv2.drawContours(phone_new,[approx],contourIdx=-1,color=(0,255,0),thickness=3)#绘制轮廓 cv2.imshow('phone',phone) cv2.waitKey(0) cv2.imshow('image_contours',image_contours) cv2.waitKey(0)

得到的图像:

http://www.jsqmd.com/news/275539/

相关文章:

  • Leetcode—3314. 构造最小位运算数组 I【简单】
  • 集成运放加法器电路原理验证的实战案例(含Multisim仿真)
  • 词根词缀拆解|dict- = 说/断言!用兜兜英语快速记牢高频词
  • 计算机毕业设计springboot少儿编程教培机构教务管理系统 基于SpringBoot的青少年编程培训中心教务运营平台 少儿编程教育机构教学事务一体化管理系统
  • 基于多目标粒子群优化算法的冷热电联供型综合能源系统运行优化(Matlab代码实现)
  • ‌如何测试AI的“推理深度”?我设计了“五层追问”测试
  • GC-IP201 驱动
  • ‌大模型测试的“监控体系”:实时检测幻觉、偏见、泄露
  • 每10年一次的“开发者淘汰战”,自1969年就已开局!
  • 智能窗户防撬报警系统仿真:proteus蜂鸣器实战
  • 055.多层图最短路(扩点)
  • Vivado License节点锁定设置:项目环境配置说明
  • ‌AI模拟用户情绪波动:软件测试从业者的新测试范式
  • 记一次经典的反序列化漏洞(CVE-2017-10271)
  • Multisim14使用教程:快速理解直流电路搭建步骤
  • Authentication is required but no CredentialsProvider has been registered 报错已解决
  • 大模型测试的“冷启动评估”:新模型上线前怎么测?
  • 解决vscode中文输入法输入没有候选框问题
  • 2026中国智慧养老行业:老龄化浪潮下的刚性需求爆发
  • Error creating bean with name ‘xxxxxxxController‘: Injection of resource dependencies failed报错已解决
  • 如何测试AI生成的邮件是否符合商务礼仪:软件测试从业者指南
  • 通过agentscope在EKS部署远程沙盒和代理应用
  • IDEA_pom.xml_spring-boot-maven-plugin爆红问题解决
  • 全国现代物业管理人才培养赋能新质生产力发展研讨会 (MPMTT 2026)
  • 跨境电商防关联:从“单点隔离”到“系统化风控”一套打穿
  • 玩转Synbo|为什么说质押是进入Club的关键动作
  • Galaxy比数平台功能介绍及实现原理|得物技术
  • 上位机软件开发中串口超时机制的设计实践
  • Eclipse 打开报 `An error has occurred. See the log null` 错误及解决方法
  • 第七篇:告别手动拼 URL!我们封装自己的“地图超市”