0

I have a problem to convert an image captured from a camera in YUV format to RGB format.

The function which is used to do it is the following :

int uwidth = 1920;
int uheight= 1080;

int i = 0,j = 0, r = 0, g = 0, b = 0;
typedef unsigned char BYTE;
IplImage* m_RGB = cvCreateImage(cvSize(uwidth, uheight), IPL_DEPTH_8U, 3);
unsigned char* pData = (unsigned char *) frameBytes;

for(i = 0, j=0; i < uwidth * uheight*3 ; i+=6, j+=4)
{
   unsigned char u = pData[j];
   unsigned char y = pData[j+1];
   unsigned char v = pData[j+2];

   b = 1.0*y + 8 + 1.402*(v-128);
   g = 1.0*y - 0.34413*(u-128) - 0.71414*(v-128);
   r = 1.0*y + 1.772*(u-128);

   if(r>255) r =255;
   if(g>255) g =255;
   if(b>255) b =255;
   if(r<0)   r =0;
   if(g<0)   g =0;
   if(b<0)   b =0;

   m_RGB->imageData[i] = (BYTE)(r*220/256);
   m_RGB->imageData[i+1] = (BYTE)(g*220/256);
   m_RGB->imageData[i+2] =(BYTE)(b*220/256);

}

cvNamedWindow("ck", CV_WINDOW_AUTOSIZE);
cvShowImage( "ck", m_RGB );
cvReleaseImage(&m_RGB);

The problem is that we have not one but two images in the window on my screen, and that we have good colors but not the good ratio.

Does anyone have an idea about those problems ?

Edit: Image output

UmNyobe
  • 21,341
  • 8
  • 52
  • 85
nico_db
  • 1
  • 1
  • 3
  • http://stackoverflow.com/questions/8042563/correct-yuv422-to-rgb-conversion/8616223#8616223 The idea is that some YUV formats are different than what you'd expect. Find the exact one you are using, and implement your algorithm accordingly – Sam Aug 29 '12 at 13:58

2 Answers2

1

Let's assume imageData is defined as

BYTE* imageData;

In this case this loop tells a lot:

for(i = 0, j=0; i < uwidth * uheight*3 ; i+=6, j+=4)

i+=6 means each time you set a pixel you will skip the next pixel (or what you expected to do, set 2 pixels at a time).

j+=4
unsigned char u = pData[j];
unsigned char y = pData[j+1];
unsigned char v = pData[j+2];

Means that the format of your camera is UYVY :

  • It describe two successive pixels P0 and P1
  • The chroma channel is the same for P0 and P1.U = U0 = U1 and V = V0 = V1
  • The lumina channel is different. the first is for P0, the second for P1.

You need to set 2 pixels by iterations :

m_RGB->imageData[i] = r1;
m_RGB->imageData[i+1] = g1;
m_RGB->imageData[i+2] =b1;
m_RGB->imageData[i+3] = r2;
m_RGB->imageData[i+4] = g2;
m_RGB->imageData[i+5] =b2;

The difference between r1 and r2 (and others) is that you use two different Y in the conversion formula.

UmNyobe
  • 21,341
  • 8
  • 52
  • 85
1

If you're programming for Mac, have a look at the recent additions to the vImage conversion library in OSX 10.9 and even 10.10. The stuff in there is truly mind blowing. I was doing my own 24-bit to 32-bit conversions and had it honed to about 6ms/frame (1920x1080). Promptly blown out of the water by vImage more than 15X.

zzyzy
  • 903
  • 5
  • 18