2012/11/21

ガンマ補正


概要

ガンマ補正をする。雰囲気としては

  • γ = 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 件のコメント:

Related Posts Plugin for WordPress, Blogger...