web-dev-qa-db-ja.com

PythonのPILを使用してグレースケール画像をカラフルな画像に変換するための適切なカラーマップはありますか?

Matplotlibには多くの優れたカラーマップがありますが、パフォーマンスは悪いです。カラーマップで補間することをお勧めしますが、グレースケールイメージをカラフルにするコードを書いています。利用可能なオープンソースのカラーマップや、Pillowを使用してカラーマップを介してグレースケール画像をカラフルな画像に変換するためのデモコードはあるのでしょうか。


明らかにする:

  1. Matplotlibはデモでの使用には適していますが、画像の数が多ければパフォーマンスは低下します。
  2. Matplotlibカラーマップ
  3. グレースケールイメージをカラーマップにマップして、カラフルなイメージを取得できます。

デモ:

最初の画像はグレースケールで、2番目は「jet」cmapにマップされ、3番目は「hot」です。

Matplotlib demo

問題は、色についてあまり知らないということです。パフォーマンスを向上させるために、PILでこのような効果を実現したいと考えています。

9
Adam

@ImportanceOfBeingErnest( matplotlibカラーマップを適用してNumpy配列をPIL画像に変換する方法 )によって言及された重複する答えを見つけました

import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np

import timeit

from PIL import Image

def pil_test():
    cm_hot = mpl.cm.get_cmap('hot')
    img_src = Image.open('test.jpg').convert('L')
    img_src.thumbnail((512,512))
    im = np.array(img_src)
    im = cm_hot(im)
    im = np.uint8(im * 255)
    im = Image.fromarray(im)
    im.save('test_hot.jpg')

def rgb2gray(rgb):
    return np.dot(rgb[:,:,:3], [0.299, 0.587, 0.114])

def plt_test():
    img_src = mpimg.imread('test.jpg')
    im = rgb2gray(img_src)
    f = plt.figure(figsize=(4, 4), dpi=128)
    plt.axis('off')
    plt.imshow(im, cmap='hot')
    plt.savefig('test2_hot.jpg', dpi=f.dpi)
    plt.close()

t = timeit.timeit(pil_test, number=30)
print('PIL: %s' % t)
t = timeit.timeit(plt_test, number=30)
print('PLT: %s' % t)

パフォーマンス結果は次のとおりです。

PIL: 1.7473899199976586
PLT: 10.632971412000188

どちらもhotカラーマップで同様の結果をもたらします。

Test Image with hot CMap

8
Adam

あなたはmatplotlibからのカラーマップを使用してそれらを適用することができますmatplotlibの数字なしでなど。これは物事をより速くします:

import matplotlib.pyplot as plt

# Get the color map by name:
cm = plt.get_cmap('Gist_Rainbow')

# Apply the colormap like a function to any array:
colored_image = cm(image)

# Obtain a 4-channel image (R,G,B,A) in float [0, 1]
# But we want to convert to RGB in uint8 and save it:
Image.fromarray((colored_image[:, :, :3] * 255).astype(np.uint8)).save('test.png')

注意:

  • 入力画像が浮動小数点の場合、値は[0.0, 1.0]
  • 入力画像が整数の場合、整数は[0, N)ここで、Nはマップ内の色の数です。ただし、必要に応じて、マップを任意の数の値にリサンプリングできます。

    # If you need 8 color steps for an integer image with values from 0 to 7:
    cm = plt.get_cmap('Gist_Rainbow', lut=8)
    
8
Philipp F