0

我想从图像中获取每个圆圈的阴影值。

  1. 我尝试使用HoughCircle.
  2. 我得到每个圆圈的中心。
  3. 我把文字(圆圈数字)放在一个圆圈里。
  4. 我设置像素子集以获取着色值并计算平均着色值。
  5. 我想以 CSV 格式获取圆数、中心坐标和平均着色值的结果。

但是,在第三步中,圈数是随机分配的。所以,很难找到圈数。

如何按顺序对圆圈进行编号?

在此处输入图像描述

# 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()
4

2 回答 2

1

您可以根据它们的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
于 2017-05-03T09:13:48.953 回答
1

你的代码中的错误是你的数字取决于list返回的圆圈的顺序cv2.HoughCircles,可以是随机的,所以在这种情况下我会做的是设计一个公式,将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))
于 2017-05-03T08:13:44.363 回答