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

实战项目实现以下功能:

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

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

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

项目完整代码:

python 复制代码
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: 图像加载与预处理

python 复制代码
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: 二值化处理

python 复制代码
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: 轮廓检测

python 复制代码
_, 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: 筛选最大面积轮廓

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

注意事项

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


模块 5: 绘制原始轮廓

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

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

python 复制代码
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: 绘制逼近轮廓

python 复制代码
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. 多目标场景改进方案

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

完整流程总结

python 复制代码
读取图像 → 灰度转换 → 反向二值化 → 检测所有轮廓 → 筛选最大轮廓 → 绘制原始轮廓 → 多边形逼近 → 绘制简化轮廓
相关推荐
struggle20257 小时前
Lightpanda:专为 AI 和自动化设计的无头浏览器
运维·人工智能·自动化
数据猿7 小时前
AI时代下,我们需要新一代的金融基础软件
大数据·人工智能·金融
飞哥数智坊7 小时前
模力方舟 + Claude Code 实测:给登录页染上国庆红
人工智能·ai编程
gladiator+7 小时前
深度学习--行人重识别技术(超分辨率网络+ResNet101)附数据集
人工智能·深度学习
有Li7 小时前
EndoChat:面向内镜手术的基于事实依据的多模态大型语言模型|文献速递-文献分享
大数据·论文阅读·人工智能·算法·文献·医学生
金井PRATHAMA7 小时前
产生式规则对自然语言处理深层语义分析的影响与启示研究
人工智能·自然语言处理·知识图谱
en-route7 小时前
深入理解 Scikit-learn:Python 中最常用的机器学习库
python·机器学习·scikit-learn
努力还债的学术吗喽8 小时前
PyTorch nn.Linear 终极详解:从零理解线性层的一切(含可视化+完整代码)
人工智能·pytorch·python·深度学习·基础组件·线性层·nn.linear
说私域8 小时前
基于开源AI智能名片的S2B2C商城小程序中搜索联想功能的优化策略研究
人工智能·小程序
工藤学编程8 小时前
零基础学AI大模型之LangChain聊天模型多案例实战
人工智能·langchain