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

机器视觉学习-day14-绘制图像轮廓

1. 轮廓的概念

轮廓是目标物体或者区域在图像外部的边界线通常由一系列像素点相连组成,这些像素点共同构成了一个封闭的形状,这样形状就是轮廓。

轮廓与边缘不同:

        轮廓是连续的,边缘可以连续也可以离散

        轮廓是完整的,边缘可以是完成的也可以不完整

轮廓主要分析物体的形态,比如计算物体的周长与面积;边缘作为图像特征使用,比如区分脸和手。

代码运行步骤:

图片输入→灰度化→二值化→寻找轮廓→绘制轮廓→图片输出

1.1 寻找轮廓

    # 4. 寻找轮廓# 返回值1:所有轮廓的点坐标,是一个list列表# 返回值2:轮廓的层级关系contours, hierarchy = cv2.findContours(image = image_np_thresh,  # 二值化之后的图像mode = cv2.RETR_EXTERNAL,  # 默认的轮廓查找方式method = cv2.CHAIN_APPROX_SIMPLE  # 默认的轮廓近似办法)

●contours 轮廓s
tuple类型,所有轮廓的点(每个元素是Numpy数组),可以通过[n-1]取出第n个轮廓的数据
●hierarchy 轮廓关系
如果没有检测到轮廓,则返回的数组为空,通常不会出现。
对于第n个轮廓:
○hierarchy[n][0]表示当前轮廓的后一条轮廓
○hierarchy[n][1]表示当前轮廓的前一条轮廓
○hierarchy[n][2]表示当前轮廓的第一个子轮廓
○hierarchy[n][3]表示当前轮廓的父轮廓
如果出现-1表示没有。
此参数较少使用,通常用于处理复杂画面效果。
●image 输入图像
要求8位的二值化图像,前景色白色,背景色黑色
●mode 轮廓的查找方式
○RETR_EXTERNAL 查找最外层轮廓(不查找内层轮廓)
在hierarchy层级结构中,每一个轮廓只有前后轮廓的索引,没有父轮廓与子轮    廓的索引。
○RETR_LIST 查找所有轮廓(包括外层和内层轮廓)
在hierarchy层级结构中,每一个轮廓只有前后轮廓的索引,没有父轮廓与子轮    廓的索引。
○RETR_CCOMP 查找所有轮廓(包括外层和内层轮廓)
在hierarchy层级结构中,每一个轮廓只有前后轮廓的索引,有父轮廓与子轮        廓的索引,轮廓为两层结构。
○RETR_TREE (包括外层和内层轮廓)
在hierarchy层级结构中,每一个轮廓只有前后轮廓的索引,有父轮廓与子轮        廓的索引,轮廓为树状结构。
●method 轮廓的近似办法
○CHAIN_APPROX_NONE 存储所有轮廓点
○CHAIN_APPROX_SIMPLE 只存储有用的点
比如轮廓中的直线,则只存储起点和终点;比如轮廓是四边形,则只存储四个顶点。
○CHAIN_APPROX_TC89_L1 使用Teh_Chin链进行轮廓逼近
精度高(优化后的点更少),使用少。

1.2 绘制轮廓

使用绘制轮廓的方式把上一步的寻找的轮廓点连接在一起进行绘制,这一步绘制的是前景轮廓。

  • contourIdx 轮廓编号

        -1表示绘制所有轮廓

  • color 轮廓颜色
  • thickness 绘制的线宽

1.3 轮廓检测算法 Suzuki

内容复杂,了解即可

2 代码实践

原图3.jpg

import cv2if __name__ == '__main__':# 1. 图片输入path = '3.jpg'image_np = cv2.imread(path)# 2. 灰度化image_np_gray = cv2.cvtColor(image_np,cv2.COLOR_BGR2GRAY)# 3. 二值化ret, image_np_thresh = cv2.threshold(image_np_gray,127,255,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)print(ret)# 4. 寻找轮廓contours, hierarchy = cv2.findContours(image_np_thresh,  # 二值化之后的图像cv2.RETR_EXTERNAL,  # 查找方式cv2.CHAIN_APPROX_SIMPLE  # 近似办法)print(len(contours))for i in contours:print(i.shape)"""cv2.findContours(): 查找图像中的轮廓参数详解:image_np_thresh: 二值化图像,必须是8位单通道图像cv2.RETR_EXTERNAL: 轮廓检索模式,只检测最外层轮廓cv2.CHAIN_APPROX_SIMPLE: 轮廓近似方法,压缩水平、垂直和对角线段,只保留它们的端点返回值:contours: 找到的轮廓列表,每个轮廓是一个点集hierarchy: 轮廓的层次信息(此代码中未使用)print(len(contours)): 打印找到的轮廓数量for i in contours: print(i.shape): 遍历所有轮廓并打印每个轮廓的形状(即包含多少个点)"""# 5. 绘制轮廓image_np = cv2.drawContours(image_np,  # 在哪个图上绘制contours,  # 轮廓数据列表contourIdx=-1,  # 绘制轮廓的id,-1表示全绘制color=(0, 0, 255),  # 绘制的颜色thickness=2  # 线宽)"""cv2.drawContours(): 在图像上绘制轮廓参数详解:image_np: 要绘制轮廓的目标图像(会在原图上直接修改)    contours: 要绘制的轮廓列表    contourIdx=-1: 指定要绘制哪个轮廓,-1表示绘制所有轮廓    color=(0, 0, 255): 轮廓颜色,BGR格式(这里是红色)    thickness=2: 轮廓线宽度"""# 6. 图片输出cv2.imshow('image_np', image_np)cv2.waitKey(0)cv2.imwrite('image.png', image_np)# 读取图像 → 2. 转换为灰度图 → 3. 二值化处理 → 4. 查找轮廓 → 5. 绘制轮廓 → 6. 显示结果

运行后图片:image.png

练习:绘制图像的所有轮廓,并使用不同的颜色标识。

图片:3.jpg

"""绘制图像的所有轮廓,并使用不同的颜色标识。"""
import cv2
import numpy as npif __name__ == '__main__':# 1.图片输入path = '3.jpg'  # 图像文件路径image_np = cv2.imread(path)  # 读取图像为NumPy数组(BGR格式)# # 2. 灰度化# image_np_gray = cv2.cvtColor(#     image_np,#     cv2.COLOR_BGR2GRAY# )# cv2.imshow('image_np_gray', image_np_gray)# # 3. 二值化# ret, image_np_thresh = cv2.threshold(#     image_np_gray,#     192,  # 191/192为青色和粉色的临界值#     255,#     cv2.THRESH_BINARY_INV# )# 使用灰度化、二值化后,颜色浅的 无法选中# 2.HSV空间转换hsv_image_np = cv2.cvtColor(image_np, cv2.COLOR_BGR2HSV)  # BGR转HSV# 3. 制作掩膜# 定义绿色范围/背景图掩膜green_low = np.array([35, 43, 46])  # 红色下限(Hmin, Smin, Vmin)green_high = np.array([77, 255, 255])  # 红色上限(Hmax, Smax, Vmax)mask1 = cv2.inRange(  # 创建掩膜hsv_image_np,  # 基于哪个图像, 输入HSV图像green_low,  # 颜色下限green_high  # 颜色上限)# 合并掩膜mask_image_np = cv2.bitwise_or(mask1, mask1)  # 红cv2.imshow('mask_image_np4', mask_image_np)# 4.反阈值二值化取到前景图片ret, image_np_thresh = cv2.threshold(mask_image_np,  # 输入的灰度图像127,  # 阈值(127),但使用OTSU方法时会自动计算最佳阈值255,  # 最大值(255),当像素值超过阈值时赋予的值cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)cv2.imshow('image_np_thresh', image_np_thresh)# 5. 寻找轮廓contours, hierarchy = cv2.findContours(image_np_thresh,  # 二值化之后的图像cv2.RETR_LIST,  # 查找方式:查找所有轮廓(包括外层和内层轮廓)cv2.CHAIN_APPROX_SIMPLE  # 近似办法)print(len(contours))for i in contours:print(i.shape)# 定义不同颜色用于绘制不同轮廓colors = [(0, 0, 0),  # 黑色(255, 255, 0),  # 青色(255, 0, 0),  # 蓝色(255, 0, 255),  # 粉色]# 遍历所有找到的轮廓for i, cnt in enumerate(contours):# enumerate()函数返回的是(index, value)元组对,所以不能直接将循环变量用于索引# 计算当前轮廓的面积,过滤掉太小的轮廓(可能是噪声)area = cv2.contourArea(cnt)if area < 197:  # 忽略面积小于100像素的轮廓continue# 选择颜色(循环使用预定义的颜色)# color = colors[i]  # 当i≥4时会报IndexErrorcolor = colors[i % len(colors)]  # 0%4=0...5%4=1(循环)# 6. 绘制轮廓image_np = cv2.drawContours(image_np,  # 在哪个图上绘制contours,  # 轮廓数据列表contourIdx=i,  # 绘制轮廓的id,-1表示全绘制,从0开始代表下标color=color,  # 使用选择的颜色thickness=2  # 线宽)# 6. 图片输出cv2.imshow('image_np', image_np)cv2.waitKey(0)cv2.imwrite('123.png', image_np)

运行结果:123.png

http://www.xdnf.cn/news/19359.html

相关文章:

  • 【机器学习基础】监督学习算法的现代理解:从经典方法到无人驾驶与生成式AI的实践应用
  • [光学原理与应用-353]:ZEMAX - 设置 - 可视化工具:2D视图、3D视图、实体模型三者的区别,以及如何设置光线的数量
  • 财务的三张报表:现金流表、利润表、资产负债表
  • Spring/Spring MVC/iBATIS 应用 HTTP 到 HTTPS 迁移技术方案
  • 基于i.MX6ULL的RAM Disk驱动开发
  • 【开题答辩全过程】以 付费自习室系统小程序为例,包含答辩的问题和答案
  • 【编号186】中国劳动统计年鉴(1991-2023)
  • kafka服务端架构总览
  • 【C++】显示与隐式加载dll的使用与区别
  • 技术框架之RPC
  • 【系统分析师】高分论文:论信息系统的安全与保密设计
  • c++ 线程局部存储(Thread-Local Storage,TLS)
  • 当服务器报警响起:CPU、内存、磁盘使用率飙升的诊断与处置
  • 基于单片机智能鞋柜/智能鞋橱/智能鞋盒
  • C++项目的Makefile案例解析
  • Python基础之元组列表集合字典
  • Python与Rust语法对比详解:从入门到精通
  • C++顺序嵌套回调函数
  • 飞牛NAS上部署Markdown文稿编辑器,阅读.md文件同时还可以跨平台访问!
  • Qt精华版打包教程,支持windows和Linux,每种平台支持2种方案
  • 电感值过大过小会影响什么
  • AI基础学习周报十一
  • 艾体宝案例 | 数据驱动破局:DOMO 如何重塑宠物零售门店的生存法则
  • HarmonyOS 应用开发:基于API 12+的现代化实践
  • C++从入门到实战(二十)详细讲解C++List的使用及模拟实现
  • Ubuntu安装NVIDIA显卡驱动
  • #Datawhale 组队学习#8月-工作流自动化n8n入门-3
  • LabVIEW 瀑布图与游标操作
  • 分布式事务相关
  • [软考中级]嵌入式系统设计师—核心知识点速记