【问题标题】:Detect All Circles in an image (Optical Mark Recognition) using Python OpenCV使用 Python OpenCV 检测图像中的所有圆圈(光学标记识别)
【发布时间】:2021-11-28 14:46:22
【问题描述】:

我需要使用 Python 为我的高中假期项目制作一个 OMR 检测系统(如果它足够可靠,学校可能会在某种程度上使用它),我已经对它进行了大量研究,并且已经尝试了从轮廓到模板匹配的所有内容,我觉得模板匹配工作正常,但它只能检测 OMR 表中的许多圆圈中的一个,有人可以帮我弄清楚如何检测多个(所有)圆圈(不管无论它们是否起泡),在 omr 表和它们各自的坐标中,这对我来说就足够了。

我尝试过的:

import numpy as np
import cv2

img = cv2.resize(cv2.imread('assets/omr_match1.jpg', 0), (0, 0), fx=0.2, fy=0.5)
template = cv2.resize(cv2.imread('assets/circle.jpg', 0), (0, 0), fx=0.2, fy=0.5)
h, w = template.shape

methods = [cv2.TM_CCOEFF, cv2.TM_CCOEFF_NORMED, cv2.TM_CCORR,
            cv2.TM_CCORR_NORMED, cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]

methods=methods[0] 
# This is one among the above which works perfectly

for method in methods:
    img2 = img.copy()

    result = cv2.matchTemplate(img2, template, method)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
        location = min_loc
    else:
        location = max_loc

    bottom_right = (location[0] + w, location[1] + h)
    cv2.rectangle(img2, location,bottom_right, 0, 1)
    cv2.imshow('Match', img2)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

#circle.jpg

见上文,只标记了一个随机圆圈,而不是所有圆圈。

【问题讨论】:

  • 可能发布一些代码或 sudo-code 来描述您尝试过的内容。如果你能找到一个并且你知道你的圆的宽度(以像素为单位),你应该能够通过制作一个网格来对每个人进行罚款。您是否正在转换为灰度和蒙版以仅留下黑色圆圈? stackoverflow.com/questions/63730808/…
  • 通常是一张纸,上面有注册标记(易于检测和定位)和一些条形码(或其他东西)来识别表格。给定这些标记,您将扫描与“模型”对齐,然后“盲目地”对校正扫描应用蒙版……并对圆圈应该是的区域进行采样。您甚至可以尝试将整个扫描页面与整个模型页面(空白、干净、从 PDF 栅格化的图像)进行特征匹配
  • 你只得到了一场比赛——得分最高的一场。你没有得到所有的比赛。例如,请参阅pyimagesearch.com/2021/03/29/…,了解如何获得多个匹配项。
  • 另一种方法是使用 cv2.HoughCircles 获取所有圆圈。
  • 然后他们需要被告知将床单弄松并尽可能平放。 -- 如果这是一个问题,您可以在整个纸张上放置很多注册标记并分段展开。 - 我认为您可以使用页面本身而不是特殊标记。展开将是困难的。 OpenCV 没有提供网格变形的单一功能。你必须自己写。 -- 拍照造成的透视失真不是问题。可以纠正。

标签: python opencv computer-vision object-detection omr


【解决方案1】:

我们开始吧:

import cv2
import numpy as np
from matplotlib import pyplot as plt


img = cv2.imread('/path/tabela_circle.jpg', 0)

template = cv2.imread('/path/circle.jpg', 0)
h, w = template.shape

res = cv2.matchTemplate(img,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
    cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)

cv2.imwrite('res.png',img)

也可以只检测答案:

【讨论】:

  • 嗨,干得好,我正在尝试将 OMR 应用于 tiked box 检测和本地化,你的方法对我不起作用,你知道如何解决这个问题吗? : stackoverflow.com/questions/69706170/… 谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-02
  • 1970-01-01
  • 2011-12-25
相关资源
最近更新 更多