2

次の式を使用して、RGBマトリックスをYUVマトリックスに変換しました。

Y  =      (0.257 * R) + (0.504 * G) + (0.098 * B) + 16
Cr = V =  (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
Cb = U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128

次に、マトリックスで4:2:0クロマサブサンプルを実行しました。私はこれを正しく行ったと思います。YUVマトリックスから2x2の部分行列を取得し、値を最小から最大の順に並べ、中央の2つの値の平均を取得しました。

次に、ウィキペディアの次の式を使用して、Y、U、およびV平面にアクセスしました。

size.total = size.width * size.height;
y = yuv[position.y * size.width + position.x];
u = yuv[(position.y / 2) * (size.width / 2) + (position.x / 2) + size.total];
v = yuv[(position.y / 2) * (size.width / 2) + (position.x / 2) + size.total + (size.total / 4)];

私はOpenCVを使用しているので、これを可能な限り解釈しようとしました。

y = src.data[(i*channels)+(j*step)];
u = src.data[(j%4)*step + ((i%2)*channels+1) + max];
v = src.data[(j%4)*step + ((i%2)*channels+2) + max + (max%4)];

srcはYUVサブサンプリングされた行列です。私はその式を正しく解釈しましたか?

これが私が色をRGBに戻す方法です:

bgr.data[(i*channels)+(j*step)] = (1.164 * (y - 16)) + (2.018 * (u - 128)); // B
bgr.data[(i*channels+1)+(j*step)] = (1.164 * (y - 16)) - (0.813 * (v - 128)) - (0.391 * (u - 128)); // G
bgr.data[(i*channels+2)+(j*step)] = (1.164 * (y - 16)) + (1.596 * (v - 128));   // R

問題は、私の画像が元の色に戻らないことです。

参考用の画像は次のとおりです。http: //i.stack.imgur.com/vQkpT.jpg(サブサンプル) http://i.stack.imgur.com/Oucc5.jpg(出力)

YUV444からRGBに変換する必要があるようですが、Wikiで見つけたサンプルでクリップ関数が何をするのかよくわかりません。

C = Y' − 16
D = U − 128
E = V − 128

R = clip(( 298 * C           + 409 * E + 128) >> 8)
G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
B = clip(( 298 * C + 516 * D           + 128) >> 8)

>>は、ビットをシフトする必要があることを意味しますか?

ヘルプ/コメントをいただければ幸いです。ありがとう

アップデート

YUV444変換を試みましたが、画像が緑の色合いで表示されました。

        y = src.data[(i*channels)+(j*step)];
        u = src.data[(j%4)*step + ((i%2)*channels+1) + max];
        v = src.data[(j%4)*step + ((i%2)*channels+2) + max + (max%4)];

        c = y - 16;
        d = u - 128;
        e = v - 128;

        bgr.data[(i*channels+2)+(j*step)] = clip((298*c + 409*e + 128)/256);
        bgr.data[(i*channels+1)+(j*step)] = clip((298*c - 100*d - 208*e + 128)/256);
        bgr.data[(i*channels)+(j*step)] = clip((298*c + 516*d + 128)/256);

そして私のクリップ関数:int clip(double value){return(value> 255)?255 :(値<0)?0:値; }

4

3 に答える 3

2

WebMフレームをRGBにデコードするときに同じ問題が発生しました。何時間も検索した後、ようやく解決策を見つけました。

ここからSCALEYUV関数を取得します:http ://www.telegraphics.com.au/svn/webpformat/trunk/webpformat.h

次に、YUVからRGBデータをデコードするには、次のファイルを参照してください: http ://www.telegraphics.com.au/svn/webpformat/trunk/decode.c

「py=img-> planets [0];」を検索すると、データを変換するための2つのアルゴリズムがあります。私は単純なものだけを試しました(「//その後、より安価な方法にフォールバックします。」)。

コード内のコメントは、このページも参照しています:http ://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC30

私にとっては素晴らしい作品です。

于 2011-07-14T17:15:41.897 に答える
1

UVは画像を圧縮するため、完全に同じ画像を取り戻すことはできません。
結果が完全に間違っている(つまりエラー)のか、それとも完全ではないのかはわかりません

R = clip(( 298 * C           + 409 * E + 128) >> 8)
G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
B = clip(( 298 * C + 516 * D           + 128) >> 8)

>> 8はビットシフトであり、256で除算するのと同じです。これは、速度の浮動小数点ではなく、整数単位ですべての算術演算を実行できるようにするためのものです。

于 2011-07-03T03:31:50.677 に答える
0

ウィキに存在する数式を試していたところ、混合数式が見つかりました:

byte c = (byte) (y - 16);
byte d = (byte) (u - 128);
byte e = (byte) (v - 128);

byte r = (byte) (c + (1.370705 * (e))); 
byte g = (byte) (c - (0.698001 * (d)) - (0.337633 * (e)));
byte b = (byte) (c + (1.732446 * (d)));

私の画像に「より良い」エラーを生成し、いくつかの黒い点を純粋な緑(つまり、rgb = 0x00FF00)にします。これは、検出と修正に適しています...

ウィキソース:https ://en.wikipedia.org/wiki/YUV#Y.27UV420p_.28and_Y.27V12_or_YV12.29_to_RGB888_conversion

于 2015-09-05T17:49:15.767 に答える