准确检测实心圆并分配唯一 ID?

Detect Filled circle accurately and assign unique id?

我想检测一个实心圆并获取该圆的值,例如第一个圆的值为 1 并携带一个。我附上了圆圈下方的图像,将用黑色或蓝色笔填充。圆的大小非常小,所以基本上我正在尝试的是我只想要特定的实心圆值,然后将其保存到数据库中。 现在它的值是 1 或 2,但有时它的值是 1 或者有时有一些像 APPLE 等的世界...... [1]: https://i.stack.imgur.com/gu2Go.png

import numpy as np
import cv2
import math
img = cv2.imread("small.jpg",0)
img = cv2.medianBlur(img,5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
circles =cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,60,param1=50,param2=30,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
counter=0
correctC=[]
xC=[]
yC=[]
for i in circles[0,:]: 
 #cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
 #cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),2)
 cv2.putText(cimg,str(i[0])+","+str(i[1])+","+str(i[2]),(i[0],i[1]), cv2.FONT_HERSHEY_SIMPLEX, 0.3,(255,0,0),1,cv2.LINE_AA)
 correctC.append((i[0],i[1],i[2]))
 xC.append(i[0])
 yC.append(i[1])
 counter+=1

print "Circle Count is : " + str(counter)

xCS=sorted(xC)
yCS=sorted(yC)
xS=sorted(correctC, key=lambda correctC:correctC[0])

q1=sorted(xS[:4],key=lambda correctC: correctC[1])
q2=sorted(xS[4:8],key=lambda correctC: correctC[1])
q3=sorted(xS[8:12],key=lambda correctC: correctC[1])
q4=sorted(xS[12:16],key=lambda correctC: correctC[1])
q5=sorted(xS[16:20],key=lambda correctC: correctC[1])
q6=sorted(xS[20:24],key=lambda correctC: correctC[1])
q7=sorted(xS[24:28],key=lambda correctC: correctC[1])
q8=sorted(xS[28:32],key=lambda correctC: correctC[1])
q9=sorted(xS[32:],key=lambda correctC: correctC[1])

sortedTmp=[q1,q2,q3,q4,q5,q6,q7,q8,q9]
sorted=[]

for i in sortedTmp:
  for j in i:
    sorted.append(j)

for i in range(36):
 cv2.putText(cimg,str(i),(sorted[i][0],sorted[i][1]), cv2.FONT_HERSHEY_SIMPLEX, 1,(255,0,0),3,cv2.LINE_AA)

cv2.imshow('detected circles',cimg)
cv2.waitKey(0)
cv2.destroyAllWindows()

一种检测和过滤实心圆的可能解决方案是:

  1. 阈值 图片来自 Otsu
  2. 获取连通分量
  3. 根据纵横比blob边界框与blob面积的差异搜索目标blob - 差异应该比较小。

让我们看看代码:

# Imports:
import numpy as np
import cv2

# Image path:
fileName = "gu2Go.png"
path = "D://opencvImages//"

# Read image:
inputImage = cv2.imread(path + fileName)

# To Grayscale:
grayscaleImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)

# Threshold:
_, binaryImage = cv2.threshold(grayscaleImage, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)

# Get Connected Components:
output = cv2.connectedComponentsWithStats(binaryImage, 8, cv2.CV_32S)
(numLabels, labels, stats, centroids) = output

现在,让我们遍历所有连接的组件(blob)并根据纵横比进行过滤(圆圈似乎具有相同的高度和宽度,它们的纵横比应该接近 1.0)和blob 的边界框和 blob 的区域之间的差异。假设您有实心圆的边界矩形。如果减去斑点的面积实际面积,因为它们的比例大致相同,差异应该很小。肯定小于空心圆的外接矩形与其面积之差:

# Store target bounding boxes here:
boundingBoxes = []

# Loop through connected components:
for i in range(1, numLabels):

    # Get blob properties:
    x = stats[i, cv2.CC_STAT_LEFT]
    y = stats[i, cv2.CC_STAT_TOP]
    w = stats[i, cv2.CC_STAT_WIDTH]
    h = stats[i, cv2.CC_STAT_HEIGHT]
    blobArea = stats[i, cv2.CC_STAT_AREA]
    (cX, cY) = centroids[i]

    # Get bounding box area:
    boxArea = w * h

    # Compute area difference
    areaDifference = boxArea - blobArea
    # Compute aspect ratio:
    aRatio = w / h

    # Set blob filter:
    minAreaDifference = 800
    minAspectRatio = 0.9
    maxAspectRatio = 1.1

    # Default color is red:
    color = (0, 0, 255)

    if areaDifference < minAreaDifference:
        if aRatio > minAspectRatio and aRatio < maxAspectRatio:
            # Got target blob
            # Color is now blue:
            color = (255, 0, 0)
            # Store bounding box in list:
            boundingBoxes.append((x, y, w, h))

    # Draw rectangle:
    cv2.rectangle(inputImage, (x, y), (x + w, y + h), color, 3)

# Show the results of the filter:
cv2.imshow("Bounding Rects", inputImage)

结果应该用蓝色边界矩形为实心圆着色,其余为红色边界矩形。请注意,我已将目标 blob 边界矩形存储在名为 boundingBoxes:

的列表中

首先非常感谢您的回答。但是问题是当我把全图放到OpenCV里面的时候,我的图是从底部截下来的,意思是全图没有设置全图canvas,我想全图开全图canvas然后检测填充框。我在下面附上我的结果截图以及我的模板。

我的结果截图: my result screenshot

我正在尝试的是我尝试以高质量调整此图像的大小并将其放入 canvas 然后尝试检测填充的框然后为每个检测框提供唯一 ID 以获得价值。所以我的方案是我会给每个唯一的 ID 一些值,然后例如如果 ID 一个盒子被填充然后给那个盒子一个值。

我原来的模板:Original template