概要
ガンマ補正をする。雰囲気としては
- γ = 1 変更なし
- γ < 1 暗くなる
- γ > 1 明るくなる
ガンマ補正とは http://ja.wikipedia.org/wiki/%E3%82%AC%E3%83%B3%E3%83%9E%E5%80%A4写真加工ソフトだと、「レベル補正」するときに真ん中にある矢印のことをいう。
http://komin2.world.coocan.jp/retouch/level.htm
実装
int main() { // 画像をグレイスケールで読み込む string fileName = "images\\face.jpg"; Mat original = imread(fileName, CV_LOAD_IMAGE_GRAYSCALE); // 出力画像 Mat result; // ガンマ値 float gamma = 0.2; // ルックアップテーブル作成 uchar lut[256]; double gm = 1.0 / gamma; for (int i = 0; i < 256; i++) lut[i] = pow(1.0*i/255, gm) * 255; // 輝度値の置き換え処理 // Matを1行として扱う(高速化のため) Mat p = original.reshape(0, 1).clone(); for (int i = 0; i < p.cols; i++) { p.at<uchar>(0, i) = lut[p.at<uchar>(0, i)]; } // 元の形にもどす result = p.reshape(0, original.rows); // この置き換え処理をする関数が用意されている // LUT(original, Mat(Size(256, 1), CV_8U, lut), result); // 元画像の表示 imshow("original", original); // 結果画像の表示 imshow("result", result); waitKey(0); return 0; }
解説
ある輝度値は、ある輝度値に変換される。
なのでピクセルごとにいちいち値を計算する必要はない。
256階調すべてについて変換後の値を保持しておけばよい。
これをルックアップテーブル(LUT)と呼ぶ。
英語はさっぱりな日本男児でもなんとなく意味は分かると思う。
OpenCVにはLUTによる輝度値の置き換えを行う関数が用意されているが、
本実装ではあえて使わないでおいた☆
この変換は近傍ピクセルの影響を受けないため、
reshape関数によりMatを1行として扱っている。
ゴリラでも勘違いしやすいのだが、reshapeはMatの「読み方」を変えるものであり、
Matを実際に変形するものでもなければ、別の場所にコピーするものでもない。
そのため今回はMatをコピーするclone関数と併用している。
reshape(0, 1).clone()によって一行に変形したMatを新たに生成できる、とでも覚えておこう。
で意味が分かってない君はclone()しないと何が起こるか、ぜひ試してみてほしい。
なお、ルックアップテーブル作成(つまりこの投稿のほとんど)に当たっては以下のサイトを参照した。
http://imagingsolution.blog107.fc2.com/blog-entry-166.html
出力結果
γ = 1.0 |
γ = 0.2 |
γ = 1.8 |
γ = 5.0 |
ゴリ……いやご覧のとおり、
0.2と5.0が同じくらい色が変化していて、対応関係にあることが確認できる。
0 件のコメント:
コメントを投稿