2011-08-07 20 views
2

私のrgbイメージをycbcrイメージに変換したい場合は、その逆もまた手作業で変換します。しかし、間違いがあり、私はそれを見つけることができません。OpenCVからRGBへのYCbCrへの変換(Visual C++)

私の画像は見た目に似ていません。ここ は私のコードです:ここでは

void YCbCrToRGB(IplImage* ScrY, IplImage* ScrCb, IplImage* ScrCr, IplImage* DesR, IplImage* DesG, IplImage* DesB){ 

    for(int i=0; i < ScrY->height; i++){ 
     for(int j=0; j < ScrY->width; j++){ 
      double Y = (double)(ScrY->imageData + ScrY->widthStep*i)[j]; 
      double Cb = (double)(ScrCb->imageData + ScrCb->widthStep*i)[j]; 
      double Cr = (double)(ScrCr->imageData + ScrCr->widthStep*i)[j]; 

      Cb = Cb -128; 
      Cr = Cr -128; 
      int r; 
      int g; 
      int b; 

      (DesR->imageData + DesR->widthStep*i)[j] = (int)(1 * Y + 0 * Cb + 1.4 * Cr); 
      (DesG->imageData + DesG->widthStep*i)[j] = (int)(1 * Y - 0.343 * Cb - 0.711 *Cr); 
      (DesB->imageData + DesB->widthStep*i)[j] = (int)(1* Y + 1.765 * Cb + 0* Cr); 
    }} 

void RGBtoYCbCr(IplImage* ScrR, IplImage* ScrG, IplImage* ScrB, IplImage* DesY, IplImage* DesCb, IplImage* DesCr){ 
    for(int i=0; i < ScrR->height; i++){ 
     for(int j=0; j < ScrR->width; j++){ 
      double R = (double)(ScrR->imageData + ScrR->widthStep*i)[j]; 
      double G = (double)(ScrG->imageData + ScrG->widthStep*i)[j]; 
      double B = (double)(ScrB->imageData + ScrB->widthStep*i)[j]; 

      (DesY->imageData + DesY->widthStep*i)[j] =  0.299 *R + 0.587 *G + 0.114 *B; 
      (DesCb->imageData + DesCb->widthStep*i)[j] =  -0.1687 *R - 0.3313 *G + 0.5 *B + 128; 
      (DesCr->imageData + DesCr->widthStep*i)[j] =  0.5  *R - 0.4187 *G - 0.0813 *B + 128;   
     } 
    }} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    try { 
     IplImage* img = cvLoadImage("C:\\sad-cat.jpg",1); 
     cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE); 
     cvShowImage("Example1", img); 

     IplImage *r = cvCreateImage(cvGetSize(img), img->depth, 1); 
     IplImage *g = cvCreateImage(cvGetSize(img), img->depth, 1); 
     IplImage *b = cvCreateImage(cvGetSize(img), img->depth, 1); 

     cvSplit(img, b, g, r, NULL); 

     IplImage *y = cvCreateImage(cvGetSize(img), img->depth, 1); 
     IplImage *cb = cvCreateImage(cvGetSize(img), img->depth, 1); 
     IplImage *cr = cvCreateImage(cvGetSize(img), img->depth, 1); 


     RGBtoYCbCr(r,g,b,y,cb,cr); 

     IplImage *ycbcr = cvCreateImage(cvGetSize(img), img->depth, 3); 
     cvMerge(y,cb,cr,NULL,ycbcr); 

     cvNamedWindow("YCbCr from RGB", CV_WINDOW_AUTOSIZE); 
     cvShowImage("YCbCr from RGB", ycbcr); 



     YCbCrToRGB(y,cb,cr,r,g,b); 

     IplImage *RGBfromYCbCr = cvCreateImage(cvGetSize(img), img->depth, 3); 
     cvMerge(r,g,b,NULL,RGBfromYCbCr); 

     cvNamedWindow("RGB from YCbCr", CV_WINDOW_AUTOSIZE); 
     cvShowImage("RGB from YCbCr", RGBfromYCbCr); 

     cvWaitKey(0); 
     return 0; 
    } 
    catch(exception& e){ 
     std::cout<<("An error occurred.") << std::endl; 
     std::cout << e.what() <<std::endl; // Print the error message. 
     cvWaitKey(0); 
    } 
} 

は、構文の強調表示とリンクです:http://paste2.org/p/1569904

私はそのキャストエラーまたはこのようなものだと思います。 は非常に

ありがとうPS:私の答えはおそらく愚かですが、あなたは(そのcvShowImageは知っておくべき、

+0

画像http://i.stack.imgur.com/eos3m.jpg – vo1d

+0

私はhttp://www.equasys.de/colorconversion.htmlとhttp://opencv.willowgarage.com/から数式を試しました。 documentation/c/miscellaneous_image_transformations.html – vo1d

答えて

3

は、あなたが得る何を教えてください、そしてそれが動作するかどうはい、それはキャストの問題です。

 double Y = (double)(ScrY->imageData + ScrY->widthStep*i)[j]; 
     double Cb = (double)(ScrCb->imageData + ScrCb->widthStep*i)[j]; 
     double Cr = (double)(ScrCr->imageData + ScrCr->widthStep*i)[j]; 

 double Y = (uchar)(ScrY->imageData + ScrY->widthStep*i)[j]; 
     double Cb = (uchar)(ScrCb->imageData + ScrCb->widthStep*i)[j]; 
     double Cr = (uchar)(ScrCr->imageData + ScrCr->widthStep*i)[j]; 

する必要がありますがRGBtoYCbCrの最初の3行で同じ変更を行います。

また、丸め誤差があります。あなたは、割り当てる前に結果を丸める必要があります。

 (DesY->imageData + DesY->widthStep*i)[j] = round( 0.299 *R + 0.587 *G + 0.114 *B); 
     (DesCb->imageData + DesCb->widthStep*i)[j] = round( -0.1687 *R - 0.3313 *G + 0.5 *B) + 128; 
     (DesCr->imageData + DesCr->widthStep*i)[j] = round( 0.5  *R - 0.4187 *G - 0.0813 *B) + 128;   

cvShowImageはBGRではなく、RGBを想定しているので、最後に、cvMerge(r,g,b,NULL,RGBfromYCbCr);cvMerge(b,g,r,NULL,RGBfromYCbCr);する必要があります。

+0

あなたの悲しい猫は幸せになれば幸いです。 – SSteve

+0

ありがとうございます。猫はとても幸せです。ありがとうございました。 – vo1d

+1

結果は次のとおりです。http://dl.dropbox.com/u/724136/cat-happy.jpg – vo1d

0

まあ(iは二つ以上のリンクや画像を投稿することができないのです)式およびたとえば画像のコメントを参照してください。 )は、それがBGRイメージとして読み取ったものを解釈します。 CbはGチャネルとして

  • Crは解釈を解釈
  • BチャネルとYが解釈

    • :あなたがたYCbCrに変換し、YCbCrのが見えるものを見しようとした場合、それはなりますよう、確かにそれは奇妙に見えるだろうRチャンネル

    として私はあなたのコード上で実行されたテストどの知らない、最高の最終テストから画像を読み取るために、次のようになります。あなたのRGBtoYCbCrのYCbCrToRGB()()

    • 自分のイメージ=> RGBToYCbCr()=> YCbCrToRGB()=> cvShowImageは()

    アドバイスの第二作品、あなたはBGRの画像を作成する場合は、RGBから変換する必要がありますいないかどうかを確認BGRに...

    ジュリアン

    +0

    コメントありがとうございます。 3番目の画像は画像=> RGBToYCbCr()=> YCbCrToRGB()=> cvShowImage()です。私はまたYCbCrToRGBを試み、CvConvertを使ってrgbを元に戻しました。 cvShowImageは、Cvで変換されたYCbCrピクチャを表示しますが、私のものではありません。 – vo1d