python - 通过同一垂直线中的圆进行圆识别和画线

标签 python opencv

我有一个简单的图像,大约有15个随机放置的圆圈。我的任务是识别圆,然后通过位于同一垂直线上的圆画一条直线。我仍然是OpenCV的初学者。

我最初尝试确定圆圈的位置,并使用以下代码:

image = cv2.imread('circle', 0)
img = cv2.medianBlur(image,5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)

circles = cv2.HoughCircles(image,cv2.HOUGH_GRADIENT, 
1,20,param1=40,param2=20,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
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_imshow(cimg)
cv2.waitKey(0)
cv2.destroyAllWindows()`

这是我得到的输出,对我来说没有任何意义:

enter image description here

请帮助识别圆并通过圆画一条直线。

编辑:输入图像如下所示:

Input

最佳答案

查看您的输入图像后,我怀疑任何圆圈的中心都具有相同的x坐标。因此,我在解决方案中设置了tol公差,允许x坐标之内。然后,通过这些x坐标的平均值绘制最后一行。

通用方法如下:

  • 逆二进制阈值图像,请参阅 cv2.threshold ThresholdTypes ,以在黑色背景上具有白色圆圈,并消除可能的JPG伪像。
  • 找到极端的外部轮廓,请参见 cv2.findContours RetrievalModes
  • 使用 cv2.minEnclosingCircle 查找最小封闭区域的圆心和半径。
  • 通过在如上所述的公差范围内匹配x坐标来找到垂直线。

  • 这是代码:

    import cv2
    import numpy as np
    from skimage import io              # Only needed for web grabbing images, use cv2.imread for local images
    
    # Read image from web
    img = cv2.cvtColor(io.imread('https://i.imgur.com/VQ5Ri0W.jpg'), cv2.COLOR_RGB2BGR)
    
    # Convert image to grayscale for further processing; inverse binary threshold (also to get rid of JPG artifacts)
    _, gray = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 240, 255, cv2.THRESH_BINARY_INV)
    
    # Find only external contours
    contours, _ = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    n = len(contours)
    
    # Get center coordinates and radii of all circles (converted to int)
    circles = [cv2.minEnclosingCircle(cnt) for cnt in contours]
    centers = np.array([np.int32(np.round(circ[0])) for circ in circles])
    
    # Find vertical lines within tolerance; calculate mean
    tol = 10
    x_match = np.array([np.abs(centers[:, 0] - cent[0]) < tol for cent in centers])
    lines_global = []
    for i in np.arange(n):
        lines_local = []
        lines_local.append(i)
        for j in np.arange(i+1, n):
            if (x_match[i, j]):
                lines_local.append(j)
        if (len(lines_local) > 1):
            lines_global.append(np.int32(np.round(np.mean(centers[lines_local, 0]))))
            for j in lines_local:
                for k in lines_local:
                    x_match[j, k] = False
                    x_match[k, j] = False
    
    # Draw lines
    for line in lines_global:
        cv2.line(img, (line, 0), (line, img.shape[0]), (0, 255, 0), 2)
    
    cv2.imshow('img', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    当前输出如下所示:

    Output

    您可以将tol = 0设置为仅获取精确的x坐标匹配,但是如最初所述,对于给定的图像,您将找不到任何两个圆圈。

    希望有帮助!

    关于python - 通过同一垂直线中的圆进行圆识别和画线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58611929/

    相关文章:

    python - 在 python 函数中访问函数

    python - 标准输出 pymssql 到变量

    android - 无法构建 OpenCV Android 示例项目

    c++ - 在 opencv : no error no output 中播放的视频

    python - 使用python获取图像中形状的轮廓(x,y)坐标

    OpenCV 2.4.3 VideoCapture 不工作

    python - 如何在sklearn的PCA之后保留行标题

    python - 守护线程解释

    python - pandas 循环的性能

    java - 通过TCP将Opencv图像从Android发送到PC