

Rainbow カラーマップで保存された jpeg イメージを Python で読み込んで、カラーマップに従ってグレースケールする方法はないでしょうか。  
通常 256 色で表現されるカラーマップの RGB 値を、マップの順位に従って、 0 から 255
の数字に対応させたいのですが、普通にグレースケールするとカラーマップの中央付近に最大値が来てしまいます
(<https://matplotlib.org/users/colormaps.html>)。

MATLAB を用いた方法 (<https://stackoverflow.com/questions/7440340/jet-colormap-to-
grayscale>) を見つけましたが、当方 MATLAB に詳しくないため、両方に明るい方がいらっしゃいましたら、Python
で同じことをするにはどうすればよいかご教示ください。  
リンク先 _rgb2ind_ という関数 (?) と同じ機能が Python のモジュールにあると嬉しいのですが。

その他、なにかお考えをお持ちの方ございましたら是非ご教示くださいませ。


CC BY-SA 4.0
2018-06-01T04:55:17.800
44448
2018-08-10T16:48:30.363
22652
question
python matplotlib matlab
Python で Rainbow カラーマップをグレースケール変換


コメントでの提言により、以下記事の内容を(そのままではなく)かいつまんで翻訳・転記します。  
[How I can specify how rainbow color scheme should be converted to
grayscale](https://stackoverflow.com/questions/45343981/how-i-can-specify-how-
rainbow-color-scheme-should-be-converted-to-grayscale)  
元記事の質問画像に関するコメント等は後ろに別途まとめました。

* * *

  * 元々の画像を作成した際に使われたカラーマップが何か知っていることを前提にしています。
  * 以下の記事の回答に示したコードの一部を使っています。  
[How to decode color mapping in matplotlib's
Colormap?](https://stackoverflow.com/questions/45177154/how-to-decode-color-
mapping-in-matplotlibs-colormap)

  * カラーマップは(RAINBOWではなく) JETだと仮定します。

元記事回答からのコードコピー(ただし転記者は未検証です)

[code]

    import numpy as np
    import matplotlib.colors
    import matplotlib.pyplot as plt
    
    image = plt.imread("data/jetcolimage.png")
    print image.shape, image.max()
    
    r = np.linspace(0,1, 256)
    norm = matplotlib.colors.Normalize(0,1)
    cmap = plt.cm.jet
    mapvals = cmap(norm(r))[:,:3]
    
    def get_value_from_cm(color):
        color=matplotlib.colors.to_rgb(color)
        #if color is already gray scale, dont change it
        if np.std(color) < 0.1:
            return np.mean(color)
        #otherwise return value from colormap
        distance = np.sum((mapvals - color)**2, axis=1)
        return r[np.argmin(distance)]
    
    newim = np.zeros_like(image)
    for i in range(image.shape[0]):
        for j in range(image.shape[1]):
            c = image[i,j,:3]
            newim[i,j] =  get_value_from_cm(c)
    
    
    fig, (ax,ax2) = plt.subplots(ncols=2)
    ax.imshow(image)
    ax2.imshow(newim, cmap="gray")
    
    ax.axis("off")
    ax2.axis("off")
    plt.show()
    
[/code]

* * *

  
元記事の質問画像はカラーマップ画像以外(黒の枠線や数字と元から灰色)の要素を含んでいます。  
単純なカラーマップ画像以外を処理する場合には、グレースケールにもカラーマップにも属さない値を扱う必要があるそうです。  
画像のアンチエイリアシング処理が原因で白が表示されることがあるらしいとか。

以下の記事回答中で「(画像を)あるカラーマップから別のカラーマップに変更する方法」として、それらグレースケールにもカラーマップにも属さない値を、最も近い値に変換する処理を扱っているようです。  
[How can I change colors in contours (obtained from non-Python) with
Python?](https://stackoverflow.com/questions/51478981/how-can-i-change-colors-
in-contours-obtained-from-non-python-with-python/51484647#51484647)


CC BY-SA 4.0
2018-08-10T16:48:30.363
47428
2018-08-10T16:48:30.363
26370
44448
answer