如何用OpenCV Python精准识别并完整填充图像孔洞
基于轮廓完整填充图像黑色孔洞的代码修改方案
我需要识别图像中的黑色孔洞并基于邻域像素颜色填充。目前通过HSV阈值分割检测黑色区域轮廓,但现有代码只能填充轮廓的外接矩形区域,无法完整填充孔洞,期望实现完整填充轮廓内部的效果。
现有代码:
img=cv2.imread(r'image.png') img_copy = img.copy() black_MIN = np.array([0, 0, 0],np.uint8) black_MAX = np.array([179, 50, 100],np.uint8) hsv_img = cv2.cvtColor(img,cv2.COLOR_BGR2HSV) frame_threshed = cv2.inRange(hsv_img, black_MIN, black_MAX) contours,hierarchy = cv2.findContours(frame_threshed, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) for c in contours: area = cv2.contourArea(c) # Area of first contour perimeter = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.04 * perimeter, True) (x,y,w,h) = cv2.boundingRect(c) roi=img[y:y+h,x:x+w] cv2.rectangle(img_copy,(x,y),(x+w,y+h),(0,252,213),-1) plt.imshow(img_copy[:,:,::-1])
解决方案
问题核心是你用cv2.rectangle填充了轮廓的外接矩形,而非轮廓实际区域。只需替换为轮廓内部填充,同时可加入噪声过滤优化效果:
修改后的固定颜色填充代码
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread(r'image.png') img_copy = img.copy() black_MIN = np.array([0, 0, 0], np.uint8) black_MAX = np.array([179, 50, 100], np.uint8) hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) frame_threshed = cv2.inRange(hsv_img, black_MIN, black_MAX) contours, hierarchy = cv2.findContours(frame_threshed, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for idx, c in enumerate(contours): area = cv2.contourArea(c) # 过滤过小的噪声轮廓,阈值根据实际图像调整 if area < 50: continue # 直接填充轮廓内部,-1表示填充模式 cv2.drawContours(img_copy, [c], 0, (0,252,213), -1) plt.imshow(img_copy[:,:,::-1]) plt.show()
关键修改点
- 用
cv2.drawContours替代cv2.rectangle,通过参数-1实现轮廓内部填充 - 增加面积过滤,避免填充细碎噪声点
- 可选:若需区分外轮廓和内部孔洞,可通过层级判断:
if hierarchy[0][idx][3] != -1(表示当前轮廓是父轮廓的子轮廓,即孔洞),只填充这类轮廓
基于邻域像素的智能填充(更贴合需求)
如果需要用孔洞周围的像素颜色自动填充,可使用cv2.inpaint函数:
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread(r'image.png') black_MIN = np.array([0, 0, 0], np.uint8) black_MAX = np.array([179, 50, 100], np.uint8) hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) mask = cv2.inRange(hsv_img, black_MIN, black_MAX) # 膨胀掩码,确保覆盖孔洞边缘细节 mask = cv2.dilate(mask, np.ones((3,3), np.uint8), iterations=1) # 基于邻域像素修复孔洞,INPAINT_TELEA算法效果更自然 inpainted_img = cv2.inpaint(img, mask, 3, cv2.INPAINT_TELEA) plt.imshow(inpainted_img[:,:,::-1]) plt.show()
内容的提问来源于stack exchange,提问作者xionxavier
相关产品推荐
相关产品推荐

