I had an irritating problem doing a simple image conversion for my GaugeCam project where I am capturing images with a USB camera that I want to process with OpenCV on a Beaglebone Black embedded computer. I am using a Logitech C270 camera for my development work on the desktop, but we will be using a different, more industrial quality camera when we get ready to put the devices we are building in the field. At any rate, I usually can just do an Internet search and find some code I can cut and paste to do this simply types of conversions so I though I would just put this out there in case anyone wants to use it. If you have questions on how to use it with OpenCV, just ask. Feel free to just cut and paste as needed–use at your own risk, it works in my application.This is not a tutorial, just a convenience for whoever can use it. I know the format is not great–I will get around to adding something to the blog for code pasting if I ever do any more of it.
A couple of additional notes:
- I am converting this to BGR (for OpenCV) rather than the RGB specified in Wikipedia.
- I am using the boost::algorithm::clamp method to do the clamping (using namespace boost::algorithm). You can do clamping with something like this if you like: MIN( 255, MAX( 0, x ) )
- You might have to convert “u_char” to “unsigned char” depending on what other includes you use.
- I am assuming the stride of both the source and destination buffers are equal to the width.
- I am assuming the output buffer has been allocated.
- I am assuming the input buffer is a YUYV buffer that is two-thirds the size of the output buffer in the format specified in the Wikipedia link.
- The way I am using this is passing the cv::Mat data pointer into the method as the output buffer.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Conversion algorithm from: https://en.wikipedia.org/wiki/YUV
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int ConvertYUYV_2_BGR( const int nWidth, const int nHeight,
u_char *pPixSrc, u_char *pPixDst )
{
if ( NULL == pPixSrc || NULL == pPixDst )
{
cerr << “FAIL: Cannot convert YUYV to BGR from/to NULL pixel buffers” << endl;
return -1;
}
int nStrideSrc = nWidth * 2;
int nStrideDst = nWidth * 3;
u_char *pSrc = pPixSrc;
u_char *pDst = pPixDst;
int nRow, nCol, nColDst, c, d, e;
for ( nRow = 0; nRow < nHeight; ++nRow )
{
for ( nCol = 0, nColDst = 0; nCol < nStrideSrc; nCol +=4, nColDst += 6 )
{
d = ( int )pSrc[ nCol + 1 ] – 128; // d = u – 128;
e = ( int )pSrc[ nCol + 3 ] – 128; // e = v – 128;
// c = y’ – 16 (for first pixel)
c = 298 * ( ( int )pSrc[ nCol ] – 16 );
// B – Blue
pDst[ nColDst ] = ( u_char )clamp( ( c + 516 * d + 128 ) >> 8, 0, 255 );
// G -Green
pDst[ nColDst + 1 ] = ( u_char )clamp( ( c – 100 * d – 208 * e + 128 ) >> 8, 0, 255 );
// R – Red
pDst[ nColDst + 2 ] = ( u_char )clamp( ( c + 409 * e + 128 ) >> 8, 0, 255 );
// c = y’ – 16 (for second pixel)
c = 298 * ( ( int )pSrc[ nCol + 2 ] – 16 );
// B – Blue
pDst[ nColDst + 3 ] = ( u_char )clamp( ( c + 516 * d + 128 ) >> 8, 0, 255 );
// G -Green
pDst[ nColDst + 4 ] = ( u_char )clamp( ( c – 100 * d – 208 * e + 128 ) >> 8, 0, 255 );
// R – Red
pDst[ nColDst + 5 ] = ( u_char )clamp( ( c + 409 * e + 128 ) >> 8, 0, 255 );
}
pSrc += nStrideSrc;
pDst += nStrideDst;
}
return 0;
}