有各种可用的示例,其中包含2D高斯Blob的公式并通过Pyplot绘制,例如:
How to generate 2D gaussian with Python?
和/或
How to plot a 2d gaussian with different sigma?的
我正在尝试将其更改为OpenCV(在Python中)。
一些要求是:
- 为团块指定不同高度和宽度的能力,即使斑点成为椭圆的能力(不总是圆形)
- 指定原始图像中的斑点的中心点的能力
- 在斑点的确切中心处的值应当是255,并且这些值应当朝着斑点的边缘逐渐下降到0。
- 不需要旋转
最终的图像(当然取决于设置)应该看起来像这样:x1c 0d1x的数据
在CenterNet的上下文中(这是我的用例),结果(上面有高斯斑点的图像)被称为“热图”,所以这是我将在图像代码中使用的术语。
以下是我到目前为止所做的:
import numpy as np
import cv2
def main():
# suppress numpy printing in scientific notation
np.set_printoptions(suppress=True)
hm_width = 1600
hm_height = 1000
# create blank heatmap (OpenCV image)
heatmap = np.zeros((hm_height, hm_width), dtype=np.uint8)
blob_height = 100
blob_width = 300
blob_center_x = 1000
blob_center_y = 400
# Create a 2D Gaussian blob
x, y = np.meshgrid(np.linspace(0, 1, blob_width), np.linspace(0, 1, blob_height))
print('\n' + 'x: ')
print(x.dtype)
print(x.shape)
print('min = ' + str(np.min(x)) + ' (s/b 0.0)')
print('max = ' + str(np.max(x)) + ' (s/b 1.0)')
print(x)
print('\n' + 'y: ')
print(y.dtype)
print(y.shape)
print('min = ' + str(np.min(y)) + ' (s/b 0.0)')
print('max = ' + str(np.max(y)) + ' (s/b 1.0)')
print(y)
# gaussian_blob = 1.0 / (2.0 * np.pi * blob_width * blob_height) * np.exp(-((x - blob_center_x)**2.0 / (2. * blob_width**2.0) + (y - blob_center_y)**2.0 / (2. * blob_height**2.0)))
gaussian_x_term = np.power(x - blob_center_x, 2.0) / np.power(blob_width, 2.0)
gaussian_y_term = np.power(y - blob_center_y, 2.0) / np.power(blob_height, 2.0)
gaussian_blob = np.exp(-1.0 * (gaussian_x_term + gaussian_y_term))
print('\n' + 'gaussian_blob before: ')
print(gaussian_blob.dtype)
print(gaussian_blob.shape)
print('min = ' + str(np.min(gaussian_blob)) + ' (s/b 0.0)')
print('max = ' + str(np.max(gaussian_blob)) + ' (s/b 1.0)')
print(gaussian_blob)
# scale up the gaussian blob from the 0.0 to 1.0 range to the 0 to 255 range
gaussian_blob = gaussian_blob * 255.0
gaussian_blob = np.clip(gaussian_blob, a_min=0.0, a_max=255.0)
gaussian_blob = np.rint(gaussian_blob)
gaussian_blob = np.clip(gaussian_blob, a_min=0, a_max=255)
gaussian_blob = gaussian_blob.astype(np.uint8)
print('\n' + 'gaussian_blob after: ')
print(gaussian_blob.dtype)
print(gaussian_blob.shape)
print('min = ' + str(np.min(gaussian_blob)) + ' (s/b 0)')
print('max = ' + str(np.max(gaussian_blob)) + ' (s/b 255)')
print(gaussian_blob)
# show the blob via OpenCV
cv2.imshow('gaussian blob', gaussian_blob)
# add the gaussian blob image to the heatmap
blob_left_edge_loc = round(blob_center_x - (0.5 * blob_width))
blob_right_edge_loc = round(blob_center_x + (0.5 * blob_width))
blob_top_edge_loc = round(blob_center_y - (0.5 * blob_height))
blob_bottom_edge_loc = round(blob_center_y + (0.5 * blob_height))
heatmap[blob_top_edge_loc:blob_bottom_edge_loc, blob_left_edge_loc:blob_right_edge_loc] = gaussian_blob
# show the heatmap
cv2.imshow('heatmap', heatmap)
cv2.waitKey()
# end function
if __name__ == '__main__':
main()
字符串
目前,两个图像几乎都是空白的,并且基于输出:
x:
float64
(100, 300)
min = 0.0 (s/b 0.0)
max = 1.0 (s/b 1.0)
[[0. 0.00334448 0.00668896 ... 0.99331104 0.99665552 1. ]
[0. 0.00334448 0.00668896 ... 0.99331104 0.99665552 1. ]
[0. 0.00334448 0.00668896 ... 0.99331104 0.99665552 1. ]
...
[0. 0.00334448 0.00668896 ... 0.99331104 0.99665552 1. ]
[0. 0.00334448 0.00668896 ... 0.99331104 0.99665552 1. ]
[0. 0.00334448 0.00668896 ... 0.99331104 0.99665552 1. ]]
y:
float64
(100, 300)
min = 0.0 (s/b 0.0)
max = 1.0 (s/b 1.0)
[[0. 0. 0. ... 0. 0. 0. ]
[0.01010101 0.01010101 0.01010101 ... 0.01010101 0.01010101 0.01010101]
[0.02020202 0.02020202 0.02020202 ... 0.02020202 0.02020202 0.02020202]
...
[0.97979798 0.97979798 0.97979798 ... 0.97979798 0.97979798 0.97979798]
[0.98989899 0.98989899 0.98989899 ... 0.98989899 0.98989899 0.98989899]
[1. 1. 1. ... 1. 1. 1. ]]
gaussian_blob before:
float64
(100, 300)
min = 6.880118208869318e-12 (s/b 0.0)
max = 7.240508138966562e-12 (s/b 1.0)
[[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
...
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]]
gaussian_blob after:
uint8
(100, 300)
min = 0 (s/b 0)
max = 0 (s/b 255)
[[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]]
型
看起来我计算的高斯斑点不太正确,但我不知道如何解决这个问题。有什么建议吗
2条答案
按热度按时间ubbxdtey1#
第一个问题是meshgrid生成不正确-它使用
0..1
范围,而代码的其余部分假设它持有大图的坐标(0..hm_width/height
范围)。即使我们在归一化空间中操作,0..1
也只能捕获曲线的一小部分。解决方案:我会保留规范化的空间,因为它将简化以下代码。我会把范围扩大到-3..3标准差请随意调整。
字符串
第二个问题:这是一个2D分布,你不能分别计算x和y的结果(在一般情况下,正如Chris指出的那样-在这里,你可以)。通常,the formula为
型
但由于我们现在在归一化空间中操作,平均值为零,sigma为
[[1, 0], [0, 1]]
,因此可以简化为:型
最后,注意缩放时忽略的常量:
型
UPD
正如Chris所指出的,你可以通过这样做来保存一毫秒左右的时间:
型
vatpfxk52#
这里是一个复制/粘贴可运行的示例,包括制作高斯的代码(由@马拉特提供)和将高斯添加到OpenCV图像的代码,包括高斯部分重叠的情况。我不会把这个作为解决方案,这样@马拉特就能得到信任。
在代码中有一个轻微的缺陷,将高斯添加到热图中,因为在高斯重叠的情况下,结果图像中有一个轻微的接缝,请参见下面的截图。我将在稍后的时间尝试解决这个问题。
字符串
结果:x1c 0d1x