计算机视觉--Opencv(郁金香图像轮廓提取与多边形逼近)

本次项目的核心目标有两个:

一是从郁金香图像中精准提取出整束花的外部原始轮廓,排除图像中的背景杂质与无关干扰;

二是通过多边形逼近算法对原始轮廓进行简化,得到平滑的近似轮廓,同时保留郁金香的核心形状特征。

代码如下:

python 复制代码
1. 读取图像并预处理
img = cv2.imread(r"C:\Users\LEGION\Desktop\fb312a897160f2c9036096f52dbdecf6.png")

# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化处理(针对白色背景郁金香,阈值240提升轮廓提取精度)
_, thresh = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)

# 2. 提取外部轮廓(OpenCV 3.x专属:返回3个值,下划线忽略无用的处理后图像)
_, contours, hierarchy = cv2.findContours(
    thresh,
    cv2.RETR_EXTERNAL,
    cv2.CHAIN_APPROX_SIMPLE
)

if len(contours) == 0:
    raise ValueError("未检测到图像轮廓,请调整二值化阈值或检查图像质量")

# 选取面积最大的轮廓(确保是整束花的外部轮廓,排除杂质小轮廓)
target_contour = max(contours, key=cv2.contourArea)

# 3. 计算近似轮廓(ε=周长×0.005,符合题目要求)
contour_perimeter = cv2.arcLength(target_contour, closed=True)
epsilon = 0.005 * contour_perimeter
approx_contour = cv2.approxPolyDP(target_contour, epsilon, closed=True)

# 4. 核心:创建两个独立图像副本,分别绘制单一轮廓(避免叠加,实现分开输出)
# 副本1:仅绘制红色原始外部轮廓
img_red_original = img.copy()
cv2.drawContours(
    img_red_original,
    [target_contour],
    0,
    (0, 0, 255),  # OpenCV BGR格式:红色
    2  # 线宽
)

# 副本2:仅绘制绿色近似轮廓
img_green_approx = img.copy()
cv2.drawContours(
    img_green_approx,
    [approx_contour],
    0,
    (0, 255, 0),  # OpenCV BGR格式:绿色
    2  # 线宽
)

# 5. 分开显示:两个独立窗口展示结果(可视化查看)
# 窗口1:红色原始轮廓
cv2.namedWindow("Result 1: Red Original Contour", cv2.WINDOW_NORMAL)
cv2.imshow("Result 1: Red Original Contour", img_red_original)

# 窗口2:绿色近似轮廓
cv2.namedWindow("Result 2: Green Approx Contour", cv2.WINDOW_NORMAL)
cv2.imshow("Result 2: Green Approx Contour", img_green_approx)

# 6. 分开保存:两个独立文件持久化存储(可长期查看,保存在代码同级目录)
cv2.imwrite('flower_red_original_contour.png', img_red_original)
cv2.imwrite('flower_green_approx_contour.png', img_green_approx)

# 打印保存提示
print("分开保存完成,文件路径:")
print("1. 红色原始轮廓:flower_red_original_contour.png")
print("2. 绿色近似轮廓:flower_green_approx_contour.png")

# 等待按键输入后关闭所有显示窗口
cv2.waitKey(0)
cv2.destroyAllWindows()

注释:

二值化处理 :二值化处理是将灰度图像转换为只有黑色和白色两种像素值的图像,这样能够突出目标物体与背景的边界,方便后续轮廓提取。我们使用cv2.threshold()函数进行二值化处理,该函数有四个核心参数:

  • 第一个参数:待二值化的灰度图像(gray);

  • 第二个参数:阈值(240),本次实战中郁金香图像的背景是白色,像素值接近 255,郁金香本身的像素值低于 240,因此选择 240 作为阈值能够很好地区分郁金香和背景

  • 第三个参数:最大值(255),当像素值超过阈值(或低于阈值,取决于二值化类型)时,将其设置为该最大值;

  • 第四个参数:二值化类型(cv2.THRESH_BINARY_INV),表示反向二值化,即像素值低于阈值的设置为 255(白色),高于阈值的设置为 0(黑色)。这样处理后,郁金香会变成白色,背景会变成黑色,更符合 OpenCV 轮廓提取的要求。

cv2.findContours()函数有三个核心参数:

  • 第一个参数:二值化图像(thresh);

  • 第二个参数:轮廓检索模式(cv2.RETR_EXTERNAL),表示只提取最外层的轮廓,忽略内部的子轮廓,这正是我们需要的郁金香外部轮廓;

  • 第三个参数:轮廓逼近方法(cv2.CHAIN_APPROX_SIMPLE),表示压缩轮廓点,只保留轮廓的关键点(如直线的端点、曲线的拐点),能够大幅减少轮廓点的数量,节省内存空间。

运行结果:

(红色的为原始轮廓,绿色的为近似轮廓)

将两个图像的结果放在成同一张图上

代码如下:

python 复制代码
import cv2

# 1. 读取图像并预处理
img = cv2.imread(r"C:\Users\LEGION\Desktop\fb312a897160f2c9036096f52dbdecf6.png")

# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化处理(针对白色背景郁金香,阈值240提升轮廓提取精度)
_, thresh = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)

# 2. 提取外部轮廓(OpenCV 3.x专属:返回3个值,下划线忽略无用的处理后图像)
_, contours, hierarchy = cv2.findContours(
    thresh,
    cv2.RETR_EXTERNAL,
    cv2.CHAIN_APPROX_SIMPLE
)

if len(contours) == 0:
    raise ValueError("未检测到图像轮廓,请调整二值化阈值或检查图像质量")

# 选取面积最大的轮廓(确保是整束花的外部轮廓,排除杂质小轮廓)
target_contour = max(contours, key=cv2.contourArea)

# 3. 计算近似轮廓(ε=周长×0.005,符合题目要求)
contour_perimeter = cv2.arcLength(target_contour, closed=True)
epsilon = 0.005 * contour_perimeter
approx_contour = cv2.approxPolyDP(target_contour, epsilon, closed=True)

# 4. 核心:创建单个图像副本,在同一张图上绘制两种轮廓(红色原始+绿色近似)
img_combined = img.copy()  # 仅创建一个图像副本,用于合并两种轮廓

# 先绘制红色原始外部轮廓
cv2.drawContours(
    img_combined,
    [target_contour],
    0,
    (0, 0, 255),  # OpenCV BGR格式:红色
    2  # 线宽
)

# 再绘制绿色近似轮廓(在同一个副本上叠加绘制)
cv2.drawContours(
    img_combined,
    [approx_contour],
    0,
    (0, 255, 0),  # OpenCV BGR格式:绿色
    2  # 线宽
)

# 5. 可视化展示:单个窗口展示合并结果
cv2.namedWindow("Result: Red Original Contour + Green Approx Contour", cv2.WINDOW_NORMAL)
cv2.imshow("Result: Red Original Contour + Green Approx Contour", img_combined)

# 6. 保存结果:单个文件保存合并后的图像
cv2.imwrite('flower_combined_contours.png', img_combined)

# 打印保存提示
print("合并结果保存完成,文件路径:")
print("合并轮廓图像:flower_combined_contours.png")

# 等待按键输入后关闭所有显示窗口
cv2.waitKey(0)
cv2.destroyAllWindows()

轮廓叠加绘制 :在img_combined上先调用cv2.drawContours()绘制红色原始轮廓,再调用一次该函数绘制绿色近似轮廓,OpenCV 会自动将两种轮廓叠加在同一张图上,红色和绿色对比清晰,能直观看到轮廓近似的简化效果。

运行结果:

相关推荐
风象南9 小时前
普通人用AI加持赚到的第一个100块
人工智能·后端
牛奶9 小时前
2026年大模型怎么选?前端人实用对比
前端·人工智能·ai编程
牛奶9 小时前
前端人为什么要学AI?
前端·人工智能·ai编程
罗西的思考12 小时前
AI Agent框架探秘:拆解 OpenHands(10)--- Runtime
人工智能·算法·机器学习
冬奇Lab13 小时前
OpenClaw 源码精读(2):Channel & Routing——一条消息如何找到它的 Agent?
人工智能·开源·源码阅读
冬奇Lab13 小时前
一天一个开源项目(第38篇):Claude Code Telegram - 用 Telegram 远程用 Claude Code,随时随地聊项目
人工智能·开源·资讯
格砸14 小时前
从入门到辞职|从ChatGPT到OpenClaw,跟上智能时代的进化
前端·人工智能·后端
可观测性用观测云14 小时前
可观测性 4.0:教系统如何思考
人工智能
sunny86515 小时前
Claude Code 跨会话上下文恢复:从 8 次纠正到 0 次的工程实践
人工智能·开源·github
小笼包包仔15 小时前
OpenClaw 多Agent软件开发最佳实践指南
人工智能