如何使用 python 以特定顺序对圆圈进行编号?
How can I number circles in a certain order using python?
我想从图像中获取每个圆圈的阴影值。
- 我尝试使用
HoughCircle
检测圆圈。
- 我得到了每个圆的圆心。
- 我把文字(圆圈数字)放在一个圆圈里。
- 我设置像素子集来获取明暗值并计算平均明暗值。
- 我想获得 CSV 格式的圆数、圆心坐标和平均阴影值的结果。
但是,在第 3 步中,圈数是随机分配的。所以,很难找到圈数。
如何在一个序列中给圆圈编号?
# 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()
你的代码中的错误是你的数字取决于从 cv2.HoughCircles
返回的 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))
您可以根据 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)
此外,使用 Python 的 CSV 库将条目写入输出文件更容易。这样您就不需要将每个条目转换为字符串并在每个条目之间添加逗号。 enumerate()
可用于自动计算每个圆圈。 getTextSize()
还可用于确定要打印的文本的尺寸,使您能够将其置于矩形的中心。
这将为您提供如下输出:
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
我想从图像中获取每个圆圈的阴影值。
- 我尝试使用
HoughCircle
检测圆圈。 - 我得到了每个圆的圆心。
- 我把文字(圆圈数字)放在一个圆圈里。
- 我设置像素子集来获取明暗值并计算平均明暗值。
- 我想获得 CSV 格式的圆数、圆心坐标和平均阴影值的结果。
但是,在第 3 步中,圈数是随机分配的。所以,很难找到圈数。
如何在一个序列中给圆圈编号?
# 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()
你的代码中的错误是你的数字取决于从 cv2.HoughCircles
返回的 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))
您可以根据 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)
此外,使用 Python 的 CSV 库将条目写入输出文件更容易。这样您就不需要将每个条目转换为字符串并在每个条目之间添加逗号。 enumerate()
可用于自动计算每个圆圈。 getTextSize()
还可用于确定要打印的文本的尺寸,使您能够将其置于矩形的中心。
这将为您提供如下输出:
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