二维浮点的密度图像
Density image of 2D floating points
给定一组二维点
pts = np.random.uniform(low=0, high=127, size=32).reshape((-1, 2))
可以通过绘制峰值并使用高斯模糊进行过滤来计算密度图像:
sigma = 2
peaks_img = np.zeros((128, 128))
peaks_img[np.int_(pts[:, 0]), np.int_(pts[:, 1])] = 1
density_img = cv2.GaussianBlur(peaks_img, (0, 0), sigma)
是否有一种很好(且快速)的方法可以在不强制转换为 int 的情况下执行此操作,从而保持浮点精度?
通常的库(openCV、scipy.ndimage 等)需要您所做的舍入,因为它们在图像处理的上下文中工作。输入和输出都是图像,所以输入和输出都是像素。概括这一点并非易事,尤其是因为通常的高斯模糊有一些 "conservation laws" 通过所用高斯核的求和规则连接到其中。
我会尝试通过简单地在每个(浮动)位置添加适当的高斯峰并在相关像素坐标处查看结果函数来概括高斯模糊。对于我们的连续近似,我们可以以类似的方式强制执行 "conservation of weight",但我不完全确定这会使 完美 感觉像二维密度图像。无论如何,这是我现在能想到的最好的概括:
import numpy as np
# inputs
imsize = (128,128)
npeaks = 16
pts_x,pts_y = np.random.uniform(low=0, high=min(imsize)-1, size=(2,npeaks,1,1))
# weird size: prepare for broadcasting
# pts_x.shape == pts_y.shape == (npeaks,1,1)
ii,jj = np.ogrid[:imsize[0],:imsize[1]] # memory-efficient np.indices
peaks = np.exp(-((pts_x - ii)**2 + (pts_y - jj)**2)/(2*sigma**2)) # shape (npeaks,*imsize)
# normalize each peak to preserve weight 1 for each
peaks /= peaks.sum(axis=(1,2),keepdims=True)
# sum each peak to end up with an array of size imsize
peaks = peaks.sum(axis=0)
# print(peaks.sum()) is now 16.0
# same for blurred openCV version: 16.18
将上面的(左)与 openCV 生成的版本(右)进行比较:
请注意顶部的最大差异,其中一个峰几乎位于边缘。不同之处在于 openCV 与高斯核进行了适当的卷积,这受边缘存在或不存在的影响。我的方法盲目地总结了每个坐标的高斯峰。这些是你必须要知道的limitations/features。总而言之,根据您的具体需求,以上内容可能是可以接受的替代品。
为了后人,上面的数字是用随机点创建的
array([[ 71.84229522, 53.87674552],
[ 49.46010032, 25.54820408],
[ 118.08357845, 6.83220309],
[ 97.20503813, 76.96684427],
[ 1.00902832, 51.26414236],
[ 82.38165581, 30.2121626 ],
[ 64.46298579, 58.15192887],
[ 121.90414697, 38.02821749],
[ 101.81869852, 49.64438987],
[ 28.49284669, 41.81582785],
[ 9.48948284, 55.24329885],
[ 63.54365708, 116.05157199],
[ 86.00412101, 46.56952082],
[ 34.27945909, 40.62669415],
[ 34.46355519, 14.85889878],
[ 67.23707619, 76.76113722]])
给定一组二维点
pts = np.random.uniform(low=0, high=127, size=32).reshape((-1, 2))
可以通过绘制峰值并使用高斯模糊进行过滤来计算密度图像:
sigma = 2
peaks_img = np.zeros((128, 128))
peaks_img[np.int_(pts[:, 0]), np.int_(pts[:, 1])] = 1
density_img = cv2.GaussianBlur(peaks_img, (0, 0), sigma)
是否有一种很好(且快速)的方法可以在不强制转换为 int 的情况下执行此操作,从而保持浮点精度?
通常的库(openCV、scipy.ndimage 等)需要您所做的舍入,因为它们在图像处理的上下文中工作。输入和输出都是图像,所以输入和输出都是像素。概括这一点并非易事,尤其是因为通常的高斯模糊有一些 "conservation laws" 通过所用高斯核的求和规则连接到其中。
我会尝试通过简单地在每个(浮动)位置添加适当的高斯峰并在相关像素坐标处查看结果函数来概括高斯模糊。对于我们的连续近似,我们可以以类似的方式强制执行 "conservation of weight",但我不完全确定这会使 完美 感觉像二维密度图像。无论如何,这是我现在能想到的最好的概括:
import numpy as np
# inputs
imsize = (128,128)
npeaks = 16
pts_x,pts_y = np.random.uniform(low=0, high=min(imsize)-1, size=(2,npeaks,1,1))
# weird size: prepare for broadcasting
# pts_x.shape == pts_y.shape == (npeaks,1,1)
ii,jj = np.ogrid[:imsize[0],:imsize[1]] # memory-efficient np.indices
peaks = np.exp(-((pts_x - ii)**2 + (pts_y - jj)**2)/(2*sigma**2)) # shape (npeaks,*imsize)
# normalize each peak to preserve weight 1 for each
peaks /= peaks.sum(axis=(1,2),keepdims=True)
# sum each peak to end up with an array of size imsize
peaks = peaks.sum(axis=0)
# print(peaks.sum()) is now 16.0
# same for blurred openCV version: 16.18
将上面的(左)与 openCV 生成的版本(右)进行比较:
请注意顶部的最大差异,其中一个峰几乎位于边缘。不同之处在于 openCV 与高斯核进行了适当的卷积,这受边缘存在或不存在的影响。我的方法盲目地总结了每个坐标的高斯峰。这些是你必须要知道的limitations/features。总而言之,根据您的具体需求,以上内容可能是可以接受的替代品。
为了后人,上面的数字是用随机点创建的
array([[ 71.84229522, 53.87674552],
[ 49.46010032, 25.54820408],
[ 118.08357845, 6.83220309],
[ 97.20503813, 76.96684427],
[ 1.00902832, 51.26414236],
[ 82.38165581, 30.2121626 ],
[ 64.46298579, 58.15192887],
[ 121.90414697, 38.02821749],
[ 101.81869852, 49.64438987],
[ 28.49284669, 41.81582785],
[ 9.48948284, 55.24329885],
[ 63.54365708, 116.05157199],
[ 86.00412101, 46.56952082],
[ 34.27945909, 40.62669415],
[ 34.46355519, 14.85889878],
[ 67.23707619, 76.76113722]])