Showing posts with label YUV. Show all posts
Showing posts with label YUV. Show all posts

12/23/2014

yuv422(YUYV) to RGB and RGB to yuv422(YUYV), (Using OpenCV and TBB)

In past, I wrote an articel about YUV 444, 422, 411 introduction and yuv <-> rgb converting example code.
refer to this page -> http://feelmare.blogspot.kr/2012/11/yuv-color-format-444-422-411-simple.html

In this article, I will introduce method of using opencv and TBB.
TBB is an acronym for Thread Building Block.
TBB is to enable parellel processing using multi thread.
see the this page -> http://feelmare.blogspot.kr/2014/12/opencv-tbb-utility-parallelfor.html


This is YUV422 to RGB example source code.
In my case YUV422 is consisted of YUYV.
And input type of the YUYV data is unsigned char *.

So example is
unsigned char * yuyv to Mat rgb
In here, m_stride is real width length of yuyv data.

....
Mat yuyv(m_height, m_width, CV_8UC2);
memcpy( yuyv.data, yuyv_buffer, sizeof(unsigned char) * (m_stride * m_height) );
Mat rgb(m_height, m_width, CV_8UC3);
cvtColor(yuyv, rgb, CV_YUV2BGR_YUYV);
....



Next example is rgb to yuyv using TBB.
....
class Parallel_process : public cv::ParallelLoopBody
{

private:
 cv::Mat& inImg;
 unsigned char* outImg;
 int widhStep;
 int m_stride;

public:
 Parallel_process(cv::Mat& inputImgage,  unsigned char* outImage)
  : inImg(inputImgage), outImg(outImage){

   widhStep = inputImgage.size().width * 3; 
   m_stride = inputImgage.size().width *2;

 }

 virtual void operator()(const cv::Range& range) const
 {
  //thread
  for(int i = range.start; i < range.end; i++)
  {

   int s1 = i*widhStep;

   for(int iw=0; iw< inImg.size().width; iw=iw+2)
   {
    int s2 = iw*3;

    int mc = s1+s2;
    int B1 = (unsigned char)(inImg.data[mc + 0]);
    int G1 = (unsigned char)(inImg.data[mc + 1]);
    int R1 = (unsigned char)(inImg.data[mc + 2]);
    int B2 = (unsigned char)(inImg.data[mc + 3]);
    int G2 = (unsigned char)(inImg.data[mc + 4]);
    int R2 = (unsigned char)(inImg.data[mc + 5]);


    int Y = (0.257*R1) + (0.504*G1) + (0.098*B1) +16;
    int U = -(0.148*R1) - (0.291*G1) + (0.439*B1) + 128;
    int V = (0.439*R1 ) - (0.368*G1) - (0.071*B1) + 128;
    int Y2 = (0.257*R2) + (0.504*G2) + (0.098*B2) +16;

    Y = MMIN(255, MMAX(0, Y));
    U = MMIN(255, MMAX(0, U));
    V = MMIN(255, MMAX(0, V));
    Y2 = MMIN(255, MMAX(0, Y2)); 

    mc = i*m_stride + iw*2;
    outImg[mc + 0] = Y;
    outImg[mc + 1] = U;
    outImg[mc + 2] = Y2;
    outImg[mc + 3] = V;

   }
  }
 }
};



//in main rutine
cv::parallel_for_(cv::Range(0, (OriginMat).rows), Parallel_process((OriginMat), inP_OriginImg));

....


In opencv convert function,  YUYV to RGB option is exist (-> CV_YUV2BGR_YUYV).
But RGB to YUYV option is not exist.

thank you.

11/06/2012

YUV color format (444, 422, 411) - simple explanation

In the YUV color format, Y is bright information, U is blue color area, V is red color area.
Show the below picture. The picture is u-v color map

 
 
There are 3 type color format of YUV.
The types are 444, 422, 411.
 
 
444 is one pixel is 24 bits. 
 
 
 
 
422 is one pixel is 16 bits.
And U0, V0 is shared by Y0, Y1.



411 is one pixel is 12 bits.
 
 
 
 
This source code is convert code from YUV422 to RGB.
 

/ 


void ConvertYUV422toRGB(unsigned char** pSrc, unsigned char** pDst,int width,int height){
int i,j;
unsigned char* dst=*pDst;
unsigned char* src=*pSrc;
int Y1,Y2,U,V;
int R,G,B;

for(i=0;i2)
{
Y1=src[i*2+1];
Y2=src[i*2+3];
U=src[i*2];
V=src[i*2+2];

dst[i*3+2]=(unsigned char)((float)Y1+(1.4075f*(float)(V-128)));
dst[i*3+1]=(unsigned char)((float)Y1+(0.3455f*(float)(U-128)-(0.7169f*(float)(V-128))));
dst[i*3]=(unsigned char)((float)Y1+(1.7790f*(float)(U-128)));
dst[i*3+5]=(unsigned char)((float)Y2+(1.4075f*(float)(V-128)));
dst[i*3+4]=(unsigned char)((float)Y2+(0.3455f*(float)(U-128)-(0.7169f*(float)(V-128))));
dst[i*3+3]=(unsigned char)((float)Y2+(1.7790f*(float)(U-128)));
}
}

 


And YUV is converted by below fomulation.

R = Y + 1.4075(V-128)
G = Y - 0.3455(U-128) - 0.7169(V-128)
B = Y + 1.7790(U-128)
 
 
 
Thanks you.
 


sorry last source code is broken.
becasue html tag..
So I upload new version convert source code.
note!!! check Y position, the position is different as machine environment..
In the source code, stride means real width size.
YUV422 to RGB
--
//yuv to rgb
 int Y,U,V;   
 int R1,G1,B1;
 for(int ih=0; ihm_height; ++ih)
 {   
  //int iww=0;
  for(int iw=0; iwm_width; iw++)
  {
  
   if(iw %2 == 0)
   {
    Y = obj->m_yuv[ih*obj->m_stride + iw*2 + 0];
    U = obj->m_yuv[ih*obj->m_stride + iw*2 + 1];
    V = obj->m_yuv[ih*obj->m_stride + iw*2 + 3];
   }else{
    Y = obj->m_yuv[ih*obj->m_stride + iw*2 + 0];
    U = obj->m_yuv[ih*obj->m_stride + iw*2 -1];
    V = obj->m_yuv[ih*obj->m_stride + iw*2 + 1];
   }
   
   R1 = Y + 1.4075*(V-128);
   G1 = Y - 0.3455*(U-128) - 0.7169*(V-128);
   B1 = Y + 1.7790*(U-128);

   o_Image2.at(ih, iw)[0] = BYTE(MMIN(255, MMAX(0, B1)));// B1;
   o_Image2.at(ih, iw)[1] = BYTE(MMIN(255, MMAX(0, G1)));// G1;
   o_Image2.at(ih, iw)[2] = BYTE(MMIN(255, MMAX(0, R1)));// R1;
  }
 }
--
RGB to YUV422
--
int Y,U,V;   
   int R1,G1,B1;
   for(int ih=0; ih< obj->m_height; ++ih)
   {   
    //int iww=0;
    for(int iw=0; iw< obj->m_width; iw++)
    {

     B1 = o_Image2.at< cv::Vec3b>(ih, iw)[0];// B1;
     G1 = o_Image2.at< cv::Vec3b>(ih, iw)[1];// G1;
     R1 = o_Image2.at< cv::Vec3b>(ih, iw)[2];// R1;

     Y = (0.257*R1) + (0.504*G1) + (0.098*B1) +16;
     U = -(0.148*R1) - (0.291*G1) + (0.439*B1) + 128;
     V = (0.439*R1 ) - (0.368*G1) - (0.071*B1) + 128;
     Y = MMIN(255, MMAX(0, Y));
     U = MMIN(255, MMAX(0, U));
     V = MMIN(255, MMAX(0, V));

     if(iw %2 == 0)
     {
      obj->m_yuv[ih*obj->m_stride + iw*2 + 0] = Y;
      obj->m_yuv[ih*obj->m_stride + iw*2 + 1] = U;
      obj->m_yuv[ih*obj->m_stride + iw*2 + 3] = V;
     }else{
      obj->m_yuv[ih*obj->m_stride + iw*2 + 0] = Y;
      obj->m_yuv[ih*obj->m_stride + iw*2 -1] = U;
      obj->m_yuv[ih*obj->m_stride + iw*2 + 1] = V;
     }     
    }
--