note.nkmk.me

scipy.misc.imsaveは最小値と最大値で規格化される

Date: 2015-09-22 / tags: Python, SciPy, 画像処理

scipy.misc.imsave()で保存する際、画像データのdtypeuint8以外は最小値と最大値で規格化される。

画像をファイルから読み込む場合などはdtypeuint8になるなので、問題になる場面は少ないと思うが、注意が必要。

スポンサーリンク

症状

例えば、scipy.misc.lena()で取得できる画像の場合、

  • 最小値: 25
  • 最大値: 245

だが、そのままscipy.misc.imsave()で保存すると、保存された画像は、

  • 最小値: 0
  • 最大値: 255

となり、コントラストが強調されたようになってしまう。

from scipy import misc
import numpy as np
from PIL import Image

lena = misc.lena()
print(lena.min(), lena.max())
# 25 245
misc.imsave('lena_imsave.jpg', lena)

lena_imsave = np.array(Image.open('lena_imsave.jpg'))
print(lena_imsave.min(), lena_imsave.max())
# 0 255

原因

コードをたどると、scipy.misc.imsave()scipy.misc.toimage()ndarrayPIL imageに変換して保存している。さらに、scipy.misc.toimage()の中では、scipy.misc.bytescale()が呼ばれている。

scipy.misc.bytescale()では、uint8以外のタイプはデフォルトで最小値から最大値の範囲に規格化される。

scipy.misc.lena()の画像はタイプがint64なので、規格化されてしまう。

対処法

  • numpy.uint8()でタイプを変える。
  • scipy.misc.bytescale()scipy.misc.toimage()で適切な規格化のパラメータを設定する。
misc.imsave('lena_uint8.jpg', np.uint8(lena))

misc.imsave('lena_bytescale.jpg', misc.bytescale(lena, cmin=0, cmax=255))

misc.toimage(lena, cmin=0, cmax=255).save('lena_toimage.jpg')

cmincmaxが規格化に使われる値で、デフォルトでは入力されるndarrayの最小値と最大値になっている。例えば、10bit(0-1023)の画像のときは、cmin=0cmax=1023とすればよい。

参考

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事