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

实战项目-----在图片 hua.png 中,用红色画出花的外部轮廓,用绿色画出其简化轮廓(ε=周长×0.005),并在同一窗口显示

实战项目实现以下功能:

对图片 hua.png 进行轮廓提取,并在同一窗口中完成以下两个绘制操作:

  1. 用红色画出花的外部轮廓(即最外层轮廓)

  2. 用绿色画出该轮廓的近似多边形,其中近似精度参数 ε 设置为轮廓周长的 0.005

项目完整代码:

import cv2
hua = cv2.imread('picture/hua.png')#读取原图
hua_gray = cv2.cvtColor(hua,cv2.COLOR_BGR2GRAY)#灰度图的处理
cv2.imshow('hua_b',hua_gray)
cv2.waitKey(0)
# hua_gray=cv2.imread('hua.png',0)  #读取灰度图
ret, hua_binary = cv2.threshold(hua_gray, 240, 255, cv2.THRESH_BINARY_INV)#阈值处理为二值
cv2.imshow('hua_binary',hua_binary)
cv2.waitKey(0)
_,contours, hierarchy = cv2.findContours(hua_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  #cv2.RETR_EXTERNAL:只检测外轮廓(黑底),所有子轮廓被忽略
# _,contours, hierarchy = cv2.findContours(hua_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# sortcnt=contours[0]
print(len(contours))# image_copy = hua.copy()
# cv2.drawContours(image=image_copy, contours=contours, contourIdx=-1,color=(0,255,0),thickness=2)
# cv2.imshow('Contours_show', image_copy)
# cv2.waitKey(0)image_copy = hua.copy()
sortcnt = sorted(contours, key=cv2.contourArea, reverse=True)[0]  # 选取最大面积的轮廓
image_contours = cv2.drawContours(image_copy,[sortcnt],contourIdx=-1,color=(0,0,255),thickness=3)#绘制轮廓
cv2.imshow('image_contours',image_contours)
cv2.waitKey(0)epsilon = 0.005  * cv2.arcLength(sortcnt,True)        #设置近似精度   【h要<ε;ε越小,点越多,越精确】
approx = cv2.approxPolyDP(sortcnt, epsilon, True)   #对轮廓进行近似
print(sortcnt.shape)
print(approx.shape)image_contours = cv2.drawContours(image_copy,[approx],contourIdx=-1,color=(0,255,0),thickness=3)#绘制轮廓
cv2.imshow('image_contours',image_contours)
cv2.waitKey(0)

整体功能概述

此代码实现了以下核心功能:

  1. 图像预处理 → 灰度转换 + 反向二值化
  2. 轮廓检测 → 提取所有轮廓并筛选最大面积轮廓
  3. 轮廓可视化 → 绘制原始轮廓与多边形逼近结果
  4. 几何简化 → 使用 Douglas-Peucker 算法对轮廓进行多点精简

 模块 1: 图像加载与预处理

import cv2
hua = cv2.imread('picture/hua.png')          # ① 读取原图
hua_gray = cv2.cvtColor(hua, cv2.COLOR_BGR2GRAY)  # ② 转为灰度图
cv2.imshow('hua_b', hua_gray)                 # ③ 显示灰度图
cv2.waitKey(0)                               # ④ 暂停等待按键
关键点解析:
  • 灰度转换必要性:减少颜色干扰,聚焦亮度信息,提升后续二值化效果
  • cv2.COLOR_BGR2GRAY:OpenCV 默认 BGR 色彩空间,此处正确转换
  • 可视化验证:通过 imshow 确保灰度转换无误

模块 2: 二值化处理

ret, hua_binary = cv2.threshold(hua_gray, 240, 255, cv2.THRESH_BINARY_INV)  # ⑤ 反向二值化
cv2.imshow('hua_binary', hua_binary)           # ⑥ 显示二值图
cv2.waitKey(0)
关键参数详解
参数说明
thresh=240阈值像素值 >240 → 设为255(白);≤240 → 设为0(黑)
maxval=255饱和值超过阈值时的赋值上限
THRESH_BINARY_INV反向模式关键! 将高亮区域变为黑色背景,低亮区域变为白色前景

为何选择反向模式?
如果花朵主体比背景更暗(常见情况),正向二值化会使背景变白,导致轮廓断裂。反向模式可保留暗色前景的完整性。

模块 3: 轮廓检测

_, contours, hierarchy = cv2.findContours(hua_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  # ⑦ 检测所有轮廓
print(len(contours))                                                                    # ⑧ 输出轮廓数量
核心概念解析
  1. 三个返回值

    • _:忽略的 retval(通常无用)
    • contours:存储所有轮廓点的列表(每个轮廓是一个 numpy 数组)
    • hierarchy:轮廓层级关系矩阵(父子兄弟关系)
  2. 关键参数

    • cv2.RETR_TREE:检索所有轮廓并建立完整层级树(包括嵌套轮廓)
    • cv2.CHAIN_APPROX_SIMPLE:压缩水平/垂直方向连续点,仅保留端点

典型轮廓数量:若输出 n,表示检测到 n 个独立轮廓(含嵌套结构)


模块 4: 筛选最大面积轮廓

image_copy = hua.copy()                                  # ⑨ 创建原图副本用于绘图
sortcnt = sorted(contours, key=cv2.contourArea, reverse=True)[0]  # ⑩ 按面积降序排序,取最大轮廓
关键操作
  • cv2.contourArea():计算单个轮廓的面积(像素数)
  • sorted(..., reverse=True):按面积从大到小排序
  • [0]:取排序后的第一个元素(最大面积轮廓)

注意事项
如果图像存在多个相似大小的物体,此方法可能无法稳定选取目标。建议结合位置/形状特征进一步过滤。


模块 5: 绘制原始轮廓

image_contours = cv2.drawContours(image_copy, [sortcnt], contourIdx=-1, color=(0,0,255), thickness=3)  # ⑪ 绘制红色轮廓
cv2.imshow('image_contours', image_contours)                                                 # ⑫ 显示结果
cv2.waitKey(0)
绘图参数详解
参数说明
imageimage_copy在原图副本上绘制
contours=[sortcnt]仅绘制最大轮廓注意传入的是单元素列表
contourIdx=-1绘制全部层级-1 表示绘制轮廓的所有层级
color=(0,0,255)纯红色BGR 格式
thickness=3线宽较大的线宽使轮廓更醒目

模块 6: 多边形逼近(几何简化)

epsilon = 0.005 * cv2.arcLength(sortcnt, True)      # ⑬ 计算近似精度(基于轮廓周长)
approx = cv2.approxPolyDP(sortcnt, epsilon, True)    # ⑭ 执行多边形逼近
print(sortcnt.shape)                                 # ⑮ 输出原始轮廓点数
print(approx.shape)                                # ⑯ 输出逼近后点数
 核心算法解析
  1. 近似精度计算

    • cv2.arcLength(sortcnt, True):计算轮廓总长度(闭合路径)
    • epsilon = 0.005 * 周长:控制逼近误差容忍度(经验值)
    • 原理:ε 越小,保留的细节越多;越大,简化程度越高
  2. Douglas-Peucker 算法

    • 递归删除偏离直线距离小于 ε 的中间点
    • closed=True:保证首尾相连形成闭合多边形

点数对比示例
假设原始轮廓有 1000 个点 → 逼近后可能只剩 10-20 个顶点,大幅减少数据量


模块 7: 绘制逼近轮廓

image_contours = cv2.drawContours(image_copy, [approx], contourIdx=-1, color=(0,255,0), thickness=3)  # ⑰ 绘制绿色逼近轮廓
cv2.imshow('image_contours', image_contours)                                                # ⑱ 显示结果
cv2.waitKey(0)
可视化对比
颜色含义特点
红色原始轮廓显示实际边缘细节
绿色多边形逼近结果展示几何简化后的顶点分布

应用场景
可用于形状识别(如判断是否为多边形)、尺寸测量、碰撞检测等需要简化几何表示的场景


 常见问题与优化建议

  1. 二值化失效怎么办?

    • 调整阈值(尝试 127 或自适应阈值 adaptiveThreshold
    • 添加高斯模糊去噪:blurred = cv2.GaussianBlur(hua_gray, (5,5), 0)
  2. 轮廓断裂如何处理?

    • 提高阈值使前景更连贯
    • 使用形态学操作连接断开部分:kernel = np.ones((3,3), np.uint8); closed = cv2.morphologyEx(hua_binary, cv2.MORPH_CLOSE, kernel)
  3. 多目标场景改进方案

    # 过滤小面积噪声
    min_area = 100  # 根据实际调整
    valid_contours = [cnt for cnt in contours if cv2.contourArea(cnt) > min_area]
    

完整流程总结

读取图像 → 灰度转换 → 反向二值化 → 检测所有轮廓 → 筛选最大轮廓 → 绘制原始轮廓 → 多边形逼近 → 绘制简化轮廓


文章转载自:

http://28YToE4a.fyLsz.cn
http://5BeLfxc6.fyLsz.cn
http://nY0XDQMD.fyLsz.cn
http://wcp3CLgF.fyLsz.cn
http://ioLtkrlo.fyLsz.cn
http://6iJy183b.fyLsz.cn
http://xC7NfcWF.fyLsz.cn
http://YekCxUSk.fyLsz.cn
http://7Kvi8zEd.fyLsz.cn
http://QSNsFatd.fyLsz.cn
http://i4oUL5ki.fyLsz.cn
http://w5ihvtDh.fyLsz.cn
http://zER9mmtU.fyLsz.cn
http://q89p8rGz.fyLsz.cn
http://NL3SKr1K.fyLsz.cn
http://Le4YTMqI.fyLsz.cn
http://dKvYGxI9.fyLsz.cn
http://JcsnDwyB.fyLsz.cn
http://AGmQTiUX.fyLsz.cn
http://EVWRFjpr.fyLsz.cn
http://YEuuXGck.fyLsz.cn
http://eYnM8JRb.fyLsz.cn
http://dfGpLgj7.fyLsz.cn
http://dU0DwOwO.fyLsz.cn
http://ZTp9NlX7.fyLsz.cn
http://t1GVI1KP.fyLsz.cn
http://0BV91My1.fyLsz.cn
http://JXsUxk9i.fyLsz.cn
http://4UV8MJDg.fyLsz.cn
http://omt0YaMQ.fyLsz.cn
http://www.dtcms.com/a/374963.html

相关文章:

  • 第一章 神经网络的复习
  • Spring Cloud 配置中心
  • Typescript入门-d.ts类型声明文件讲解
  • DBF Viewer 2000:专业的DBF文件查看与编辑工具
  • 【字符压缩存在整数32bit技术】
  • 【芯片设计-信号完整性 SI 学习 1.0 -- SI 介绍】
  • uniapp开源多商户小程序商城平台源码 支持二次开发+永久免费升级
  • map / unordered_map / set / unordered_set
  • 不同数据仓库模型有什么不同?企业如何选择适合的数据仓库模型?
  • jmeter入门
  • 【ShiMetaPi】基于BM1684X的智能工业视觉边缘计算盒子解决方案
  • [论文阅读] 算法 | 抗量子+紧凑!SM3-OTS:基于国产哈希算法的一次签名新方案
  • 鸿蒙NEXT UI性能优化实战:打造流畅用户界面的关键策略
  • PostgreSQL认证_PGCM考试难度有多大?
  • Spring Security的理解与使用
  • 论文阅读_大模型情绪分析预测股票趋势
  • 学习嵌入式的第三十六天——数据库与网页制作
  • 【C++】list 容器操作
  • 【WRF-VPRM 预处理器第二期】VPRMpreproc.r 脚本详解
  • 430章:Python Web爬虫入门:使用Requests和BeautifulSoup
  • 在 Vite 中,环境变量的处理方式与传统的 Node.js 环境有所不同
  • 不同射频对应不同mac地址(查找无线用户连接AP信息)
  • 《红色脉络:一部PLMN在中国的演进史诗 (1G-6G)》 第9篇 | 5G:领跑者的姿态——SA/NSA之争与中国的战略选择
  • 36页可编辑PPT | 某制造集团灯塔工厂解决方案
  • 基于springboot+vue的厨艺交流平台的设计与实现(源码+论文+部署+安装)
  • 【华为OD】5G网络建设
  • 使用LLM(Ollama部署)为Bertopic确定的主题命名
  • C++容器:list
  • PAT 1178 File Path
  • ESP32开发:ubuntu22.04 下esp-idf开发环境搭建