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

如何用OpenCV识别图像伪影与孔洞并完成形状提取等处理

OpenCV 技术支持需求

现有一张地面上放置复杂形状的图像,需完成以下任务:

  • 提取目标复杂形状
  • 去除图像噪声
  • 移除图像中的logo
  • 识别形状上的4个孔洞

原始图像:
原始图像
效果参考图:
效果参考图

当前实现代码

import cv2
import numpy as np


# Read the original image
img = cv2.imread('Amoebe_1.jpg') 
# resize image
scale_down = 0.4
img = cv2.resize(img, None, fx= scale_down, fy= scale_down, interpolation= cv2.INTER_LINEAR)

# Display original image
cv2.imshow('Original', img)
cv2.waitKey(0)

# Denoising
dst = cv2.fastNlMeansDenoisingColored(img,None,20,10,10,21)

# Canny Edge Detection
edges = cv2.Canny(image=dst, threshold1=100, threshold2=200) # Canny Edge Detection

# Contour Detection
contours1, hierarchy1 = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# draw contours on the original image for `CHAIN_APPROX_SIMPLE`
image_copy1 = img.copy()
cv2.drawContours(image_copy1, contours1, -1, (0, 255, 0), 2, cv2.LINE_AA)
# see the results
cv2.imshow('Simple approximation', image_copy1)

# Display Canny Edge Detection Image
cv2.imshow('Canny Edge Detection', edges)
cv2.waitKey(0)

#Floodfill
h,w,chn = img.shape
seed = (w/2,h/2)
mask = np.zeros((h+2,w+2),np.uint8)
bucket = edges.copy()
cv2.floodFill(bucket, mask, (0,0), (255,255,255))
cv2.imshow('Mask', bucket)
cv2.waitKey(0)

cv2.destroyAllWindows()

优化解决方案

步骤1:预处理与去噪

转为灰度图处理可降低计算复杂度,组合高斯模糊+非局部均值去噪,能更高效过滤地面纹理噪声:

# 读取图像并缩放
img = cv2.imread('Amoebe_1.jpg')
scale_down = 0.4
img = cv2.resize(img, None, fx=scale_down, fy=scale_down, interpolation=cv2.INTER_LINEAR)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 组合去噪:高斯模糊平滑纹理,非局部均值去除残留噪声
blurred = cv2.GaussianBlur(gray, (5,5), 0)
dst = cv2.fastNlMeansDenoising(blurred, None, 15, 7, 21)

通过自适应阈值分割分离前景后,用图像修复功能覆盖Logo区域(需根据实际图像调整Logo坐标):

# 自适应阈值分割,突出目标形状与背景的差异
thresh = cv2.adaptiveThreshold(dst, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)

# 定位Logo区域(示例坐标,需根据实际图像调整)
logo_x, logo_y, logo_w, logo_h = 50, 50, 100, 50
# 生成Logo掩膜
logo_mask = np.zeros(gray.shape, np.uint8)
logo_mask[logo_y:logo_y+logo_h, logo_x:logo_x+logo_w] = 255
# 使用Telea算法修复Logo区域
img_no_logo = cv2.inpaint(img, logo_mask, 3, cv2.INPAINT_TELEA)

步骤3:提取目标形状与孔洞识别

利用轮廓层级区分外轮廓(目标形状)和内轮廓(孔洞),通过面积过滤噪声轮廓:

# 对去噪后的灰度图做Canny边缘检测,调整阈值减少冗余边缘
edges = cv2.Canny(dst, 50, 150)

# 寻找轮廓及层级关系,RETR_TREE可保留轮廓嵌套结构
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

result = img_no_logo.copy()
hole_count = 0

# 遍历轮廓,根据层级判断外轮廓/孔洞
for i, cnt in enumerate(contours):
    area = cv2.contourArea(cnt)
    # 过滤过小的噪声轮廓
    if area < 100:
        continue
    # 外轮廓:层级中父节点索引为-1
    if hierarchy[0][i][3] == -1:
        cv2.drawContours(result, [cnt], -1, (0,255,0), 2)
    # 内轮廓:存在父节点,即为孔洞
    else:
        cv2.drawContours(result, [cnt], -1, (0,0,255), 2)
        hole_count += 1

print(f"识别到孔洞数量:{hole_count}")
cv2.imshow('最终结果', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

步骤4:形态学优化(可选)

若边缘仍存在细碎噪声,可加入形态学开闭操作清理:

# 创建3x3矩形结构元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
# 闭操作填充边缘缝隙,开操作去除孤立噪声点
edges_clean = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
edges_clean = cv2.morphologyEx(edges_clean, cv2.MORPH_OPEN, kernel)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 02:25:51