9. 画像調整:画像コンテンツの変換#
9.1. 色の操作#
カラーチャネルを操作するためのほとんどの関数は、サブモジュール skimage.color
にあります。
9.1.1. カラーモデル間の変換#
カラー画像は、異なる色空間を使用して表現できます。最も一般的な色空間の1つは、画像に赤、緑、青のチャネルがあるRGB空間です。ただし、HSVカラーモデル(色相、彩度、値が独立したチャネルである)、または印刷に使用されるCMYKモデルなど、他のカラーモデルも広く使用されています。
skimage.color
は、画像を異なる色空間との間で変換するためのユーティリティ関数を提供します。整数型の配列は、変換操作によって浮動小数点型に変換できます。
>>> # bright saturated red
>>> red_pixel_rgb = np.array([[[255, 0, 0]]], dtype=np.uint8)
>>> color.rgb2hsv(red_pixel_rgb)
array([[[ 0., 1., 1.]]])
>>> # darker saturated blue
>>> dark_blue_pixel_rgb = np.array([[[0, 0, 100]]], dtype=np.uint8)
>>> color.rgb2hsv(dark_blue_pixel_rgb)
array([[[ 0.66666667, 1. , 0.39215686]]])
>>> # less saturated pink
>>> pink_pixel_rgb = np.array([[[255, 100, 255]]], dtype=np.uint8)
>>> color.rgb2hsv(pink_pixel_rgb)
array([[[ 0.83333333, 0.60784314, 1. ]]])
9.1.2. RGBAからRGBへの変換 - アルファブレンディングによるアルファチャネルの削除#
RGBA画像を背景とアルファブレンディングすることによってRGB画像に変換することは、rgba2rgb()
を使用して実現されます。
>>> import skimage as ski
>>> img_rgba = ski.data.logo()
>>> img_rgb = ski.color.rgba2rgb(img_rgba)
9.1.3. カラー値とグレー値間の変換#
RGB画像をグレースケール画像に変換することは、rgb2gray()
を使用して実現されます。
>>> img = ski.data.astronaut()
>>> img_gray = ski.color.rgb2gray(img)
rgb2gray()
は、人間の目が異なる色に対して異なる感度を持つため、カラーチャネルの不均一な重み付けを使用します。したがって、このような重み付けは、RGBからグレースケールへの輝度保持を保証します。
>>> red_pixel = np.array([[[255, 0, 0]]], dtype=np.uint8)
>>> ski.color.rgb2gray(red_pixel)
array([[ 0.2125]])
>>> green_pixel = np.array([[[0, 255, 0]]], dtype=np.uint8)
>>> ski.color.rgb2gray(green_pixel)
array([[ 0.7154]])
gray2rgb()
を使用したグレースケール画像のRGBへの変換は、3つのカラーチャネル全体でグレースケール値を複製するだけです。
9.1.4. 画像の反転#
反転した画像は、補色画像とも呼ばれます。バイナリ画像の場合、Trueの値はFalseになり、その逆も同様です。グレースケール画像の場合、ピクセル値はデータ型の最大値と実際の値の差に置き換えられます。RGB画像の場合、同じ操作が各チャネルに対して行われます。この操作は、skimage.util.invert()
を使用して実現できます。
>>> import skimage as ski
>>> img = ski.data.camera()
>>> inverted_img = ski.util.invert(img)
9.1.5. ラベル付き画像のペイント#
label2rgb()
を使用して、同じ色で表現される領域をエンコードするラベルの配列を使用して、グレースケール画像に色を重ねることができます。

9.2. コントラストと露出#
画像ピクセルは、画像のdtype
(画像のデータ型とその意味を参照)によって決定される値を取ることができます。たとえば、uint8
画像の場合は0〜255、浮動小数点画像の場合は[0, 1]
などです。ただし、ほとんどの画像は、値の範囲が狭い(コントラストが低いため)、またはほとんどのピクセル値がアクセス可能な値のサブ範囲に集中しています。skimage.exposure
は、強度値をより広い範囲に広げる関数を提供します。
最初の手法は、特定の画像のピクセル値とは独立した、強度の非線形関数を計算します。このような方法は、センサーや人間の目などの受容体の既知の非線形性を補正するために使用されることがよくあります。よく知られた例は、ガンマ補正であり、adjust_gamma()
に実装されています。
他のメソッドは、画像のヒストグラムに従ってピクセル値を再配布します。ピクセル値のヒストグラムは、skimage.exposure.histogram()
で計算されます。
>>> import numpy as np
>>> import skimage as ski
>>> image = np.array([[1, 3], [1, 1]])
>>> ski.exposure.histogram(image)
(array([3, 0, 1]), array([1, 2, 3]))
histogram()
は、各値ビンに対するピクセル数と、ビンの中心を返します。したがって、histogram()
の動作は、ビンの境界を返すnumpy.histogram()
の動作とはわずかに異なります。
最も単純なコントラスト強調rescale_intensity()
は、線形変換を使用して、ピクセル値を許容される範囲全体に引き伸ばすことです。
>>> import skimage as ski
>>> text = ski.data.text()
>>> text.min(), text.max()
(10, 197)
>>> better_contrast = ski.exposure.rescale_intensity(text)
>>> better_contrast.min(), better_contrast.max()
(0, 255)
画像が値の範囲全体を使用している場合でも、場合によっては、値の範囲の両端に非常に小さな重みしかありません。このような場合、画像のパーセンタイルを使用してピクセル値をクリッピングすると、コントラストが向上します(ただし、一部のピクセルがこの操作によって飽和するため、情報がいくらか失われます)。
>>> moon = ski.data.moon()
>>> v_min, v_max = np.percentile(moon, (0.2, 99.8))
>>> v_min, v_max
(10.0, 186.0)
>>> better_contrast = ski.exposure.rescale_intensity(moon, in_range=(v_min, v_max))
関数equalize_hist()
は、ピクセル値の累積分布関数(cdf)を線形cdfにマッピングし、値の範囲のすべての部分が画像で均等に表現されるようにします。その結果、コントラストの低い大きな領域で詳細が強調されます。さらに洗練されたものとして、画像全体の露出勾配を修正するために、equalize_adapthist()
を使用して、画像のサブ領域でヒストグラム平坦化を実行できます。例ヒストグラム平坦化を参照してください。
