2016-06-14 41 views
1

画像をRGBAからYUV422形式に変換したい。以下は私のコードです:C++を使用してRGBAをYUV422形式に変換する - 適切な出力が得られない

#include "opencv2/highgui/highgui.hpp" 
#include "opencv2/imgproc/imgproc.hpp" 
#include <iostream> 
#include <stdio.h> 
#include <stdlib.h> 

using namespace cv; 
using namespace std; 

#define CLIP(X) ((X) > 255 ? 255 : (X) < 0 ? 0 : X) 
#define RGB2Y(R, G, B) CLIP((( 66 * (R) + 129 * (G) + 25 * (B) + 128) >> 8) + 16) 
#define RGB2U(R, G, B) CLIP(((-38 * (R) - 74 * (G) + 112 * (B) + 128) >> 8) + 128) 
#define RGB2V(R, G, B) CLIP(((112 * (R) - 94 * (G) - 18 * (B) + 128) >> 8) + 128) 

int main(int argc, char *argv[]) 
{ 

    Mat in_img, in_RGB, out_yuv; 
    in_img = imread(argv[1],1); 
    if(!in_img.data) 
    { 
     printf("Failed to load the image ... %s\n!", argv[1]); 
     return -1; 
    } 
    short imgwidth = in_img.cols; 
    short imgheight = in_img.rows; 

    cvtColor(in_img, in_RGB, CV_BGR2RGB); 
    out_yuv.create(imgheight, imgwidth, CV_16U); 

    imwrite("RGB.jpg",in_RGB); 

    for(int i = 0; i< imgheight; i++) 
     for(int j = 0; j< imgwidth; j = j+2) { 
      unsigned int val = in_RGB.at<unsigned int>(i,j); 

/*********** for 1st pixel ***********/ 
      unsigned int tmp = val; 
      unsigned char B = (unsigned char)(((tmp<<16) >> 24) | 0x000000ff); //Extracting B channel data 

      tmp = val; 
      unsigned char G = (unsigned char)(((tmp<<8) >> 24) | 0x000000ff); //Extracting G channel data 

      tmp = val; 
      unsigned char R = (unsigned char)((tmp >> 24) | 0x000000ff); //Extracting R channel data 

      unsigned char Y1 = RGB2Y(R, G, B); 
      unsigned char U = RGB2U(R, G, B); 
      unsigned char V = RGB2V(R, G, B); 

/*********** for 2nd pixel ***********/ 
      unsigned int val1 = in_RGB.at<unsigned int>(i,j+1); 
      unsigned int tmp1 = val1; 
      unsigned char B1 = (unsigned char)(((tmp1<<16) >> 24) | 0x000000ff); 

      tmp1 = val1; 
      unsigned char G1 = (unsigned char)(((tmp1<<8) >> 24) | 0x000000ff); 

      tmp1 = val1; 
      unsigned char R1 = (unsigned char)((tmp1 >> 24) | 0x000000ff); 

      unsigned char Y2 = RGB2Y(R, G, B); 

/********** writing into out image in U-Y1-V-Y2 format *********************/ 

     unsigned short p1 = ((U << 8) | Y1) ; 
     unsigned short p2 = ((V << 8) | Y2) ; 
     out_yuv.at<unsigned short>(i,j) = p1; 
     out_yuv.at<unsigned short>(i,j+1) = p2; 

    } 
     imwrite("YUV422.png",out_yuv); 
return 0; 
} 

しかし、適切な出力イメージが得られません。私はY1-U-Y2-Vフォーマットでも同じ出力を書こうとしました。上記のコードで何が間違っているのか、または問題の原因となる出力イメージ形式(.png/.jpg)ですか? (CV ::関数imwriteは.yuv形式で保存はできません)ここ

+0

画像を使用すると、アルファチャンネル – EdChum

+0

'関数imwriteスキップ/ハンドリングている場所、私は見ていないRGBAであれば(「YUV422.pngを」、out_yuv);'あなたは結果の画像を表示するために使うのですか? – UmNyobe

+0

@EdChum:アルファチャンネル(LSB 8ビット)を無視し、 'R'、 'G'、 'B'チャンネル(MSB 24ビット)を抽出します。 – Goutham

答えて

1
out_yuv.create(imgheight, imgwidth, CV_16U); 
... 
imwrite("YUV422.png",out_yuv); 

いくつかの問題:

  • imwriteCV_16Uto be mono channelを検討します。
  • yuvをpng内に書き込むことはできません。あなたは、データrawをダンプし、raw yuvplayerのような特別なyuvビューアを使用して、データが正しいことを確認する必要があります。

編集:生のピクセルの頭字語はちょっとビッグエンディアンであることを
注意、左端の値は、メモリ内の最下位バイト、すなわち(ほとんどの時間、ビデオの人々は混乱を愛する)

  • RGBA R = RGB[0]G = RGB[1]B = RGB[2]A = RGB[3]
  • YUYVバッファp手段意味するp[0]は、Y0であるp[1]はUであり、p[2]がY1であり、012意味しますがV

あなたはあなたのシフト:)

編集2と正反対をやっているである:あなたのイメージがまだスクランブルされている場合は 、あなたは平面形式以下の書き込みを喜んでいるように見えます(YUV422 P別名YV16)。平面形式とは、各チャネルが別々の連続した平面にあることを意味します。ターゲットデータ(普通の古いバッファ)(unsigned char*、またはstd::vector<unsigned char>)を使用する方が明確です。

unsigned char* out_yuv_ptr = new unsigned char[imgwidth*imgheight*2]; 
unsigned char* y_ptr = out_yuv_ptr; 
unsigned char* u_ptr = y_ptr + imgwidth*imgheight; 
unsigned char* v_ptr = u_ptr + imgwidth*imgheight/2; 
... 
*y_ptr = Y1; 
++y_ptr 
*y_ptr = Y2; 
++y_ptr 
*u_ptr = U; 
++u_ptr; 
*v_ptr = V; 
++v_ptr; 
+0

あなたの提案をありがとうございました、それは本当に役立ちました。 私はデータを 'にダンプしました。yuv 'ファイルを作成します。 [raw yuvplayer](https://sourceforge.net/projects/raw-yuvplayer/)でチェックすると、スクランブルされた出力が表示されます(適切な画像サイズとカラーエンコーディング(YUV422)がプレーヤーに設定されています)。プレーヤーの「カラー」オプションをYUYV/UYVYに変更すると、オリジナルとは異なる色を除いて、期待どおりの出力イメージが得られます。今私は、コードに従った変換方法が正しいかどうか疑問に思う。これを知る方法はありますか? – Goutham

+0

@quintello編集を参照してください。 – UmNyobe

+0

私はエンディアンタイプを修正しましたが、出力は** YUYV **フォーマットで完璧と思われますが、元の意図はYUV422フォーマットに変換することです(これはまだスクランブルされています)。私はどこからYUV422からYUYVへの道を離れましたか? – Goutham

関連する問題