0

我试图通过计算数据的梯度并使用它来设置 alpha 值来为某些数据的映射添加阴影。

我首先加载我的数据(不幸的是,我无法共享这些数据,因为它正在准备中的许多手稿中使用。编辑 - 2020 年 12 月:已发表的论文可在勘探地球物理学家协会图书馆开放访问,并且数据可通过随附的Jupyter Notebook获得):

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 中创建,颜色图不同): 着色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()
4

1 回答 1

3

首先,Matplotlib 包含一个山体阴影实现。这通过将梯度与某个角度的光源进行比较来计算强度。所以它不完全是你正在实施的,但很接近,甚至可能会产生更好的结果。

Ran Novitsky 制作了另一个与 Matplotlib 不同的山体着色实现,它在颜色和强度值的合并方式上有所不同。我不知道哪个更好,但值得一看。

也许结合颜色和强度的最佳方法是使用gouraud shading,它用于 3D 计算机图形。我自己过去实施的方法是将强度放在图像的 HSV 颜色的层中。

我认为我不同意您将强度(tdx_n在您的情况下)放置在图像的 alpha 层中的方法。这意味着在梯度较低的地方,图像将是透明的,您将看到之前绘制的数据。我认为这就是你的屏幕截图中发生的事情。

此外,我认为您需要在将数据通过 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 here上。

它使用类似于 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])

混合比较结果

于 2015-05-19T01:04:55.640 回答