如何用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)
步骤2:移除Logo
通过自适应阈值分割分离前景后,用图像修复功能覆盖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
相关产品推荐
相关产品推荐

