OpenCV converts RGB to YCbCr and vice versa (Visual C ++)

I want to convert rgb image to ycbcr image and vice versa. But there is a mistake, and I cannot find it.

My images do not look as they should. Here is my code:

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); } } 

Here is the syntax highlighted link: http://paste2.org/p/1569904

I think this is a casting error or something like that. THANK YOU VERY MUCH

PS: see comments for formula and sample image (I am not allowed to post more than two links or images)

+2
source share
2 answers

Yes, this is a casting issue.

  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]; 

it should be

  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]; 

Make the same change in the first three lines of RGBtoYCbCr .

In addition, you have rounding errors. You must round the results to the destination:

  (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; 

Finally, cvMerge(r,g,b,NULL,RGBfromYCbCr); must be cvMerge(b,g,r,NULL,RGBfromYCbCr); because cvShowImage assumes BGR, not RGB.

+3
source

Well, my answer may be stupid, but you should know that cvShowImage () interprets what it reads as BGR images. If you convert to YCbCr and try to see what YCbCr looks like, it will probably look strange, like it will:

  • Y is interpreted as channel B
  • Cb is interpreted as a G-channel
  • Cr is interpreted as an R channel

I don’t know which test you used on your code, the best final test would be to read the image from: YCbCrToRGB () of your RGBtoYCbCr ()

  • your image => RGBToYCbCr () => YCbCrToRGB () => cvShowImage ()

Second tip, check if you are recording BGR images, if not, you will need to convert from RGB to BGR ...

Tell me what you get, and if it works or not,

Julien

0
source

Source: https://habr.com/ru/post/895214/


All Articles