[英]How can I number circles in a certain order using python?
I want to get the shade value of each circles from an image. 我想从图像中获取每个圆圈的阴影值。
HoughCircle
. HoughCircle
检测圆。 But, in the 3rd step, the circle numbers were randomly assigned. 但是,在第三步中,圈号是随机分配的。 So, it's so hard to find circle number.
因此,很难找到圈号。
How can I number circles in a sequence? 如何按顺序编号圆圈?
# USAGE
# python detect_circles.py --image images/simple.png
# import the necessary packages
import numpy as np
import argparse
import cv2
import csv
# define a funtion of ROI calculating the average value in specified sample size
def ROI(img,x,y,sample_size):
Each_circle=img[y-sample_size:y+sample_size, x-sample_size:x+sample_size]
average_values=np.mean(Each_circle)
return average_values
# open the csv file named circles_value
circles_values=open('circles_value.csv', 'w')
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True, help = "Path to the image")
args = vars(ap.parse_args())
# load the image, clone it for output, and then convert it to grayscale
image = cv2.imread(args["image"])
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# detect circles in the image
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.2,50, 100, 1, 1, 20, 30)
# ensure at least some circles were found
if circles is not None:
# convert the (x, y) coordinates and radius of the circles to integers
circles = np.round(circles[0, :]).astype("int")
number=1
font = cv2.FONT_HERSHEY_SIMPLEX
# loop over the (x, y) coordinates and radius of the circles
for (x, y, r) in circles:
# draw the circle in the output image, then draw a rectangle
# corresponding to the center of the circle
number=str(number)
cv2.circle(output, (x, y), r, (0, 255, 0), 4)
cv2.rectangle(output, (x - 10, y - 10), (x + 10, y + 10), (0, 128, 255), -1)
# number each circle, but its result shows irregular pattern
cv2.putText(output, number, (x,y), font,0.5,(0,0,0),2,cv2.LINE_AA)
# get the average value in specified sample size (20 x 20)
sample_average_value=ROI(output, x, y, 20)
# write the csv file with number, (x,y), and average pixel value
circles_values.write(number+','+str(x)+','+str(y)+','+str(sample_average_value)+'\n')
number=int(number)
number+=1
# show the output image
cv2.namedWindow("image", cv2.WINDOW_NORMAL)
cv2.imshow("image", output)
cv2.waitKey(0)
# close the csv file
circles_values.close()
The mistake in your code is that your number is dependent upon the order of circles in list
returned from cv2.HoughCircles
which can be random, So what I would have done in this situation is to devise a formula which would convert the center(x, y)
value of each circle to an ID, and the same circle would yield same ID given its center position remains same: 您代码中的错误是您的数字取决于
cv2.HoughCircles
list
返回的list
的圆圈顺序,它可以是随机的,因此在这种情况下,我要做的是设计一个公式来转换center(x, y)
将每个圆的值赋予一个ID,鉴于其中心位置相同,相同的圆将产生相同的ID:
def get_id_from_center(x, y):
return x + y*50
for (x, y, r) in circles:
number = str(get_id_from_center(x, y))
You could sort your circles based on their x, y
values, the width of the image and a rough line height, for example: 您可以根据圆的
x, y
值,图像的宽度和粗线高度对圆进行排序,例如:
import numpy as np
import argparse
import cv2
import csv
# define a funtion of ROI calculating the average value in specified sample size
def ROI(img,x,y,sample_size):
Each_circle=img[y-sample_size:y+sample_size, x-sample_size:x+sample_size]
average_values=np.mean(Each_circle)
return average_values
# open the csv file named circles_value
with open('circles_value.csv', 'wb') as circles_values:
csv_output = csv.writer(circles_values)
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True, help = "Path to the image")
args = vars(ap.parse_args())
# load the image, clone it for output, and then convert it to grayscale
image = cv2.imread(args["image"])
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# detect circles in the image
circles = cv2.HoughCircles(gray, cv2.cv.CV_HOUGH_GRADIENT, 1.2,50, 100, 1, 1, 20, 30)
# ensure at least some circles were found
if circles is not None:
# convert the (x, y) coordinates and radius of the circles to integers
circles = np.round(circles[0, :]).astype("int")
font = cv2.FONT_HERSHEY_SIMPLEX
height = 40
# loop over the (x, y) coordinates and radius of the circles
for number, (x, y, r) in enumerate(sorted(circles, key=lambda v: v[0] + (v[1] / height) * image.shape[1]), start=1):
text = str(number)
(tw, th), bl = cv2.getTextSize(text, font, 0.5, 2) # So the text can be centred in the circle
tw /= 2
th = th / 2 + 2
# draw the circle in the output image, then draw a rectangle
# corresponding to the center of the circle
cv2.circle(output, (x, y), r, (0, 255, 0), 3)
cv2.rectangle(output, (x - tw, y - th), (x + tw, y + th), (0, 128, 255), -1)
# number each circle, centred in the rectangle
cv2.putText(output, text, (x-tw, y + bl), font, 0.5, (0,0,0), 2, cv2.CV_AA)
# get the average value in specified sample size (20 x 20)
sample_average_value = ROI(output, x, y, 20)
# write the csv file with number, (x,y), and average pixel value
csv_output.writerow([number, x, y, sample_average_value])
# show the output image
cv2.namedWindow("image", cv2.WINDOW_NORMAL)
cv2.imshow("image", output)
cv2.waitKey(0)
Also, it is easier to use Python's CSV library to write entries to your output file. 同样,使用Python的CSV库将条目写入输出文件也更容易。 This way you don't need to convert each entry to a string and add commas between each entry.
这样,您无需将每个条目转换为字符串并在每个条目之间添加逗号。
enumerate()
can be used to count each circle automatically. enumerate()
可用于自动计数每个圆。 Also getTextSize()
can be used to determine the dimensions of the text to be printed enabling you to centre it in the rectangle. getTextSize()
也可用于确定要打印的文本的尺寸,使您可以将其居中放置在矩形中。
This would give you an output as follows: 这将为您提供如下输出:
And a CSV starting as: CSV开头为:
1,2,29,nan
2,51,19,nan
3,107,22,100.72437499999999
4,173,23,102.33291666666666
5,233,26,88.244791666666671
6,295,22,92.953541666666666
7,358,28,142.51625000000001
8,418,26,155.12875
9,484,31,127.02541666666667
10,547,25,112.57958333333333
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.