概要
ガンマ補正をする。雰囲気としては
- γ = 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 件のコメント:
コメントを投稿