为了账号安全,请及时绑定邮箱和手机立即绑定

区分圆圈和单选按钮 Opencv python

区分圆圈和单选按钮 Opencv python

一只斗牛犬 2023-09-26 15:07:13
我的任务是检测图像中的圆圈和单选按钮。为此,我通过使用不同的参数尝试了霍夫圆。问题:如果图像中的圆圈与单选按钮的半径相同,则两者都会被检测到,但在我们的情况下,它应该只检测到一个。有没有办法区分圆圈和单选按钮(当未选中它们时)。现在我用半径限制它们,有两种不同的功能,一种用于圆形,一种用于单选按钮。上面的代码是针对圆的    circle_contours=[]    # Converting the image Gray scale    gray = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)    # Blur the image to reduce noise    img_blur = cv2.medianBlur(gray, 5)    # Apply hough transform on the image    circles = cv2.HoughCircles(img_blur, cv2.HOUGH_GRADIENT, 1,20, param1=50, param2=20,     minRadius=11, maxRadius=21)    # Draw detected circles    if circles is not None:       circles = np.uint16(np.around(circles))    for i in circles[0, :]:       # Draw outer circle       cv2.circle(image1, (i[0], i[1]), i[2], (34, 255, 34), 2)       circle_contours.append(circles)我对单选按钮使用了类似的方法,但参数不同,如下所示。    radio_buttons= cv2.HoughCircles(img_blur, cv2.HOUGH_GRADIENT, 1,20, param1=50, param2=16,     minRadius=9, maxRadius=10)原始图像图片1:图片2:对于 Image1,它正确检测到圆圈,当它传递到单选按钮功能时,它还会为其内部绘制半径减小的圆圈(Image2),这些圆圈也被检测为单选按钮在Image3 Image3 中,它必须检测圆形和单选按钮,而我的代码只能检测圆形。我也尝试过使用绘制轮廓,但当图像也有复选框时会出现问题。有没有其他方法或者更好的检测方法?
查看完整描述

1 回答

?
RISEBY

TA贡献1856条经验 获得超5个赞

  1. 找到并画出答题卡中的所有轮廓。


  1. 申请HoughCircles


步骤#1:我们可以从找到给定答卷中的所有轮廓开始。

  • contourIdx=-1意思是画出所有的轮廓。

import cv2

import numpy as np


image = cv2.imread('zip_grade_form.png')


# Converting the image Gray scale

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)


ret, thresh = cv2.threshold(src=gray, thresh=127, maxval=255, type=0)


contours, hierarchy = cv2.findContours(image=thresh,

                                       mode=cv2.RETR_TREE,

                                       method=cv2.CHAIN_APPROX_SIMPLE)


gray = cv2.drawContours(image=gray, contours=contours, contourIdx=-1,

                     color=(255, 255, 255), thickness=2)

结果:

https://img3.sycdn.imooc.com/651283990001d13404320554.jpg

  • 从上面我们可以看到,除了圆圈之外的所有特征都被删除了。我们使用该findContours方法来删除不需要的伪影。

步骤#2:申请HoughCircles。您在问题上编写的代码相同。结果:

https://img4.sycdn.imooc.com/651283af0001ea9204330554.jpg

代码:

import cv2

import numpy as np


image = cv2.imread('zip_grade_form.png')


# Converting the image Gray scale

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)


ret, thresh = cv2.threshold(src=gray, thresh=127, maxval=255, type=0)


contours, hierarchy = cv2.findContours(image=thresh,

                                       mode=cv2.RETR_TREE,

                                       method=cv2.CHAIN_APPROX_SIMPLE)


gray = cv2.drawContours(image=gray, contours=contours, contourIdx=-1,

                        color=(255, 255, 255), thickness=2)


cv2.imwrite("gray.png", gray)


img_blur = cv2.medianBlur(gray, 5)

circles = cv2.HoughCircles(img_blur, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=16,

                           minRadius=9, maxRadius=10)


circle_contours = []


if circles is not None:

    circles = np.uint16(np.around(circles))

    for i in circles[0, :]:

        # Draw outer circle

        cv2.circle(image, (i[0], i[1]), i[2], (108, 105, 255), 2)

        circle_contours.append(circles)



cv2.imwrite("circles.png", image)

更新

  • 为了检测复选框和单选按钮,您需要计算contour-perimeter(p) 和contour-approximation(a)。

  • 我们可以使用pa值来分隔每个对象,因为每个对象都有唯一的pa值。

  • 例如,在图像 3 中,

    • 复选框:p= 73 和a= 4

    • 单选按钮:p= 64 和a= 8。

  • 您可以通过观察代码找到这些值。

  • 再次应用第一步。

    • 结果:

https://img3.sycdn.imooc.com/651283c60001396203860556.jpg

现在找到上图中的轮廓:


if len(approx) == 8 and int(p) == 64:

    cv2.drawContours(image, [c], -1, (180, 105, 255), 3)

elif len(approx) == 4 and int(p) == 73:

    cv2.drawContours(image, [c], -1, (180, 105, 255), 3)

结果:

https://img4.sycdn.imooc.com/651283d2000186ef03870554.jpg

代码:


import cv2


from imutils import grab_contours as grb_cns

from imutils import resize as rsz


image = cv2.imread('K1Z94.png')


# Converting the image Gray scale

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)


ret, thresh = cv2.threshold(src=gray, thresh=127, maxval=255, type=0)


contours, hierarchy = cv2.findContours(image=thresh.copy(),

                                        mode=cv2.RETR_TREE, 

                                         method=cv2.CHAIN_APPROX_SIMPLE)


gray = cv2.drawContours(image=gray, contours=contours, contourIdx=-1, color=(255, 255, 255), thickness=2)



resized = rsz(gray, width=300)

ratio = gray.shape[0] / float(gray.shape[0])


canny = cv2.Canny(gray, 50, 200)


thresh = cv2.threshold(src=canny, thresh=60, maxval=255,

                   type=cv2.THRESH_OTSU + cv2.THRESH_BINARY)[1]


cns = cv2.findContours(image=thresh.copy(), mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)


cns = grb_cns(cns)


for c in cns:

     p = cv2.arcLength(c, True)  # perimeter

     approx = cv2.approxPolyDP(c, 0.04 * p, True)


     M = cv2.moments(c)


     # check if the all values of M are 0.

     all_zr = all(value == 0 for value in M.values())


     if not all_zr:

         cX = int((M["m10"] / M["m00"]))

         cY = int((M["m01"] / M["m00"]))

         c = c.astype("float")

         c *= ratio

         c = c.astype("int")


         # Circles: (radio-buttons)

         if len(approx) == 8 and int(p) == 64:

             cv2.drawContours(image, [c], -1, (180, 105, 255), 3)

         elif len(approx) == 4 and int(p) == 73:

             cv2.drawContours(image, [c], -1, (180, 105, 255), 3)


  cv2.imwrite("result.png", image)


查看完整回答
反对 回复 2023-09-26
  • 1 回答
  • 0 关注
  • 88 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信