stackoverflow で見つけたコードをコピーして貼り付け、デフォルトのカメラ プレビュー YUV を RGB 形式に変換し、それを OpenGL にアップロードして処理しました。問題は、YUV 画像を RGB 形式に変換する際に CPU のほとんどがビジー状態になり、ボトルネックになったことです。
YUV 画像を GPU にアップロードしてから、フラグメント シェーダーで RGB に変換したいと考えています。CPUで動作するJava YUV to RGB関数を見つけて、GPUで動作させようとしました。
Java と GPU での計算の実行にはいくつかの違いがあるため、これはかなりの悪夢になりました。まず、Java ではプレビュー画像は byte[] で表示されますが、バイトは署名されているため、負の値が含まれている可能性があります。
さらに、フラグメント シェーダーは通常、バイトの代わりに [0..1] の浮動値を処理します。
これは解決可能であると確信しており、ほとんど解決しました。しかし、何が間違っているのかを理解するのに数時間を費やしましたが、うまくいきませんでした。
結論として、誰かにこのシェーダー関数を書いて、できればテストしてもらいたいと思います。私にとっては、この変換がこのように機能する理由がよくわからないため、退屈なサルの仕事であり、GPU で同じ機能を模倣しようとしています。
これは、私が Java で使用したものと非常によく似た関数です: Displaying YUV Image in Android
次のように、1.5*w h バイトの YUV 形式を aw h*YUV に変換するなど、CPU でいくつかの作業を行いました。
static public void decodeYUV420SP(int[] rgba, byte[] yuv420sp, int width,
int height) {
final int frameSize = width * height;
for (int j = 0, yp = 0; j < height; j++) {
int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
for (int i = 0; i < width; i++, yp++) {
int y = (int) yuv420sp[yp]+127;
if ((i & 1) == 0) {
v = (int)yuv420sp[uvp++]+127;
u = (int)yuv420sp[uvp++]+127;
}
rgba[yp] = 0xFF000000+(y<<16) | (u<<8) | v;
}
}
}
バイトが署名されているため、127 を追加しました。次に、rgba を OpenGL テクスチャにロードし、残りの計算を GPU で実行しようとしました。
どんな助けでも感謝されます...