如何使用Python OpenCV检测和查找表单中的复选框?

12

我有几张图片需要使用计算机视觉检测复选框并进行OMR。

我正在使用findContours仅在扫描文档中的复选框上绘制轮廓。但该算法会提取文本的每一个轮廓。

from imutils.perspective import four_point_transform
from imutils import contours
import numpy as np
import argparse, imutils, cv2, matplotlib
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

image = cv2.imread("1.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(blurred, 75, 200)

im_test = [blurred, cv2.GaussianBlur(gray, (7, 7), 0), cv2.GaussianBlur(gray, (5, 5), 5), cv2.GaussianBlur(gray, (11, 11), 0)]
im_thresh = [ cv2.threshold(i, 127, 255, 0)  for i in im_test ]
im_thresh_0 = [i[1] for i in im_thresh ]
im_cnt = [cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0] for thresh in im_thresh_0]

im_drawn = [cv2.drawContours(image.copy(), contours, -1, (0,255,0), 1) for contours in im_cnt]

plt.imshow(im_drawn[0])
plt.show()

输入图像:

enter image description here


您可以在 https://dev59.com/grzpa4cB1Zd3GeqPDxID#62801071 查看我的答案,针对相同类型的问题。 - Sreekiran A R
2个回答

10
  1. 获取二进制图像。 加载图像灰度化高斯模糊Otsu自适应阈值分割以获取二进制黑白图像。

  2. 去除小的噪点。 查找轮廓并使用轮廓面积筛选来消除噪声。

  3. 修复复选框的水平和垂直墙壁。 这一步是可选的,但在复选框可能损坏的情况下,我们会修复墙壁以便更容易检测。思路是创建一个 矩形核 然后进行形态学操作

  4. 检测复选框。 从这里开始,我们找到轮廓,获取边界矩形坐标,并使用 图形近似 + 宽高比进行筛选。 复选框本质上是一个正方形,因此其轮廓尺寸应该在一定范围内。


输入图像 -> 二进制图像

已检测出的复选框已用绿色突出显示

enter image description here

复选框:52

另一个输入图像 -> 二进制图像

已检测出的复选框已用绿色突出显示

enter image description<pre class=import cv2 # Load image, convert to grayscale, Gaussian blur, Otsu's threshold image = cv2.imread('1.jpg') original = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (3,3), 0) thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] # 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 checkbox_contours = [] 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.035 * peri, True) x,y,w,h = cv2.boundingRect(approx) aspect_ratio = w / float(h) if len(approx) == 4 and (aspect_ratio >= 0.8 and aspect_ratio <= 1.2): cv2.rectangle(original, (x, y), (x + w, y + h), (36,255,12), 3) checkbox_contours.append(c) print('Checkboxes:', len(checkbox_contours)) cv2.imshow('thresh', thresh) cv2.imshow('repair', repair) cv2.imshow('original', original) cv2.waitKey()


谢谢。但是当我在真实数据上尝试代码时,它仍然无法正常工作。尝试调整阈值和近似长度。输入图像:https://imgur.com/LrzYXga - Shivam Chaurasia
它对我有效,可以尝试将threshold_max_area更改为3000。我已经添加了这个新输入图像的输出。 - nathancy
1
@nathancy,这看起来很棒。但是,有没有办法识别一个框是否被选中? - Kalaschnik
@Kalaschnik,是同样的问题,你找到任何解决方法了吗? - gig
基于复选框大小相同的假设,识别已选中框的一个想法是:1)获取复选框轮廓2)计算白色像素的数量(或许使用cv2.countNonZero),并将其与基准值进行比较,或者只需比较像素百分比。因此,如果白色像素百分比为80%,则未选中,否则为选中。 - nathancy

3

每个文档都有不同区域的复选框,其中一些水平、垂直或与文本组合对齐。此外,我正在构建的解决方案需要是无模板的。 - Shivam Chaurasia
这是一个形状检测器的示例,您可以使用该示例仅检测正方形(勾选框):https://www.pyimagesearch.com/2016/02/08/opencv-shape-detection/希望能对您有所帮助... - ThiagoRTK
已经参考了那个例子和StackOverflow上的许多线程,但我仍然无法找到如何避免文本区域的方法。 - Shivam Chaurasia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接