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に対して計算した方がいいとか)
よろしくお願いいたします。
No.1ベストアンサー
- 回答日時:
原因は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の構成比率が変化して、
・明るくすると、白っぽくなる
・暗くすると、原色っぽくなる
ということが起ります。
実際に、まともに変換できている写真下部を見ると、全体的に白っぽくなっています。
これを良しとしないのなら、計算に工夫が必要です。
例えば、加減算ではなく、掛け算にするとか。
画像処理の理論は、本やサイトで紹介されていることも多いので、参考にしてはどうでしょうか。
No.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で変える方が直感的で分かりやすい。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Ruby pandasでsqlite3にテーブル作成・追加・読み出しでindexの取り扱い方教えてください 5 2023/03/08 09:57
- Excel(エクセル) 何故割り算なのでしょうか? 6 2022/11/09 13:30
- その他(プログラミング・Web制作) python pandas 行ごとに列名(列番号)を指定して抽出したい 1 2023/05/26 13:47
- Excel(エクセル) エクセルでエラーを無視して一番左側のセルの値を返したい 2 2023/07/27 13:06
- C言語・C++・C# C言語 ポインタ 配列 2 2022/06/02 17:29
- その他(ビジネス・キャリア) Excel関数で、 =INDEX(データE22:E100,1) =INDEX(データE22:E100 1 2023/04/18 00:01
- Visual Basic(VBA) サブフォルダ(データ)にある複数の.xlsxファイルのSheet3のA2セルの値で01から左側をB2 2 2022/08/14 15:46
- Visual Basic(VBA) RemoveDuplicatesメソッドについて教えてください。 シート1にシート2から値をもってく 1 2023/02/28 22:43
- Excel(エクセル) INDEX関数とMATCH関数を使用し値を返す数式についてです 2 2022/04/20 13:40
- Visual Basic(VBA) 集めたシートのシート名を変更したい。 下記のコードでサブフォルダにあるファイルのSheet3を集めて 6 2022/08/23 10:38
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
O(n log n)について2
-
16進数 加算 減算 C言語
-
VB.net Double と...
-
C言語プログラミングにて、arct...
-
”/”を使わずに割り算したいんで...
-
c languageで 簡単な質問があ...
-
EXCELの関数"STDEV(標準偏差)"...
-
10次の多項式を求めるプログラ...
-
powf を使わずにべき乗を計算
-
浮動小数演算は実行環境の変化...
-
差分積分、数値積分の誤差について
-
全加算回路
-
乱数 なぜ剰余を使うのか
-
有効数字について 以前質問をし...
-
ラズベリーパイ>MM-TXS03で温度...
-
多桁計算
-
ハッシュ関数
-
計算が合わない
-
三菱シーケンサ(Aシリーズ)で...
-
コンピューターは指数関数をど...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
O(n log n)について2
-
16進数 加算 減算 C言語
-
c languageで 簡単な質問があ...
-
ExcelでPC(パソコン)によって...
-
”/”を使わずに割り算したいんで...
-
有効数字について 以前質問をし...
-
三角比の俯角の計算
-
ExcelのINT関数の計算結果がお...
-
VB.net Double と...
-
floatの有効桁数
-
パソコンで階乗を計算
-
三菱シーケンサ(Aシリーズ)で...
-
除算を使わずに10で割りたい。
-
VB6.0での小数点の扱いについて
-
EXCELの関数"STDEV(標準偏差)"...
-
時刻の比較
-
VBAでの割り算の余りの求め方
-
計算の丸め誤差の解消について
-
C言語プログラミングにて、arct...
-
VBAでミリ秒まで出力する方法
おすすめ情報
画像が添付出来ていませんでしたので、補足します。
元画像がこちらです。
単にYにトラックバーの値を加算しても、輝度の変更は出来ず、
明らかに変色してしまっているものがこちらです。
お察しの通り、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の方は、暗いところはあまり変化せず、明るいところはより明るく変化する様に見えます。
難しいですね。。
これがaviutilの色調補正で輝度のみ変化させた場合です。
色々と調べていて、自分が知りたかった事は、GIMPやPhotoShopの「トーンカーブ」の式だという事が解りました。
また、回答者様の仰る通り、ここまで書いていた式は、YUV変換する必要は特に無く、RGB値に対して直接加算するのと同じことでした(笑)。
単純な加算の為、RGB値が255(白)に近づき、全体が白くなっていったという事です(笑)。
aviutilでどういった数式で輝度変化させているのかは解りませんが、
GIMPのトーンカーブで確認すると、どうも3次関数の式等で表すと良いようです。
試しにシグモイド関数で下記の様に計算したものを載せておきます。
これはこれで良い効果だと思いました(笑)。
R = (1 / (1 + exp(-track_bar_val * ((R - 127) / 127))))*255;
ここからGIMPの表示を参考に、grapesなどのグラフ描画ソフトで確認していけば、
もっと期待した効果に近い式があると思います。
取り敢えずの足掛かりが出来たので満足です。
ありがとうございました!!