如何使用 Python OpenCV 通过去除噪声来检测复选框?

How to detect checkboxes by removing noise using Python OpenCV?

我正在尝试识别图像中的复选框

已识别前 4 个,但未识别后 2 个。同时,我希望能够去掉胡椒粉以避免误报,因为其他文档的复选标记要小得多。我已经尝试了各种膨胀和内核大小,但我一直无法成功获得盒子。

我试过先膨胀再腐蚀

kernel = np.ones((2, 2), np.uint8)
image_dilat = cv2.dilate(image, kernel, iterations=1)
kernel = np.ones((4, 4), np.uint8)
image_erosion = cv2.erode(image_dilat2, kernel, iterations=1)

我也试过变形

kernel = np.ones((3, 3), np.uint8)
image = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel, iterations=1)
kernel = np.ones((3, 3), np.uint8)
image = cv2.morphologyEx(image, cv2.cv2.MORPH_CLOSE, , kernel, iterations=1)

如有任何建议,我们将不胜感激。

这是一种使用简单图像处理的潜在方法:

  1. 获取二值图像。加载图像,转换为灰度,Otsu的阈值。

  2. 去除噪声的小像素。找到轮廓并使用轮廓区域过滤过滤掉噪声。我们通过用黑色“绘制”轮廓来有效地去除噪声。

  3. 修复复选框墙。从这里我们创建一个水平和垂直修复内核,然后执行形态学关闭以修复复选框墙中的任何孔。

  4. 检测复选框。接下来在修复后的图像上找到轮廓,然后使用形状近似和纵横比过滤来过滤复选框轮廓。这个想法是复选框是一个正方形,应该具有大致相同的宽度和高度。


带噪点的二值图像->去除了微小的噪点

修复了复选框墙 -> 检测到复选框

代码

import cv2

# Load image, convert to grayscale, Otsu's threshold
image = cv2.imread('1.png')
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
cv2.imshow('thresh before', thresh)

# Find contours and filter using contour area filtering to remove noise
cnts, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:]
AREA_THRESHOLD = 10
for c in cnts:
    area = cv2.contourArea(c)
    if area < AREA_THRESHOLD:
        cv2.drawContours(thresh, [c], -1, 0, -1)

# Repair checkbox horizontal and vertical walls
repair_kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5,1))
repair = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, repair_kernel1, iterations=1)
repair_kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (1,5))
repair = cv2.morphologyEx(repair, cv2.MORPH_CLOSE, repair_kernel2, iterations=1)

# Detect checkboxes using shape approximation and aspect ratio filtering
cnts, _ = cv2.findContours(repair, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2:]
for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.05 * peri, True)
    x,y,w,h = cv2.boundingRect(approx)
    aspect_ratio = w / float(h)
    if aspect_ratio > 0.9 and aspect_ratio < 1.1:
        cv2.rectangle(original, (x, y), (x + w, y + h), (36,255,12), 3)

cv2.imshow('thresh', thresh)
cv2.imshow('repair', repair)
cv2.imshow('original', original)
cv2.waitKey()

注意:假设复选框是方形的,并且没有噪声重叠在复选框上。根据图像的不同,您可能需要添加另一层轮廓区域过滤以确保您不会得到误报。