获取中心像素周围像素的周长
Get perimeter of pixels around centre pixel
我正在尝试围绕中心像素获取一圈像素。即,就像 FAST 关键点检测器的工作原理一样,我想在给定半径的情况下获取它周围的周边像素。不管数学如何让我逃避,我理论上知道如何使用三角函数获得它。即,我可以使用 for 循环并以 15 度迭代。我知道三角形斜边的长度是半径,我知道角度。
关于如何获得给定像素周围像素周长的任何建议?
假设 img
是您的图像,radius
是圆的半径,x, y
是您要对焦的圆心坐标。
可以使用
获得focus_img
offset = math.ceil(radius * math.sqrt(2))
focus_img = img[y-offset:y+offset, x-offset:x+offset]
公式为:
(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()
结果如下:
方法一
方法二
还有第三种方法...你在大小为 radius x radius 的圆周围取一个框并用上面给出的圆公式计算每个点,如果它是真的那么它是一个圆点...但是画整个圆很好,因为你有整数,很可能没有多少点是相等的...
更新:
提醒一下,确保你的点在图像中,在上面的例子中,如果你把中心放在 0,0 它会在每个角落画出 1/4 的圆,因为它考虑了从数组末尾开始的负值。
要删除重复项,您可以尝试以下代码:
c = np.unique(np.array(list(zip(y,x))), axis=0 )
img2[c[:,0], c[:,1]] = 255
只需将圆圈画到蒙版上即可:
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]))
我正在尝试围绕中心像素获取一圈像素。即,就像 FAST 关键点检测器的工作原理一样,我想在给定半径的情况下获取它周围的周边像素。不管数学如何让我逃避,我理论上知道如何使用三角函数获得它。即,我可以使用 for 循环并以 15 度迭代。我知道三角形斜边的长度是半径,我知道角度。
关于如何获得给定像素周围像素周长的任何建议?
假设 img
是您的图像,radius
是圆的半径,x, y
是您要对焦的圆心坐标。
可以使用
获得focus_img
offset = math.ceil(radius * math.sqrt(2))
focus_img = img[y-offset:y+offset, x-offset:x+offset]
公式为:
(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()
结果如下:
方法一
方法二
还有第三种方法...你在大小为 radius x radius 的圆周围取一个框并用上面给出的圆公式计算每个点,如果它是真的那么它是一个圆点...但是画整个圆很好,因为你有整数,很可能没有多少点是相等的...
更新:
提醒一下,确保你的点在图像中,在上面的例子中,如果你把中心放在 0,0 它会在每个角落画出 1/4 的圆,因为它考虑了从数组末尾开始的负值。
要删除重复项,您可以尝试以下代码:
c = np.unique(np.array(list(zip(y,x))), axis=0 )
img2[c[:,0], c[:,1]] = 255
只需将圆圈画到蒙版上即可:
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]))