0

データの勾配を計算し、それを使用してアルファ値を設定することにより、一部のデータのマップにシェーディングを追加しようとしています。

データを読み込むことから始めます (残念ながら、準備中の多数の原稿で使用されているため、データを共有することはできません。編集 - 2020 年 12 月: 公開された論文は、Society of Exploration Geophysicistsライブラリでオープン アクセスで入手できます。データは付属の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 の回答で提案されたコードを使用すると、次の結果が得られます。 ペグトップ

これは私が探していた効果をもたらします。シェーディングに関しては、HSV を使用するという titusjan 自身の提案が気に入っています。これにより、次の結果が得られます ティトゥスヤンス

ただし、呼び出したにもかかわらず、カラーマップをキューブヘリックスにすることができませんでした。

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 とは色と強度の値をマージする方法が異なる別のヒル シェーディングの実装を作成しました。どちらが優れているとは言えませんが、一見の価値があります。

おそらく、色と強度を組み合わせる最良の方法は、3D コンピュータ グラフィックスで使用されるグーロー シェーディングを使用することでしょう。過去に実装した私自身のアプローチは、画像の HSV カラーの値レイヤーに強度を配置することでした。

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 を編集:

あなたの質問により、私は 1 年前に開始したヒル シェーディングの実装を完了するようになりました。Github hereに置きました。

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 に答える