实战项目-----在图片 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 复制代码
读取图像 → 灰度转换 → 反向二值化 → 检测所有轮廓 → 筛选最大轮廓 → 绘制原始轮廓 → 多边形逼近 → 绘制简化轮廓
相关推荐
KimLiu3 小时前
LCODER之Python:使用Django搭建服务端
后端·python·django
胡耀超3 小时前
3.Python高级数据结构与文本处理
服务器·数据结构·人工智能·windows·python·大模型
索迪迈科技3 小时前
GPS汽车限速器有哪些功能?主要运用在哪里?
人工智能·行车记录仪·车辆安全·监控管理·gps定位
1373i3 小时前
【Python】pytorch安装(使用conda)
pytorch·python·conda
keyinf03 小时前
python网络爬取个人学习指南-(五)
python
Niuguangshuo4 小时前
深度学习基本模块:Conv2D 二维卷积层
人工智能·深度学习
b***25114 小时前
深圳比斯特|多维度分选:圆柱电池品质管控的自动化解决方案
大数据·人工智能