在图像中找到所有的圆形

6

我是一个新手,对于Python和图像处理不太熟悉。我正在做一个爱好项目,想要在图像中找到所有的圆,并找出其中有'X'标记的圆。我已经写了一些代码来找圆(如下所示)。它可以在一个图像上工作,但无法识别另一个图像中的所有圆。请指导我如何改进find_circles算法的性能。

测试图像:

test image

结果图像:

result image

import cv2
import cv
import numpy as np
import operator
from PIL import Image

def find_circles(img):
    im_gray = cv2.imread(img, cv2.CV_LOAD_IMAGE_GRAYSCALE)
    (thresh, im_bw) = cv2.threshold(im_gray, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
    img_bw = cv2.threshold(im_gray, thresh, 255, cv2.THRESH_BINARY)[1]
    cv2.imwrite('img_bw.png',img_bw)
    rows, cols =img_bw.shape
    circles = cv2.HoughCircles(img_bw,cv.CV_HOUGH_GRADIENT,1,rows/32, param1=100,param2=40,minRadius=0,maxRadius=100)
    circles = np.uint16(np.around(circles))
    return circles

def draw_circles(img, circles):
    img = cv2.imread(img,0)
    cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
    for i in circles[0,:]:
    # draw the outer circle
        cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
        # draw the center of the circle
        cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
        cv2.putText(cimg,str(i[0])+str(',')+str(i[1]), (i[0],i[1]), cv2.FONT_HERSHEY_SIMPLEX, 0.4, 255)
    return cimg 

def main():
    img = "query_circle9.png"
    circles = find_circles(img)
    img_circle = draw_circles(img,circles)
    cv2.imwrite('cricle.png',img_circle) 

if __name__=='__main__':
    main()

提供有问题的图片链接会很有帮助。 - John1024
您能否同时发布一下有问题的图片的 _原始链接_? - John1024
最好能提供未经处理的图像,是吧 ;) - Micka
1个回答

7
#!/usr/bin/env python

import cv2

def draw_circles(img, circles):
    # img = cv2.imread(img,0)
    cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
    for i in circles[0,:]:
    # draw the outer circle
        cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
        # draw the center of the circle
        cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
        cv2.putText(cimg,str(i[0])+str(',')+str(i[1]), (i[0],i[1]), cv2.FONT_HERSHEY_SIMPLEX, 0.4, 255)
    return cimg

def detect_circles(image_path):
    gray = cv2.imread(image_path, cv2.CV_LOAD_IMAGE_GRAYSCALE)
    gray_blur = cv2.medianBlur(gray, 13)  # Remove noise before laplacian
    gray_lap = cv2.Laplacian(gray_blur, cv2.CV_8UC1, ksize=5)
    dilate_lap = cv2.dilate(gray_lap, (3, 3))  # Fill in gaps from blurring. This helps to detect circles with broken edges.
    # Furture remove noise introduced by laplacian. This removes false pos in space between the two groups of circles.
    lap_blur = cv2.bilateralFilter(dilate_lap, 5, 9, 9)
    # Fix the resolution to 16. This helps it find more circles. Also, set distance between circles to 55 by measuring dist in image.
    # Minimum radius and max radius are also set by examining the image.
    circles = cv2.HoughCircles(lap_blur, cv2.cv.CV_HOUGH_GRADIENT, 16, 55, param2=450, minRadius=20, maxRadius=40)
    cimg = draw_circles(gray, circles)
    print("{} circles detected.".format(circles[0].shape[0]))
    # There are some false positives left in the regions containing the numbers.
    # They can be filtered out based on their y-coordinates if your images are aligned to a canonical axis.
    # I'll leave that to you.
    return cimg

结果如下:
cimg = detect_circles("circles.png")

检测的圆

有一些误检测的结果。如果你的图片已经对齐,那么你可以根据它们的y坐标来过滤这些错误的检测结果。我会把这个交给你处理。


谢谢你的帮助! - user1146904
不客气。我认为你还面临着许多挑战。你会发现算法对于平滑图像等参数非常敏感。即使它看起来对这个图像工作得很好,但可能对其他图像无效。根据你的背景,我建议考虑结合机器学习来验证圆形,并使用启发式方法(单独或在优化框架中)如每行和每列的圆数来进一步完善它们。如果你有类似的问题,请随时联系我。祝你好运 :)。 - lightalchemist
我遇到了一个错误:AttributeError: module 'cv2.cv2' has no attribute 'cv'。如何纠正它?谢谢。 - ah bon
@ahbon 这段代码是在2014年编写的,当时OpenCV版本还停留在2.0+。似乎自从OpenCV 3.0以后,HOUGH_GRADIENT常量已经被移动到了cv2命名空间中,因此现在应该写成cv2.HOUGH_GRADIENT(即在cv2之后去掉cv)。 - lightalchemist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接