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