我试图通过计算数据的梯度并使用它来设置alpha值来为某些数据的地图添加阴影。 我开始加载我的数据(遗憾的是我不能共享数据,因为它正在准备中用于许多手稿,但我正在添加我的整个代码和屏幕截图):
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
from pylab import imread, imshow, gray, mean
import matplotlib.colors as cl
%matplotlib inline
data = np.loadtxt('data.txt')
plt.imshow(data, cmap='cubehelix')
plt.show()
给我一个数据图:
然后我计算总水平梯度并将其标准化以用于着色:
dx,dy = np.gradient(data, 1, 1)
tdx=np.sqrt(dx*dx + dy*dy)
tdx_n=(tdx-tdx.min())/(tdx.max()-tdx.min())
tdx_n=1-tdx_n
看起来像我预期的那样:
plt.imshow(tdx_n[4:-3,4:-3], cmap='bone')
plt.show()
要创建着色效果,我想我会从数据图中获取颜色,然后用渐变替换不透明度,使暗色阴影与渐变成比例,如下所示:
img_array = plt.get_cmap('cubehelix')(data[4:-3,4:-3])
img_array[..., 3] = (tdx_n[4:-3,4:-3])
plt.imshow(img_array)
plt.show()
但结果不是我的预期:
这就是我要找的东西(在Matlab中创建,色彩映射是不同的):
有关如何修改我的代码的任何建议吗?
更新使用Ran Novitsky的方法,使用titusjan的答案中建议的代码,我得到了这个结果:
给出了我正在寻找的效果。在阴影方面我虽然喜欢titusjan自己建议使用HSV,但结果如下: 。
然而,即使我要求它,我也无法将色彩映射作为cubehelix:
from matplotlib.colors import rgb_to_hsv, hsv_to_rgb
hsv = rgb_to_hsv(img_array[:, :, :3])
hsv[:, :, 2] = tdx_n
rgb = hsv_to_rgb(hsv)
plt.imshow(rgb[4:-3,4:-3], cmap='cubehelix')
plt.show()
答案 0 :(得分:2)
首先,Matplotlib包含Amazon's example Dockerfile实现。这通过将梯度与特定角度的光源进行比较来计算强度。所以它并不完全是你所实现的,但是接近甚至可能会产生更好的结果。
Ran Novitsky已经将hill shading与Matplotlib的不同之处在于如何合并颜色和强度值。我不知道哪个更好,但值得一看。
结合颜色和强度的最佳方法可能是使用 gouraud着色,它用于3D计算机图形。我过去实现的自己的方法是将强度放在图像的HSV颜色的值层中。
我认为我不同意您在图像的alpha图层中放置强度(tdx_n
)的方法。这意味着在渐变较低的情况下,图像将是透明的,您将看到之前绘制的数据。我认为这就是你的屏幕截图中发生的事情。
此外,我认为您需要在将数据传递到cmap之前对其进行规范化,就像规范化强度一样:
data_n=(data-data.min())/(data.max()-data.min())
img_array = plt.get_cmap('cubehelix')(data_n)
然后我们可以使用Ran Novitsky的方法将颜色与强度合并:
rgb = img_array[:, :, :3]
# form an rgb eqvivalent of intensity
d = tdx_n.repeat(3).reshape(rgb.shape)
# simulate illumination based on pegtop algorithm.
rgb = 2 * d * rgb + (rgb ** 2) * (1 - 2 * d)
plt.imshow(rgb[4:-3,4:-3])
plt.show()
或者您可以按照我过去的方法将强度放在HSV三联体的值层中。
from matplotlib.colors import rgb_to_hsv, hsv_to_rgb
hsv = rgb_to_hsv(img_array[:, :, :3])
hsv[:, :, 2] = tdx_n
rgb = hsv_to_rgb(hsv)
plt.imshow(rgb[4:-3,4:-3])
plt.show()
修改2015-05-23:
你的问题促使我完成了一年前开始的山坡阴影实施。我把它放在Github another hill shading implementation上。
它使用类似于Gouraud着色的混合机制,用于3D计算机图形。它在下面标有 RGB混合。我认为这是最好的混合算法,当颜色接近黑色时,HSV混合会产生错误的结果(注意HSV图像中心的蓝色,这在非阴影数据中不存在)。
RGB混合也是最简单的算法,它只是将强度与RGB三元组相乘(它增加了长度为1的额外维度以允许在乘法中进行广播)。
rgb = img_array[:, :, :3]
tdx_n_exp = np.expand_dims(tdx_n, axis=2)
result = tdx_n_exp * rgb
plt.imshow(result[4:-3,4:-3])