准确检测实心圆并分配唯一 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()
一种检测和过滤实心圆的可能解决方案是:
- 阈值 图片来自 Otsu
- 获取连通分量
- 根据纵横比和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
我想检测一个实心圆并获取该圆的值,例如第一个圆的值为 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()
一种检测和过滤实心圆的可能解决方案是:
- 阈值 图片来自 Otsu
- 获取连通分量
- 根据纵横比和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