代码之家  ›  专栏  ›  技术社区  ›  sazr

获取中心像素周围像素的周长

  •  0
  • sazr  · 技术社区  · 7 年前

    我试图得到一个围绕中心像素的像素圆。也就是说,就像关键点探测器的工作速度一样,我想得到给定半径的周边像素。不管我怎么不懂数学,我从理论上知道如何用三角学得到它。也就是说,我可以使用for循环并在15度下迭代。我知道三角形斜边的长度是半径,我知道角度。

    有什么建议可以让我得到一个给定像素周围像素的周长吗?

    image description

    3 回复  |  直到 7 年前
        1
  •  2
  •   api55    7 年前

    公式是:

    (x-cx)**2 + (y-cy)**2 = r**2
    

    其中cx和cy是圆的中心,x和y是要测试的坐标…现在我们可以迭代x得到y,公式如下:

    y = sqrt(r**2 - (x-cx)**2) + cy
    

    另一种方法是迭代360度并计算x和y,然后添加偏移(中心),如下所示:

    x = cos(radians) * radius + cx
    y = sin(radians) * radius + cy
    

    第二个版本在我的测试中给了我一个更完整的圆圈。以下是我的python测试脚本:

    import numpy as np
    import cv2
    import math
    
    img = np.zeros((480, 640, 1), dtype="uint8")
    img2 = np.zeros((480, 640, 1), dtype="uint8")
    
    center = (200, 200)
    radius = 100
    
    x = np.arange(center[0] - radius, center[0]+radius+1)
    y_off = np.sqrt(radius**2 - (x - center[0]) **2)
    y1 = np.int32(np.round(center[1] + y_off))
    y2 = np.int32(np.round(center[1] - y_off))
    img[y1, x] = 255
    img[y2, x] = 255
    
    
    degrees = np.arange(360)
    x = np.int32(np.round(np.cos(degrees) * radius)) + center[0]
    y = np.int32(np.round(np.sin(degrees) * radius)) + center[1]
    img2[y,x] = 255
    
    
    cv2.imshow("First method", img)
    cv2.imshow("Second method", img2)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    结果是:

    方法1

    enter image description here

    方法2

    enter image description here

    还有第三种方法…在半径x半径的圆周围取一个方框,用上面给出的圆公式计算每个点,如果是真的,那么它就是一个圆点…不过,这是很好的画整个圆,因为你有整数和高度可能不会有很多点将相等…


    更新:

    只是一个小提示,确保你的点在图像中,在上面的例子中,如果你把中心放在0,0,它将在每个角落画1/4的圆,因为它认为负值从数组的末尾开始。

    要删除重复项,可以尝试以下代码:

    c = np.unique(np.array(list(zip(y,x))), axis=0  )
    img2[c[:,0], c[:,1]] = 255
    
        2
  •  2
  •   alkasm Anuj Gautam    7 年前

    把圆圈画在面具上:

    In [27]: mask = np.zeros((9, 9), dtype=np.uint8)
    
    In [28]: cv2.circle(mask, center=(4, 4), radius=4, color=255, thickness=1)
    Out[28]:
    array([[  0,   0,   0,   0, 255,   0,   0,   0,   0],
           [  0,   0, 255, 255,   0, 255, 255,   0,   0],
           [  0, 255,   0,   0,   0,   0,   0, 255,   0],
           [  0, 255,   0,   0,   0,   0,   0, 255,   0],
           [255,   0,   0,   0,   0,   0,   0,   0, 255],
           [  0, 255,   0,   0,   0,   0,   0, 255,   0],
           [  0, 255,   0,   0,   0,   0,   0, 255,   0],
           [  0,   0, 255, 255,   0, 255, 255,   0,   0],
           [  0,   0,   0,   0, 255,   0,   0,   0,   0]], dtype=uint8)
    

    现在你可以用它来索引你喜欢的图像。例如,这是一张随机图像:

    In [33]: img
    Out[33]:
    array([[ 88, 239, 212, 160,  89,  85, 249, 242,  88],
           [ 47, 230, 206, 206,  63, 143, 152,  67,  58],
           [162, 212,   0, 213, 208, 169, 228,  14, 229],
           [230,  45, 103, 201, 188, 231,  80, 122, 131],
           [159,  31, 148, 158,  73, 215, 152, 158, 235],
           [213, 177, 148, 237,  92, 115, 152, 188, 223],
           [234,  67, 141, 173,  14,  18, 242, 208, 147],
           [ 53, 194, 229, 141,  37, 215, 230, 167,  82],
           [ 72,  78, 152,  76, 230, 128, 137,  25, 168]], dtype=uint8)
    

    这是周长上的值:

    In [34]: img[np.nonzero(mask)]
    Out[34]:
    array([ 89, 206, 206, 143, 152, 212,  14,  45, 122, 159, 235, 177, 188,
            67, 208, 229, 141, 215, 230, 230], dtype=uint8)
    

    将圆周长处的图像值设置为0:

    In [35]: img[np.nonzero(mask)] = 0
    
    In [36]: img
    Out[36]:
    array([[ 88, 239, 212, 160,   0,  85, 249, 242,  88],
           [ 47, 230,   0,   0,  63,   0,   0,  67,  58],
           [162,   0,   0, 213, 208, 169, 228,   0, 229],
           [230,   0, 103, 201, 188, 231,  80,   0, 131],
           [  0,  31, 148, 158,  73, 215, 152, 158,   0],
           [213,   0, 148, 237,  92, 115, 152,   0, 223],
           [234,   0, 141, 173,  14,  18, 242,   0, 147],
           [ 53, 194,   0,   0,  37,   0,   0, 167,  82],
           [ 72,  78, 152,  76,   0, 128, 137,  25, 168]], dtype=uint8)
    

    你也可以很容易地得到坐标:

    In [56]: np.where(mask)
    Out[56]:
    (array([0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8]),
     array([4, 2, 3, 5, 6, 1, 7, 1, 7, 0, 8, 1, 7, 1, 7, 2, 3, 5, 6, 4]))
    
        3
  •  -1
  •   Silver    7 年前

    假定 img 是你的形象, radius 是圆的半径 x, y 是要聚焦的中心的坐标。

    那个 focus_img 可以使用

    offset = math.ceil(radius * math.sqrt(2))
    focus_img = img[y-offset:y+offset, x-offset:x+offset]