首页 > 解决方案 > opencv - OMR -Python - 排序问题

问题描述

我编写了一个脚本,它应该拍摄一张扫描的图像并检查调查结果。我已经设法让它识别调查选项框并确定在页面上选中了哪个选项框。

问题:我希望能够根据索引确定哪个框已打勾。因此,在下面的示例中,我有选项 1-5,数字 2 被勾选,但是由于某种原因,我的框的顺序在我的列表中混淆了,在控制台输出中它表明复选框 5 是票。我需要这个来正确告诉我复选框 2 已选中,以便我可以继续存储/分析完整调查的信息

import os
import sys
import cv2

if os.path.isfile(file_path):

    # read the image
    img = cv2.imread(file_path, 1)
    # convert to gray
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # obtain inverse binary image
    _, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
    # find contours
    _, contours, hierarchy = cv2.findContours(binary, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)

    # select contours having a parent contour and append them to a list
    contour_list = []

    for h in hierarchy[0]:
        if h[0] > -1 and h[2] > -1:
            contour_list.append(h[2])

    print str(len(contour_list))+" contours found"

    # copy original image
    img2 = img.copy()

    a = 0
    # calculate the average size of contour and use this rough size for assuming we have a checkbox
    for j, i in enumerate(contour_list):
        a = a + cv2.contourArea(contours[i])
    mean_area = int(a / len(contour_list))

    boxes_found = 0
    options = 0
    answer = 0

    # draw those contours
    for cnt in contour_list:
        # if contour roughly matches our average size
        if (cnt > 0) & (cv2.contourArea(contours[cnt]) > mean_area):
            # print len(contours[cnt])
            options += 1
            answer += 1
            if len(contours[cnt]) > 210:
                # larger contour length signifies a tick
                cv2.drawContours(img2, [contours[cnt]], -1, (0, 255, 0), 2)
                print "option: "+str(options)+" ticked"
                # print str(options) + " options"
                # options = 0
            else:
                cv2.drawContours(img2, [contours[cnt]], -1, (0, 255, 255), 2)

            boxes_found += 1


    cv2.imshow('img2', img2)
    cv2.waitKey(0)

    print "Boxes found: " + str(boxes_found)

else:
    print "no file"

原图: 在此处输入图像描述

当前输出图像: 在此处输入图像描述

控制台输出:

6 contours found
option: 5 ticked
Boxes found: 5

标签: pythonopencvimage-processingcomputer-visionoptical-mark-recognition

解决方案


这篇文章findContours从图像底部找到轮廓。因此,在这种情况下,对象从左到右排序,您需要根据它们的x坐标来识别它们。

接受你所拥有的[contours[cnt]]价值观

cv2.drawContours(img2, [contours[cnt]], -1, (0, 255, 0), 2)

并且订单中的位置应该很容易出现。


推荐阅读