使用Python在有限大小的图像中查找未填充圆

2024-06-16 11:34:20 发布

您现在位置:Python中文网/ 问答频道 /正文

试图在image中找到一个半径有限的圆。开始使用OpenCV中的“HoughCircles”方法作为参数,它似乎与我的情况非常相关。但它没有找到它。看起来图像可能需要更多的预处理才能可靠地找到。因此,开始在opencv中使用不同的阈值,但没有成功Here是图像的一个示例(请注意,图像的整体强度会有所不同,但圆的半径始终保持不变~45像素)

这是我到目前为止所做的尝试

image = cv2.imread('image1.bmp', 0)
img_in = 255-image
mean_val = int(np.mean(img_in))
ret, img_thresh = cv2.threshold(img_in, thresh=mean_val-30, maxval=255, type=cv2.THRESH_TOZERO)
# detect circle
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.0, 100, minRadius=40, maxRadius=50)

如果你看这张图片,圆圈很明显,它是一个薄的浅灰色圆圈,位于斑点的中心

有什么建议吗? 编辑以显示预期结果 预期的结果应该类似于this,正如您所看到的,这个圆在原始图像上肉眼非常明显,并且总是具有相同的半径,但不在图像上的相同位置。但是在任何给定的图像上都只有一个这样的圆

从2020年8月20日起,以下是我用来获取中心和半径的代码

from numpy import zeros as np_zeros,\
                full as np_full
from cv2 import calcHist as cv2_calcHist,\
                HoughCircles as cv2_HoughCircles,\
                HOUGH_GRADIENT as cv2_HOUGH_GRADIENT

def getCenter(img_in, saturated, minradius, maxradius):
    img_local = img_in[100:380,100:540,0]
    res = np_full(3, -1)
    # do some contrast enhancement
    img_local = stretchHistogram(img_local, saturated)

    circles = cv2_HoughCircles(img_local, cv2_HOUGH_GRADIENT, 1, 40, param1=70, param2=20,
                               minRadius=minradius,
                                  maxRadius=maxradius)
    if circles is not None: # found some circles
        circles = sorted(circles[0], key=lambda x: x[2])
        res[0] = circles[0][0]+100
        res[1] = circles[0][1]+100
        res[2] = circles[0][2]

    return res #x,y,radii


def stretchHistogram(img_in, saturated=0.35, histMin=0.0, binSize=1.0):
    img_local = img_in.copy()
    img_out = img_in.copy()
    min, max = getMinAndMax(img_local, saturated)
    if max > min:
        min = histMin+min * binSize
        max = histMin+max * binSize

        w, h = img_local.shape[::-1]
        #create a new lut
        lut = np_zeros(256)
        max2 = 255
        for i in range(0, 256):
            if i <= min:
                lut[i] = 0
            elif i >= max:
                lut[i] = max2
            else:
                lut[i] = (round)(((float)(i - min) / (max - min)) * max2)

        #update image with new lut values
        for i in range(0, h):
            for j in range(0, w):
                img_out[i, j] = lut[img_local[i, j]]

    return img_out


def getMinAndMax(img_in, saturated):
    img_local = img_in.copy()
    hist = cv2_calcHist([img_local], [0], None, [256], [0, 256])
    w, h = img_local.shape[::-1]
    pixelCount = w * h
    saturated = 0.5
    threshold = (int)(pixelCount * saturated / 200.0)

    found = False
    count = 0
    i = 0
    while not found and i < 255:
        count += hist[i]
        found = count > threshold
        i = i + 1
    hmin = i

    i = 255
    count = 0
    while not found and i > 0:
        count += hist[i]
        found = count > threshold
        i = i - 1
    hmax = i

    return hmin, hmax

将上述函数调用为

getCenter(img, 5.0, 55, 62)

但它仍然非常不可靠。我不知道为什么很难找到一种算法,这种算法能够可靠地处理肉眼可见的事情。不知道为什么帧与帧之间的结果会有如此大的差异,即使它们之间没有变化

如有任何建议,我们将不胜感激。这里还有一些samples可以玩


Tags: in图像imglocalascountnpmin
1条回答
网友
1楼 · 发布于 2024-06-16 11:34:20

简单地说,画圆:cv2.HoughCircles返回圆的列表

照顾maxRadius = 100

for i in circles[0,:]:
    # draw the outer circle
    cv2.circle(image,(i[0],i[1]),i[2],(255,255,0),2)

     # draw the center of the circle
    cv2.circle(image,(i[0],i[1]),2,(255,0,255),3)

完整的工作代码(您必须更改Treshold):

import cv2
import numpy as np

image = cv2.imread('0005.bmp', 0)
height, width = image.shape
print(image.shape)

img_in = 255-image
mean_val = int(np.mean(img_in))

blur = cv2.blur(img_in , (3,3))
ret, img_thresh = cv2.threshold(blur, thresh=100, maxval=255, type=cv2.THRESH_TOZERO)

# detect circle
circles = cv2.HoughCircles(img_thresh, cv2.HOUGH_GRADIENT,1,40,param1=70,param2=20,minRadius=60,maxRadius=0)

print(circles)
for i in circles[0,:]:

    # check if center is in middle of picture
    if(i[0] > width/2-30 and i[0] < width/2+30 \
      and i[1] > height/2-30 and i[1] < height/2+30 ):
        # draw the outer circle
        cv2.circle(image,(i[0],i[1]),i[2],(255,255,0),2)

         # draw the center of the circle
        cv2.circle(image,(i[0],i[1]),2,(255,0,255),3)

cv2.imshow("image", image )

while True:
    keyboard = cv2.waitKey(2320)
    if keyboard == 27:
        break
cv2.destroyAllWindows()

结果: enter image description here

相关问题 更多 >