OpenCV конвертирует RGB в YCbCr и наоборот вручную (Visual C ++) - PullRequest
2 голосов
/ 07 августа 2011

Я хочу преобразовать мое изображение RGB в изображение YCBCR и наоборот вручную.Но есть ошибка, и я не могу ее найти.

Мои изображения выглядят не так, как должны.Вот мой код:

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: См. Комментарии к формуле и пример изображения (мне не разрешено размещать более двух ссылок или изображений)

Ответы [ 2 ]

3 голосов
/ 08 августа 2011

Да, это проблема кастинга.

        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.

Кроме того, у вас есть ошибки округления. Вы должны округлить результаты перед присвоением:

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

Наконец, cvMerge(r,g,b,NULL,RGBfromYCbCr); должно быть cvMerge(b,g,r,NULL,RGBfromYCbCr);, поскольку cvShowImage предполагает BGR, а не RGB.

0 голосов
/ 08 августа 2011

Ну, мой ответ может быть глупым, но вы должны знать, что cvShowImage () интерпретирует то, что он читает, как изображения BGR.Если вы конвертируете в YCbCr и попытаетесь посмотреть, как выглядит YCbCr, наверняка это будет выглядеть странно, так как это будет выглядеть так:

  • Y интерпретируется как B канал
  • Cb интерпретируется как Gchannel
  • Cr интерпретируется как R channel

Я не знаю, какой тест вы выполняли по своему коду, лучшим финальным тестом будет чтение изображения из: YCbCrToRGB () изyour RGBtoYCbCr ()

  • ваше изображение => RGBToYCbCr () => YCbCrToRGB () => cvShowImage ()

Второй совет,проверьте, если вы пишете изображения BGR, если нет, вам нужно конвертировать из RGB в BGR ...

Скажите, что вы получаете, и если это работает,

Julien

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...