skimage.transform.rescale関数を使った時にハマったので,備忘録.
色々試行錯誤したコードはページの下の方に載せている. カラー画像とグレースケール画像をで変換する時の色々を載せる.
原画像
以下のように,両画像が8bitの画像として読み込まれる.
color image shape: (512, 512, 3) dtype: uint8 min(): 0 max(): 255 mean(): 114.59900410970052 gray-scale image shape: (512, 512) dtype: uint8 min(): 0 max(): 255 mean(): 118.31400299072266
rescale()
rescale()に原画像とスケールファクタのみを与えると,予期せぬ変換も施される.
最適解と言えないかもしれないが,色々試した結果を如何に示していく.
- カラー画像は色相が3チャンネルから6チャンネルになる
- 数値の範囲: [0, 255]から[0.0, 1.0]になる
- データ型: uint8からfloat64になる
# コードの一部抜粋 img_rescaled = rescale(img, scale_factor) print_image_info(img_rescaled, ' color image', 4) img_rescaled = rescale(img_gray, scale_factor) print_image_info(img_rescaled, ' gray-scale image', 4)
# 実行結果 color image shape: (1024, 1024, 6) dtype: float64 min(): 0.0 max(): 1.0 mean(): 0.44507563581653625 gray-scale image shape: (1024, 1024) dtype: float64 min(): 0.005147058823529662 max(): 0.9975490196078434 mean(): 0.4639770320817536
カラー画像の6チャンネル化を防ぐ
rescale()のオプション引数multichannelをTrueにする. ただし,グレースケール画像を入力する時にTrueにすると,画像の縦方向のみrescaleされることになるので避ける必要がある.
- multichannelをTrueにすると,画像の最後の次元をrescaleしない
- カラー画像は最後の次元である色相が3のまま変化しなくなった
- グレースケール画像は最後の次元である横幅が512のまま変化しなくなった
# コードの一部抜粋 img_rescaled = rescale(img, scale_factor, multichannel=True) print_image_info(img_rescaled, ' color image', 4) img_rescaled = rescale(img_gray, scale_factor, multichannel=True) print_image_info(img_rescaled, ' gray-scale image', 4)
# 実行結果 color image shape: (1024, 1024, 3) dtype: float64 min(): 0.0 max(): 1.0 mean(): 0.4494087048605384 gray-scale image shape: (1024, 512) dtype: float64 min(): 6.520274516386231e-15 max(): 0.9999999999999966 mean(): 0.46397646735696224
数値の範囲を保持したい
rescale()のオプション引数preserve_rangeをTrueにする.
画像のデータ型と数値の範囲についてはここに書いてある.
- preserve_rangeをTrueにすると,出力画像の数値の範囲が保持されている
- グレースケール画像の最小値・最大値が変化してる理由はrescale時の補間処理に原因がありそう
# コードの一部抜粋 # カラー画像は6チャンネル画像にならないように,multichannel=Trueとしている img_rescaled = rescale(img, scale_factor, preserve_range=True, multichannel=True) print_image_info(img_rescaled, ' color image', 4) img_rescaled = rescale(img_gray, scale_factor, preserve_range=True) print_image_info(img_rescaled, ' gray-scale image', 4)
# 実行結果 color image shape: (1024, 1024, 3) dtype: float64 min(): 0.0 max(): 255.0 mean(): 114.5992197394371 gray-scale image shape: (1024, 1024) dtype: float64 min(): 1.312500000000064 max(): 254.37500000000006 mean(): 118.31414318084717
データ型をuint8のままで
img_as_ubyte()によってrescale()の出力をuint8に変換 (当然数値の範囲も[0.0, 1.0]から[0, 255]に変換)
# コードの一部抜粋 # カラー画像は6チャンネル画像にならないように,multichannel=Trueとしている img_rescaled = img_as_ubyte(rescale(img, scale_factor, multichannel=True)) print_image_info(img_rescaled, ' color image', 4) img_rescaled = img_as_ubyte(rescale(img_gray, scale_factor)) print_image_info(img_rescaled, ' gray-scale image', 4)
# 実行結果 color image shape: (1024, 1024, 3) dtype: uint8 min(): 0 max(): 255 mean(): 114.59968185424805 gray-scale image shape: (1024, 1024) dtype: uint8 min(): 1 max(): 254 mean(): 118.31463718414307
コード
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*- import numpy as np import skimage.data from skimage.transform import rescale from skimage.util import img_as_ubyte def print_image_info(img, message=None, spaces=None): assert isinstance(img, np.ndarray) assert len(img.shape) in [2, 3] if message is not None: print(message) if spaces is None: spaces = "" else: spaces = spaces * " " for arg in ['shape', 'dtype', 'min()', 'max()', 'mean()']: exec("print('%s%s:', img.%s)" % (spaces, arg, arg)) def main(): print('Original image') img = skimage.data.astronaut() print_image_info(img, ' color image', 4) img_gray = skimage.data.camera() print_image_info(img_gray, ' gray-scale image', 4) scale_factor = 2.0 print('\nrescale()') img_rescaled = rescale(img, scale_factor) print_image_info(img_rescaled, ' color image', 4) img_rescaled = rescale(img_gray, scale_factor) print_image_info(img_rescaled, ' gray-scale image', 4) print('\nrescale() with multichannel=True') img_rescaled = rescale(img, scale_factor, multichannel=True) print_image_info(img_rescaled, ' color image', 4) img_rescaled = rescale(img_gray, scale_factor, multichannel=True) print_image_info(img_rescaled, ' gray-scale image', 4) print('\nrescale() with preserve_range=True') img_rescaled = rescale(img, scale_factor, preserve_range=True, multichannel=True) print_image_info(img_rescaled, ' color image', 4) img_rescaled = rescale(img_gray, scale_factor, preserve_range=True) print_image_info(img_rescaled, ' gray-scale image', 4) print('\nimg_as_ubyte(rescale())') img_rescaled = img_as_ubyte(rescale(img, scale_factor, multichannel=True)) print_image_info(img_rescaled, ' color image', 4) img_rescaled = img_as_ubyte(rescale(img_gray, scale_factor)) print_image_info(img_rescaled, ' gray-scale image', 4) if __name__ == '__main__': main()