简体   繁体   English

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

[英]Get perimeter of pixels around centre pixel

I am attempting to get a circle of pixels around a centre pixel. 我试图在中心像素周围得到一个像素圈。 Ie, just like how FAST keypoint detector works, I want to get the perimeter pixels around it given a radius. 即,就像FAST关键点检测器的工作原理一样,我想在给定半径的情况下获取其周围的周边像素。 However the math escapes me, I know theoretically how I could obtain it using trigonometry. 无论数学如何,我从理论上都知道如何使用三角函数获得数学。 Ie, I could use a for loop and iterate at 15 degrees. 即,我可以使用for循环并以15度进行迭代。 I know the triangle hypotenuse length is the radius, I know the angle. 我知道三角形的斜边长度是半径,我知道角度。

Any advice how I could obtain a perimeter of pixels around a given pixel? 任何建议如何获得给定像素周围的像素周长?

图片描述

The formula is: 公式为:

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

where cx and cy is the center of the circle and x and y are the coordinates you want to test... Now we can iterate over x and get the y with the formula like this: 其中cx和cy是圆的中心,x和y是要测试的坐标...现在,我们可以遍历x并使用如下公式获得y:

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

The other way will be to iterate the 360 degrees and calculate the x and y and add the offset (center) like this: 另一种方法是迭代360度并计算x和y并添加偏移量(中心),如下所示:

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

The second version gave me a more complete circle in my tests. 第二版使我的测试更加完整。 Here is my test script in python: 这是我在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()

and the results are these: 结果是:

Method 1 方法1

在此处输入图片说明

Method 2 方法二

在此处输入图片说明

There is a third method... You take a box around the circle of size radius x radius and evaluate each point with the circle formula given above, if it is true then it is a circle point... however that is good to draw the whole circle, since you have integers and highly probable not many point will be equal... 第三种方法...您在半径为半径x半径的圆周围取一个框,并使用上述给定的圆公式计算每个点,如果为true,则为圆点...但是绘制起来很不错整个圆圈,因为您有整数并且很可能没有多少点相等...


UPDATE: 更新:

Just a small reminder, make sure your points are in the image, in the example above, if you put the center in 0,0 it will draw 1/4 of a circle in every corner, because it considers the negative values to start from the end of the array. 提醒一下,请确保您的点在图像中,在上面的示例中,如果将中心置于0,0,则它将在每个角上绘制一个圆的1/4,因为它认为负值从数组的末尾。

To remove duplicates you can try the following code: 要删除重复项,您可以尝试以下代码:

c = np.unique(np.array(list(zip(y,x))), axis=0  )
img2[c[:,0], c[:,1]] = 255

Just draw the circle onto a mask: 只需将圆圈绘制到蒙版上:

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)

And now you can use it to index your image as you like. 现在,您可以根据需要使用它来索引图像。 Eg, here's a random image: 例如,这是一个随机图像:

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)

Here's the values on the perimeter: 这是周长上的值:

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)

Setting the value of the image at the perimeter of the circle to 0: 将圆周围的图像值设置为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)

You can easily get the coordinates as well: 您也可以轻松获取坐标:

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]))

Assume img is your image, radius is the radius of the circle and x, y are the coordinates of the center around which you want to focus. 假设img是您的图像, radius是圆的半径, x, y是您要聚焦的中心的坐标。

The the focus_img can be obtained using focus_img可以使用

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM