(99) OpenCV #4 : ガンマ補正で画像を見やすく調整

(99) OpenCV #4 : ガンマ補正で画像を見やすく調整

1. やりたいこと

Pythonで OpenCVの第 4回目、今回は OpenCVの Look up table を使って画像のガンマ補正(gamma correction)をやってみる。

2. ガンマ補正とは

ガンマ補正(gamma correction)とは、以下の式で入力値に対する出力値を得ること。
これにより画像の輝度を所望の状態に調整すること。

まずは、入力値(I)と出力値(O)の関係をグラフ上で見てみる。
折角 Pythonを使っているので matplotlib でグラフを表示してみる。

import numpy as np
import matplotlib.pyplot as plt

ary_gamma = np.array([0.1, 0.2, 0.4, 0.67, 1, 1.5, 2.5, 5, 10, 25])

for var_gamma in ary_gamma:
    var_px = np.empty(256, np.uint8)
    for i in range(256):
        var_px[i] = np.clip(pow(i / 255.0, var_gamma) * 255.0, 0, 255)
    plt.plot(var_px, label=str(var_gamma))

plt.legend()
plt.xlabel("INPUT")
plt.ylabel("OUTPUT")
plt.show()

実行すると以下のグラフが表示される。
線ごとに色を指定せずとも自動的に色分けしてくれるので便利だ。

γ = 1 であれば入力値=出力値のリニアな関係になるので画像は何も変わらない。
γ < 1 であれば暗い部分の輝度変化が強調される。
γ > 1 であれば明るい部分の輝度変化が強調される。

3. やってみる

(1) 必要最小限の機能

まずは一切の装飾や利便性などを考慮せず、愚直にガンマ補正機能だけを実行してみる。

import cv2
import numpy as np

# ガンマ値を決める。
gamma = 0.8

# 処理対象の画像をロード
imgS = cv2.imread("img001.png")

# ガンマ値を使って Look up tableを作成
lookUpTable = np.empty((1,256), np.uint8)
for i in range(256):
    lookUpTable[0,i] = np.clip(pow(i / 255.0, gamma) * 255.0, 0, 255)

# Look up tableを使って画像の輝度値を変更
imgA = cv2.LUT(imgS, lookUpTable)

# 表示実行
cv2.namedWindow('image', cv2.WINDOW_AUTOSIZE)
cv2.imshow('image', imgA)
cv2.waitKey()

ガンマ値=0.8で実行したところ、暗い部分が少しだけ見やすくなったか?

(2) 少しだけ機能拡張

上記(1)のシンプル実装プログラムに対して、以下の二つの機能を追加実装した。
追加機能#1 : コマンドラインから、画像ファイルを指定できるようにした。
追加機能#2 : コマンドラインから、ガンマ値を指定できるようにした。

###########################################################
# ガンマ補正プログラム
import argparse
import cv2
import numpy as np

def main():
    # コマンドライン引数「γ値」を取得
    parser = argparse.ArgumentParser()
    parser.add_argument('-g','--gamma', required=True)
    parser.add_argument('-f','--filepath',  required=True)
    args = parser.parse_args()
    # γ補正実行
    exec_gamma_correction( args.filepath, float(args.gamma) )

def exec_gamma_correction( filepath, gamma ):
    # 処理対象の画像をロード
    imgS = cv2.imread(filepath)

    # γ値を使って Look up tableを作成
    lookUpTable = np.empty((1,256), np.uint8)
    for i in range(256):
        lookUpTable[0,i] = np.clip(pow(i / 255.0, gamma) * 255.0, 0, 255)

    # Look up tableを使って画像の輝度値を変更
    imgA = cv2.LUT(imgS, lookUpTable)

    # PILで表示用画像を作成
    from PIL import Image, ImageDraw, ImageFont
    imgA_RGB = cv2.cvtColor(imgA, cv2.COLOR_BGR2RGB)
    imgP = Image.fromarray(imgA_RGB)

    # 画像の左上にγ値の表示を埋め込む
    obj_draw = ImageDraw.Draw(imgP)
    obj_font = ImageFont.truetype("/usr/share/fonts/ipa/ipagp.ttf", 40)
    obj_draw.text((10, 10), "γ = %.1f" % gamma, fill=(255, 255, 255), font=obj_font)

    # 表示実行
    imgP.show()

if __name__=="__main__": main()

Shellから以下の二つのコマンドラインオプションを指定して実行する。
-f : 対象画像ファイルのパス
-g : ガンマ値

python3 gamma_correct.py -f img001.png -g 0.8

以下、いろいろなガンマ値で実行してみた。

でも…
iPhoneの自動補正機能が素晴らしいのか?
ガンマ値=1 が一番きれいに見えるなぁ







4. 参考

ありがとうございます。 m(_ _)m
https://docs.opencv.org/master/d3/dc1/tutorial_basic_linear_transform.html


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*