如何使用OpenCV检测/查找复选框轮廓

时间:2019-04-19 15:03:44

标签: python opencv opencv-contour object-recognition

我有几张图像需要通过计算机视觉检测复选框来执行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

2 个答案:

答案 0 :(得分:2)

由于我们只想检测复选框,所以我们的想法是使用两种过滤方法将所需的复选框与单词分开。在预处理并找到轮廓之后,我们可以遍历每个轮廓并应用滤镜。我们将cv2.contourArea()与最小和最大阈值一起使用,然后使用cv2.approxPolyDP()计算纵横比,因为正方形的纵横比接近1。

要检测图像中的边缘,我们可以使用cv2.Canny(),然后使用cv2.findContours()抓取轮廓,从而生成此图像。注意如何检测到所有轮廓,包括单词和复选框。

enter image description here

接下来,我们遍历每个检测到的轮廓并使用阈值区域和纵横比进行过滤。使用此方法,检测到所有52个复选框。

enter image description here

输出

  

('checkbox_contours',52)

为了防止潜在的误报,我们可以添加第三个过滤器,以确保每个轮廓都有四个点(较高的机会是正方形)。如果输入图像是从某个角度拍摄的,我们可以使用four point transform作为预处理步骤来获得图像的鸟瞰图。

另一个输入图像集

输出

  

('checkbox_contours',2)

代码

import numpy as np
import imutils, cv2

original_image = cv2.imread("1.jpg")
image = original_image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(blurred, 120, 255, 1)

cv2.imshow("edged", edged)

cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

checkbox_contours = []

threshold_max_area = 250
threshold_min_area = 200
contour_image = edged.copy()

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)
    area = cv2.contourArea(c) 
    if area < threshold_max_area and area > threshold_min_area and (aspect_ratio >= 0.9 and aspect_ratio <= 1.1):
        cv2.drawContours(original_image,[c], 0, (0,255,0), 3)
        checkbox_contours.append(c)

print('checkbox_contours', len(checkbox_contours))
cv2.imshow("checkboxes", original_image)
cv2.waitKey(0)

答案 1 :(得分:0)

好吧...复选框始终位于图像的该区域吗?复选框始终在图像上保持相同的大小区域吗?

如果是,则只能在图像的该区域中运行findContours ...

或者模板与多个对象匹配,例如来自OpenCV docs:https://docs.opencv.org/3.4.3/d4/dc6/tutorial_py_template_matching.html