画像をRGBにスライスしようとしていますが、これらの画像のプロットに問題があります。この機能を使用して、特定のフォルダからすべての画像を取得します。
def get_images(path, image_type):
image_list = []
for filename in glob.glob(path + '/*'+ image_type):
im=misc.imread(filename, mode='RGB')
image_list.append(im)
return image_list
この関数は4d配列(30、1536、2048、3)を作成します。最初の値は画像の数を表し、2番目と3番目は次元、3番目はRGB値であることを確信しています。
すべての画像を取得した後、それらをnumpy配列として保存しました
image_list = get_images('C:\HDR\images', '.jpg')
temp = np.array(image_list)
その後、私はこれらの画像から特定の色を取得するために単純なスライスを使用しようとしました:
red_images = temp[:,:,:,0]
green_images = temp[:,:,:,1]
blue_images = temp[:,:,:,2]
値を出力すると、すべて問題ないようです。
print(temp[11,125,311,:])
print(red_images[11,125,311])
print(green_images[11,125,311])
print(blue_images[11,125,311])
そして私は以下を得ます:
[105 97 76]
105
97
76
これまでのところ、すべて問題ないようですが、画像を表示しようとすると問題が発生します。 matplotlib.pyplot.imshow
表示するには、次のような画像を取得します。
赤を選択しているので、これは合理的です。
plt.imshow(temp[29,:,:,0])
しかし、次のように別のカラーチャネルに変更すると、
plt.imshow(temp[29,:,:,2])
私はこのような画像を取得します:
私の質問は簡単です。ここで何が起きてるの?
Matplotlibは、各チャネル(つまり、強度)を「ヒートマップ」として扱っているだけだと思います。
次のようにカラーマップを関数imshowに渡して、イメージに色を付ける方法を伝えます。
plt.imshow(image_slice, cmap=plt.cm.gray)
@mrGreenBrownあなたのコメントへの応答として、私はあなたが使用したmisc.imread
関数がscipyから、つまりscipy.misc.imread
であると想定しています。その関数はPIL
の関数と同じです。 scipy.misc.imread docs を参照してください。これを指摘してくれた@daiに感謝します。
画像の単一チャネルは、単なる強度です。色はありません。 RGB色空間で表現された画像の場合、色は、赤、緑、青の量(それぞれのチャネルの強度によって与えられる)を「混合」することによって得られます。 単一のチャネルは色を表現できません。
起こったのは、デフォルトでMatplotlibが強度をヒートマップ、つまり「色」として表示することでした。
単一のチャネルをJPEGなどの形式の画像として保存する場合、この関数は単一のチャネルを3回複製するだけなので、R、G、Bチャネルにはすべて同じ強度が含まれます。これは、単一チャネルのグレースケールイメージを処理できるPGMなどの形式で保存しない限り、一般的な動作です。同じチャネルを3回複製したこの画像を視覚化しようとすると、赤、緑、青の寄与が各ピクセルで同じであるため、画像は灰色で表示されます。
plt.cm.gray
をcmap
引数に渡すと、単にimshow
に強度を「色分け」しないように指示します。したがって、より明るいピクセル(白に近づくピクセル)は、それらの場所にその「色」が「多い」ことを意味します。
色が必要な場合は、3チャネルイメージのコピーを作成し、他のチャネルを0
の値に設定する必要があります。
たとえば、赤のチャネルを「赤」として表示するには:
# Assuming I is numpy array with 3 channels in RGB order
I_red = image.copy() # Duplicate image
I_red[:, :, 1] = 0 # Zero out contribution from green
I_red[:, :, 2] = 0 # Zero out contribution from blue
Stackoverflowからの関連質問 here 。
したがって、画像のさまざまなRGBチャネルをさまざまな色で表示したいとします...
import matplotlib.pyplot as plt
from matplotlib.cbook import get_sample_data
image = plt.imread(get_sample_data('grace_hopper.jpg'))
titles = ['Grace Hopper', 'Red channel', 'Green channel', 'Blue channel']
cmaps = [None, plt.cm.Reds_r, plt.cm.Greens_r, plt.cm.Blues_r]
fig, axes = plt.subplots(1, 4, figsize=(13,3))
objs = Zip(axes, (image, *image.transpose(2,0,1)), titles, cmaps)
for ax, channel, title, cmap in objs:
ax.imshow(channel, cmap=cmap)
ax.set_title(title)
ax.set_xticks(())
ax.set_yticks(())
plt.savefig('RGB1.png')
暗いテーブルの上に赤いペンのある暗い部屋があるときに、赤いランプを点灯すると、ペンがほとんど白いものとして認識されます...
別の可能性は、他の色のピクセル値をゼロにして、色ごとに異なる画像を作成することです。去ったところから始めて、チャンネルを抽出して、それ以外は黒の画像にする関数を定義します。
...
from numpy import array, zeros_like
def channel(image, color):
if color not in (0, 1, 2): return image
c = image[..., color]
z = zeros_like(c)
return array([(c, z, z), (z, c, z), (z, z, c)][color]).transpose(1,2,0)
そして最後にそれを使います...
colors = range(-1, 3)
fig, axes = plt.subplots(1, 4, figsize=(13,3))
objs = Zip(axes, titles, colors)
for ax, title, color in objs:
ax.imshow(channel(image, color))
ax.set_title(title)
ax.set_xticks(())
ax.set_yticks(())
plt.savefig('RGB2.png')
どちらがより良いバージョンであるかはわかりません。おそらく最初のバージョンはもっとrealisticに見えます(多分それはあまり人工的ではない)が、それはかなり主観的です...