dポイントプレゼントキャンペーン実施中!

Aviutilの色調補正のような機能をスクリプトで実装しようと思い、
トラックバーによる輝度の変更を考えていて、
輝度はYUVのYにあたるものという事を知り、
RGBで受け取ったフレームのデータをYUVに変換してYを弄って戻すような、
処理を作成しています。

[1]dllに書いた関数で対象フレームのRGBデータとトラックバーの値を受け取り
[2]YUV変換
[3]輝度のみにトラックバーの値を加算
[4]RGBに戻して返す

RGB→YUV→RGBの処理は書けたのですが、
[3]でどういう式を書けばいいのか解りません。
単純にYにトラックバーの値を足しただけだと、
添付の画像のように変に色が変わってしまいます。

//フレームは幅w、高さh
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int index = x + w * y;
[2]
Y = 0.299 * pixels[index].r + 0.587 * pixels[index].g + 0.114 * pixels[index].b ;
U = -0.169 * pixels[index].r - 0.331 * pixels[index].g + 0.500 * pixels[index].b ;
V = 0.500 * pixels[index].r - 0.419 * pixels[index].g - 0.081 * pixels[index].b ;
[3]
//Y += トラックバーの値;
[4]
pixels[index].r = 1.000*Y + 1.402*V;
pixels[index].g = 1.000*Y - 0.344*U - 0.714*V;
pixels[index].b = 1.000*Y + 1.772*U;
}
}

もしくは何か他の方法がありますか?(RGBに対して計算した方がいいとか)
よろしくお願いいたします。

「【C言語】RGBと輝度の計算に関して」の質問画像

質問者からの補足コメント

  • つらい・・・

    画像が添付出来ていませんでしたので、補足します。
    元画像がこちらです。

    「【C言語】RGBと輝度の計算に関して」の補足画像1
      補足日時:2020/01/22 12:33
  • つらい・・・

    単にYにトラックバーの値を加算しても、輝度の変更は出来ず、
    明らかに変色してしまっているものがこちらです。

    「【C言語】RGBと輝度の計算に関して」の補足画像2
      補足日時:2020/01/22 12:36
  • お察しの通り、pixelsはunsignded charで、YUVはdoubleで計算しておりました。
    暫定対応として、代入前に
    if ((1.000 * Y + 1.402 * V) < 0) {
    pixels[index].r = 0;
    }else if ((1.000 * Y + 1.402 * V) > 255) {
    pixels[index].r = 255;
    }else {
    pixels[index].r = 1.000 * Y + 1.402 * V;
    }
    とすると、添付画像の様な、まともな?(単純に白っぽくなる)変化が得られました。
    ありがとうございます。

    ですが、これまたaviutilのフィルタ機能の色調補正の輝度の変化とはかなり異なっていて、
    aviutilの方は、暗いところはあまり変化せず、明るいところはより明るく変化する様に見えます。
    難しいですね。。

    「【C言語】RGBと輝度の計算に関して」の補足画像3
    No.1の回答に寄せられた補足コメントです。 補足日時:2020/01/25 15:49
  • どう思う?

    これがaviutilの色調補正で輝度のみ変化させた場合です。

    「【C言語】RGBと輝度の計算に関して」の補足画像4
      補足日時:2020/01/25 15:56
  • HAPPY

    色々と調べていて、自分が知りたかった事は、GIMPやPhotoShopの「トーンカーブ」の式だという事が解りました。
    また、回答者様の仰る通り、ここまで書いていた式は、YUV変換する必要は特に無く、RGB値に対して直接加算するのと同じことでした(笑)。
    単純な加算の為、RGB値が255(白)に近づき、全体が白くなっていったという事です(笑)。

    aviutilでどういった数式で輝度変化させているのかは解りませんが、
    GIMPのトーンカーブで確認すると、どうも3次関数の式等で表すと良いようです。
    試しにシグモイド関数で下記の様に計算したものを載せておきます。
    これはこれで良い効果だと思いました(笑)。

    R = (1 / (1 + exp(-track_bar_val * ((R - 127) / 127))))*255;

    「【C言語】RGBと輝度の計算に関して」の補足画像5
      補足日時:2020/01/28 19:19
  • うれしい

    ここからGIMPの表示を参考に、grapesなどのグラフ描画ソフトで確認していけば、
    もっと期待した効果に近い式があると思います。
    取り敢えずの足掛かりが出来たので満足です。
    ありがとうございました!!

      補足日時:2020/01/28 19:22

A 回答 (2件)

原因は2つあります。



1. 意図しない計算間違いが発生している。
 pixels[index] の構造体の各メンバーの型がわかりませんが、 unsigned char (8bit256階調)ではないですか? 。
  そうだとすると、単純に計算した場合、 r,g,b の値が 255超や0未満になる可能性があります。
この場合、C言語では、8bitのみに注目して、溢れたビットを無視します。
値が257 になったら、実際には 1 扱いです。

そういう視点で見ると、その画像の変化も納得できます。
・右上の白いところは、r,g,b全てが255を越えて小さな値になったので、黒(っぽいグレー)に変わった。
・左下は元々赤っぽい。ということは、r成分が他より高め。
 よって、rだけが255を越えた結果小さくなり、G,Bはまだ255に達してないので、それなりの値をキープしている
 その結果、青+緑でシアンっぽい色になってしまっている

/*
 細かいことを言えば
 変数 Y,U,V の型もわからないので、ここでも計算間違いが起っている可能性もあります。
*/


2.期待していたのと、感覚的に違う色合いになってしまう可能性がある。
 計算式をよく見てもらうとわかるのですが。
Y を d だけ足す/引く
ことと
R,G,Bそれぞれに dを足す/それぞれから dを引く
ことが同じ結果になります。

単純に足し引きすると、R,G,Bの構成比率が変化して、
・明るくすると、白っぽくなる
・暗くすると、原色っぽくなる
ということが起ります。

実際に、まともに変換できている写真下部を見ると、全体的に白っぽくなっています。

これを良しとしないのなら、計算に工夫が必要です。
例えば、加減算ではなく、掛け算にするとか。


画像処理の理論は、本やサイトで紹介されていることも多いので、参考にしてはどうでしょうか。
この回答への補足あり
    • good
    • 2

Yだけ変更しても輝度はさほど変わらず、色合いがおかしくなります。


輝度を変えたいなら、YUV全て変更しなければなりません。

また、YUVは、ヨーロッパなどのテレビ用のPALやSECAMの
コンポーネント信号です。

日本だから、YCrCb(SD映像)か、YPbPb(HD映像)を使ってください。
で、YCrCbで説明すると、
Y:輝度信号(RGBの合成)
Cr:Y-R
Cb:Y-B

3つともYが含まれているので、輝度を変えるなら、
3つとも変更しなければならない。
YUVも同じ事で、3つ変えないと輝度の増減が出来ない。

なので、輝度を変えるなら、RGBで変える方が直感的で分かりやすい。
    • good
    • 0
この回答へのお礼

それはどういく計算式になりますか?

お礼日時:2020/01/26 06:23

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!