基于OpenCV提取白纸上手绘圆圈内部内容的实现方法咨询
去除背景噪声、提取白纸区域实现方案(基于OpenCV Python)
以下是可直接落地的实现步骤:
- 第一步:预处理降噪
先将原始图像转为灰度图,再做高斯模糊过滤拍摄引入的细微噪点,避免后续阈值分割出现误判。
示例代码:
import cv2 import numpy as np # 读取原始图像 img = cv2.imread("input.jpg") # 转灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 高斯模糊降噪 blurred = cv2.GaussianBlur(gray, (5, 5), 0)
- 第二步:二值化分割白纸与背景
利用白纸亮度高于桌面背景的特性,用自适应阈值做分割,适配拍摄时光照不均匀的场景,比固定阈值鲁棒性更高。
示例代码:
# 自适应阈值二值化,前景(非白纸区域)设为白色,背景设为黑色 thresh = cv2.adaptiveThreshold( blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2 ) # 光照均匀场景可替换为大津阈值,无需手动调阈值参数 # ret, thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
- 第三步:形态学操作清理二值图
用开闭运算组合,填补白纸区域的微小孔洞,同时清除背景里的细碎噪点。
示例代码:
kernel = np.ones((3, 3), np.uint8) # 闭运算填补白纸区域孔洞 closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2) # 开运算清除背景小噪点 opened = cv2.morphologyEx(closed, cv2.MORPH_OPEN, kernel, iterations=2)
- 第四步:筛选白纸轮廓
提取所有外部轮廓,面积最大的轮廓即为白纸区域,过滤掉背景细碎轮廓。
示例代码:
contours, hierarchy = cv2.findContours(opened, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 取面积最大的轮廓作为白纸轮廓 paper_contour = max(contours, key=cv2.contourArea)
- 第五步:提取白纸区域
生成掩码,仅保留白纸轮廓内的像素,如有拍摄导致的透视形变,可额外做透视变换将白纸矫正为正矩形。
示例代码:
# 生成白纸区域掩码 mask = np.zeros_like(gray, dtype=np.uint8) cv2.drawContours(mask, [paper_contour], -1, 255, -1) # 抠出白纸区域 paper_region = cv2.bitwise_and(img, img, mask=mask) # 保存提取结果 cv2.imwrite("paper_region.jpg", paper_region)
补充优化点:如果需要矫正透视形变,可先用
cv2.approxPolyDP拟合白纸的四个角点,再调用cv2.getPerspectiveTransform和cv2.warpPerspective完成矫正,后续检测圆圈的准确率会更高。
内容的提问来源于stack exchange,提问作者Bin Chen
相关产品推荐
相关产品推荐

