You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于图像形状绘制轮廓掩码——使用Canny边缘检测(更新版)

基于OpenCV获取不含内部区域的轮廓掩码解决方案

问题说明

需要使用OpenCV-Python 4.9.0.80,针对两类不规则形状的测试图像(内部含空洞/空白区域),生成仅保留外部形状、不含内部区域的轮廓掩码(需排除灰色背景)。但使用cv.convexHull()得到的结果会强制包裹所有边缘点,覆盖内部空洞,不符合预期需求。

当前使用代码

import cv2 as cv
import numpy as np

path = '/opt/boundary-remover/SW_test2-01.png'
# path = '/opt/boundary-remover/scaled_2x.png'
# Load image
src = cv.imread(cv.samples.findFile(path))
cv.imwrite('1_original.png', src)

# Convert image to gray and blur it
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
cv.imwrite('2_gray.png', src_gray)

# Detect edges using Canny
canny_output = cv.Canny(src_gray, 100, 200)
cv.imwrite('3_canny.png', canny_output)

# Find contours
contours, _ = cv.findContours(canny_output, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)

# Combine all contours into a single contour
all_contours = np.concatenate(contours)

# Find the convex hull object for the combined contour
hull = cv.convexHull(all_contours)

# Draw the combined contour and its convex hull
drawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)
color = (0, 255, 0)  # Green color
# cv.drawContours(drawing, [all_contours], 0, color)
# cv.imwrite('4_all_contours.png', drawing)
cv.drawContours(drawing, [hull], 0, color)
cv.imwrite('5_hull.png', drawing)

cv.drawContours(drawing, [hull], -1, color, thickness=cv.FILLED)
cv.imwrite('7_filled.png', drawing)

解决方案

核心思路是筛选出最外层的原始轮廓,而非使用凸包(凸包会忽略内部空洞)。具体步骤:

  1. 更改轮廓检索模式,获取包含层级关系的所有轮廓
  2. 通过面积筛选出最大的外部轮廓(排除内部小空洞的轮廓)
  3. 用该外部轮廓绘制填充掩码

修改后的完整代码

import cv2 as cv
import numpy as np

path = '/opt/boundary-remover/SW_test2-01.png'
# path = '/opt/boundary-remover/scaled_2x.png'

# 加载图像
src = cv.imread(cv.samples.findFile(path))
cv.imwrite('1_original.png', src)

# 转灰度并添加高斯模糊(减少噪声干扰)
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
src_gray = cv.GaussianBlur(src_gray, (5,5), 0)
cv.imwrite('2_gray_blur.png', src_gray)

# Canny边缘检测
canny_output = cv.Canny(src_gray, 50, 150)
cv.imwrite('3_canny.png', canny_output)

# 查找轮廓:使用RETR_CCOMP获取层级,区分内外轮廓
contours, hierarchy = cv.findContours(canny_output, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE)

# 筛选面积最大的轮廓(即外部形状轮廓)
max_area = 0
outer_contour = None
for cnt in contours:
    area = cv.contourArea(cnt)
    if area > max_area:
        max_area = area
        outer_contour = cnt

# 创建并填充掩码
mask = np.zeros_like(src_gray)
cv.drawContours(mask, [outer_contour], -1, 255, thickness=cv.FILLED)
cv.imwrite('final_mask.png', mask)

# 彩色可视化版本(可选)
color_mask = np.zeros((src.shape[0], src.shape[1], 3), dtype=np.uint8)
cv.drawContours(color_mask, [outer_contour], -1, (0,255,0), thickness=cv.FILLED)
cv.imwrite('final_color_mask.png', color_mask)

关键说明

  • cv.RETR_CCOMP:可检索所有轮廓并分为两层(外层/内层),便于区分外部形状和内部空洞
  • cv.contourArea():通过面积筛选,最大轮廓即为目标外部形状,自动排除内部小轮廓
  • 高斯模糊:预处理减少噪声,避免Canny检测出多余的干扰边缘

内容的提问来源于stack exchange,提问作者NiRmaL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 02:07:50