mirror of
https://github.com/opencv/opencv.git
synced 2024-11-24 03:00:14 +08:00
Use cvtColor() for Bayer image color demosaicing and for V4L2_PIX_FMT_SRGGB8, V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SGBRG8, V4L2_PIX_FMT_SGRBG8 options. Update modules/videoio/test/test_v4l2.cpp test file.
This commit is contained in:
parent
f87e1efd2a
commit
d81cd13bb3
@ -1321,262 +1321,6 @@ yuv411p_to_rgb24(int width, int height,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BAYER2RGB24 ROUTINE TAKEN FROM:
|
||||
*
|
||||
* Sonix SN9C10x based webcam basic I/F routines
|
||||
* Takafumi Mizuno <taka-qce@ls-a.jp>
|
||||
*
|
||||
*/
|
||||
static void bayer2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, unsigned char *dst)
|
||||
{
|
||||
long int i;
|
||||
unsigned char *rawpt, *scanpt;
|
||||
long int size;
|
||||
|
||||
rawpt = src;
|
||||
scanpt = dst;
|
||||
size = WIDTH*HEIGHT;
|
||||
|
||||
for ( i = 0; i < size; i++ ) {
|
||||
if ( (i/WIDTH) % 2 == 0 ) {
|
||||
if ( (i % 2) == 0 ) {
|
||||
/* B */
|
||||
if ( (i > WIDTH) && ((i % WIDTH) > 0) ) {
|
||||
*scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
|
||||
*(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */
|
||||
*scanpt++ = (*(rawpt-1)+*(rawpt+1)+
|
||||
*(rawpt+WIDTH)+*(rawpt-WIDTH))/4; /* G */
|
||||
*scanpt++ = *rawpt; /* B */
|
||||
} else {
|
||||
/* first line or left column */
|
||||
*scanpt++ = *(rawpt+WIDTH+1); /* R */
|
||||
*scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; /* G */
|
||||
*scanpt++ = *rawpt; /* B */
|
||||
}
|
||||
} else {
|
||||
/* (B)G */
|
||||
if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) {
|
||||
*scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* R */
|
||||
*scanpt++ = *rawpt; /* G */
|
||||
*scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
|
||||
} else {
|
||||
/* first line or right column */
|
||||
*scanpt++ = *(rawpt+WIDTH); /* R */
|
||||
*scanpt++ = *rawpt; /* G */
|
||||
*scanpt++ = *(rawpt-1); /* B */
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( (i % 2) == 0 ) {
|
||||
/* G(R) */
|
||||
if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) {
|
||||
*scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */
|
||||
*scanpt++ = *rawpt; /* G */
|
||||
*scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* B */
|
||||
} else {
|
||||
/* bottom line or left column */
|
||||
*scanpt++ = *(rawpt+1); /* R */
|
||||
*scanpt++ = *rawpt; /* G */
|
||||
*scanpt++ = *(rawpt-WIDTH); /* B */
|
||||
}
|
||||
} else {
|
||||
/* R */
|
||||
if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) {
|
||||
*scanpt++ = *rawpt; /* R */
|
||||
*scanpt++ = (*(rawpt-1)+*(rawpt+1)+
|
||||
*(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
|
||||
*scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
|
||||
*(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* B */
|
||||
} else {
|
||||
/* bottom line or right column */
|
||||
*scanpt++ = *rawpt; /* R */
|
||||
*scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */
|
||||
*scanpt++ = *(rawpt-WIDTH-1); /* B */
|
||||
}
|
||||
}
|
||||
}
|
||||
rawpt++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// SGBRG to RGB24
|
||||
// for some reason, red and blue needs to be swapped
|
||||
// at least for 046d:092f Logitech, Inc. QuickCam Express Plus to work
|
||||
//see: http://www.siliconimaging.com/RGB%20Bayer.htm
|
||||
//and 4.6 at http://tldp.org/HOWTO/html_single/libdc1394-HOWTO/
|
||||
static void sgbrg2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, unsigned char *dst)
|
||||
{
|
||||
long int i;
|
||||
unsigned char *rawpt, *scanpt;
|
||||
long int size;
|
||||
|
||||
rawpt = src;
|
||||
scanpt = dst;
|
||||
size = WIDTH*HEIGHT;
|
||||
|
||||
for ( i = 0; i < size; i++ )
|
||||
{
|
||||
if ( (i/WIDTH) % 2 == 0 ) //even row
|
||||
{
|
||||
if ( (i % 2) == 0 ) //even pixel
|
||||
{
|
||||
if ( (i > WIDTH) && ((i % WIDTH) > 0) )
|
||||
{
|
||||
*scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */
|
||||
*scanpt++ = *(rawpt); /* G */
|
||||
*scanpt++ = (*(rawpt-WIDTH) + *(rawpt+WIDTH))/2; /* B */
|
||||
} else
|
||||
{
|
||||
/* first line or left column */
|
||||
|
||||
*scanpt++ = *(rawpt+1); /* R */
|
||||
*scanpt++ = *(rawpt); /* G */
|
||||
*scanpt++ = *(rawpt+WIDTH); /* B */
|
||||
}
|
||||
} else //odd pixel
|
||||
{
|
||||
if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) )
|
||||
{
|
||||
*scanpt++ = *(rawpt); /* R */
|
||||
*scanpt++ = (*(rawpt-1)+*(rawpt+1)+*(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
|
||||
*scanpt++ = (*(rawpt-WIDTH-1) + *(rawpt-WIDTH+1) + *(rawpt+WIDTH-1) + *(rawpt+WIDTH+1))/4; /* B */
|
||||
} else
|
||||
{
|
||||
/* first line or right column */
|
||||
|
||||
*scanpt++ = *(rawpt); /* R */
|
||||
*scanpt++ = (*(rawpt-1)+*(rawpt+WIDTH))/2; /* G */
|
||||
*scanpt++ = *(rawpt+WIDTH-1); /* B */
|
||||
}
|
||||
}
|
||||
} else
|
||||
{ //odd row
|
||||
if ( (i % 2) == 0 ) //even pixel
|
||||
{
|
||||
if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) )
|
||||
{
|
||||
*scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+*(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */
|
||||
*scanpt++ = (*(rawpt-1)+*(rawpt+1)+*(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
|
||||
*scanpt++ = *(rawpt); /* B */
|
||||
} else
|
||||
{
|
||||
/* bottom line or left column */
|
||||
|
||||
*scanpt++ = *(rawpt-WIDTH+1); /* R */
|
||||
*scanpt++ = (*(rawpt+1)+*(rawpt-WIDTH))/2; /* G */
|
||||
*scanpt++ = *(rawpt); /* B */
|
||||
}
|
||||
} else
|
||||
{ //odd pixel
|
||||
if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) )
|
||||
{
|
||||
*scanpt++ = (*(rawpt-WIDTH)+*(rawpt+WIDTH))/2; /* R */
|
||||
*scanpt++ = *(rawpt); /* G */
|
||||
*scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
|
||||
} else
|
||||
{
|
||||
/* bottom line or right column */
|
||||
|
||||
*scanpt++ = (*(rawpt-WIDTH)); /* R */
|
||||
*scanpt++ = *(rawpt); /* G */
|
||||
*scanpt++ = (*(rawpt-1)); /* B */
|
||||
}
|
||||
}
|
||||
}
|
||||
rawpt++;
|
||||
}
|
||||
}
|
||||
|
||||
// SGRBG to RGB24
|
||||
static void sgrbg2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, unsigned char *dst)
|
||||
{
|
||||
long int i;
|
||||
unsigned char *rawpt, *scanpt;
|
||||
long int size;
|
||||
|
||||
rawpt = src;
|
||||
scanpt = dst;
|
||||
size = WIDTH*HEIGHT;
|
||||
|
||||
for ( i = 0; i < size; i++ )
|
||||
{
|
||||
if ( (i/WIDTH) % 2 == 0 ) //even row
|
||||
{
|
||||
if ( (i % 2) == 0 ) //even pixel
|
||||
{
|
||||
if ( (i > WIDTH) && ((i % WIDTH) > 0) )
|
||||
{
|
||||
*scanpt++ = (*(rawpt-WIDTH) + *(rawpt+WIDTH))/2; /* R */
|
||||
*scanpt++ = *(rawpt); /* G */
|
||||
*scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
|
||||
} else
|
||||
{
|
||||
/* first line or left column */
|
||||
|
||||
*scanpt++ = *(rawpt+WIDTH); /* R */
|
||||
*scanpt++ = *(rawpt); /* G */
|
||||
*scanpt++ = *(rawpt+1); /* B */
|
||||
}
|
||||
} else //odd pixel
|
||||
{
|
||||
if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) )
|
||||
{
|
||||
*scanpt++ = (*(rawpt-WIDTH-1) + *(rawpt-WIDTH+1) +
|
||||
*(rawpt+WIDTH-1) + *(rawpt+WIDTH+1)) / 4; /* R */
|
||||
*scanpt++ = (*(rawpt-1) + *(rawpt+1) +
|
||||
*(rawpt-WIDTH) + *(rawpt+WIDTH)) / 4; /* G */
|
||||
*scanpt++ = *(rawpt); /* B */
|
||||
} else
|
||||
{
|
||||
/* first line or right column */
|
||||
|
||||
*scanpt++ = *(rawpt+WIDTH-1); /* R */
|
||||
*scanpt++ = (*(rawpt-1)+*(rawpt+WIDTH))/2; /* G */
|
||||
*scanpt++ = *(rawpt); /* B */
|
||||
}
|
||||
}
|
||||
} else
|
||||
{ //odd row
|
||||
if ( (i % 2) == 0 ) //even pixel
|
||||
{
|
||||
if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) )
|
||||
{
|
||||
*scanpt++ = *(rawpt); /* R */
|
||||
*scanpt++ = (*(rawpt-1) + *(rawpt+1)+
|
||||
*(rawpt-WIDTH) + *(rawpt+WIDTH)) / 4; /* G */
|
||||
*scanpt++ = (*(rawpt-WIDTH-1) + *(rawpt-WIDTH+1) +
|
||||
*(rawpt+WIDTH-1) + *(rawpt+WIDTH+1)) / 4; /* B */
|
||||
} else
|
||||
{
|
||||
/* bottom line or left column */
|
||||
|
||||
*scanpt++ = *(rawpt); /* R */
|
||||
*scanpt++ = (*(rawpt+1)+*(rawpt-WIDTH))/2; /* G */
|
||||
*scanpt++ = *(rawpt-WIDTH+1); /* B */
|
||||
}
|
||||
} else
|
||||
{ //odd pixel
|
||||
if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) )
|
||||
{
|
||||
*scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */
|
||||
*scanpt++ = *(rawpt); /* G */
|
||||
*scanpt++ = (*(rawpt-WIDTH)+*(rawpt+WIDTH))/2; /* B */
|
||||
} else
|
||||
{
|
||||
/* bottom line or right column */
|
||||
|
||||
*scanpt++ = (*(rawpt-1)); /* R */
|
||||
*scanpt++ = *(rawpt); /* G */
|
||||
*scanpt++ = (*(rawpt-WIDTH)); /* B */
|
||||
}
|
||||
}
|
||||
}
|
||||
rawpt++;
|
||||
}
|
||||
}
|
||||
|
||||
#define CLAMP(x) ((x)<0?0:((x)>255)?255:(x))
|
||||
|
||||
typedef struct {
|
||||
@ -1778,28 +1522,6 @@ void CvCaptureCAM_V4L::convertToRgb(const Buffer ¤tBuffer)
|
||||
yuv411p_to_rgb24(imageSize.width, imageSize.height,
|
||||
start, (unsigned char*)frame.imageData);
|
||||
return;
|
||||
case V4L2_PIX_FMT_SBGGR8:
|
||||
bayer2rgb24(imageSize.width, imageSize.height,
|
||||
start, (unsigned char*)frame.imageData);
|
||||
return;
|
||||
|
||||
case V4L2_PIX_FMT_SN9C10X:
|
||||
sonix_decompress_init();
|
||||
sonix_decompress(imageSize.width, imageSize.height,
|
||||
start, (unsigned char*)buffers[MAX_V4L_BUFFERS].memories[MEMORY_RGB].start);
|
||||
|
||||
bayer2rgb24(imageSize.width, imageSize.height,
|
||||
(unsigned char*)buffers[MAX_V4L_BUFFERS].memories[MEMORY_RGB].start,
|
||||
(unsigned char*)frame.imageData);
|
||||
return;
|
||||
case V4L2_PIX_FMT_SGBRG8:
|
||||
sgbrg2rgb24(imageSize.width, imageSize.height,
|
||||
start, (unsigned char*)frame.imageData);
|
||||
return;
|
||||
case V4L2_PIX_FMT_SGRBG8:
|
||||
sgrbg2rgb24(imageSize.width, imageSize.height,
|
||||
start, (unsigned char*)frame.imageData);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1872,6 +1594,36 @@ void CvCaptureCAM_V4L::convertToRgb(const Buffer ¤tBuffer)
|
||||
cv::cvtColor(temp, destination, COLOR_GRAY2BGR);
|
||||
return;
|
||||
}
|
||||
case V4L2_PIX_FMT_SN9C10X:
|
||||
{
|
||||
sonix_decompress_init();
|
||||
sonix_decompress(imageSize.width, imageSize.height,
|
||||
start, (unsigned char*)buffers[MAX_V4L_BUFFERS].memories[MEMORY_RGB].start);
|
||||
|
||||
cv::Mat cv_buf(imageSize, CV_8UC1, buffers[MAX_V4L_BUFFERS].memories[MEMORY_RGB].start);
|
||||
cv::cvtColor(cv_buf, destination, COLOR_BayerRG2BGR);
|
||||
return;
|
||||
}
|
||||
case V4L2_PIX_FMT_SRGGB8:
|
||||
{
|
||||
cv::cvtColor(cv::Mat(imageSize, CV_8UC1, start), destination, COLOR_BayerBG2BGR);
|
||||
return;
|
||||
}
|
||||
case V4L2_PIX_FMT_SBGGR8:
|
||||
{
|
||||
cv::cvtColor(cv::Mat(imageSize, CV_8UC1, start), destination, COLOR_BayerRG2BGR);
|
||||
return;
|
||||
}
|
||||
case V4L2_PIX_FMT_SGBRG8:
|
||||
{
|
||||
cv::cvtColor(cv::Mat(imageSize, CV_8UC1, start), destination, COLOR_BayerGR2BGR);
|
||||
return;
|
||||
}
|
||||
case V4L2_PIX_FMT_SGRBG8:
|
||||
{
|
||||
cv::cvtColor(cv::Mat(imageSize, CV_8UC1, start), destination, COLOR_BayerGB2BGR);
|
||||
return;
|
||||
}
|
||||
case V4L2_PIX_FMT_GREY:
|
||||
cv::cvtColor(cv::Mat(imageSize, CV_8UC1, start), destination, COLOR_GRAY2BGR);
|
||||
break;
|
||||
|
@ -70,6 +70,7 @@ TEST_P(videoio_v4l2, formats)
|
||||
const string device = devs[0];
|
||||
const Size sz(640, 480);
|
||||
const Format_Channels_Depth params = GetParam();
|
||||
const Size esz(sz.width * params.mul_width, sz.height * params.mul_height);
|
||||
|
||||
{
|
||||
// Case with RAW output
|
||||
@ -83,7 +84,17 @@ TEST_P(videoio_v4l2, formats)
|
||||
Mat img;
|
||||
EXPECT_TRUE(cap.grab());
|
||||
EXPECT_TRUE(cap.retrieve(img));
|
||||
EXPECT_EQ(Size(sz.width * params.mul_width, sz.height * params.mul_height), img.size());
|
||||
if (params.pixel_format == V4L2_PIX_FMT_SRGGB8 ||
|
||||
params.pixel_format == V4L2_PIX_FMT_SBGGR8 ||
|
||||
params.pixel_format == V4L2_PIX_FMT_SGBRG8 ||
|
||||
params.pixel_format == V4L2_PIX_FMT_SGRBG8)
|
||||
{
|
||||
EXPECT_EQ((size_t)esz.area(), img.total());
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_EQ(esz, img.size());
|
||||
}
|
||||
EXPECT_EQ(params.channels, img.channels());
|
||||
EXPECT_EQ(params.depth, img.depth());
|
||||
}
|
||||
@ -116,9 +127,11 @@ vector<Format_Channels_Depth> all_params = {
|
||||
// { V4L2_PIX_FMT_JPEG, 1, CV_8U, 1.f, 1.f },
|
||||
{ V4L2_PIX_FMT_YUYV, 2, CV_8U, 1.f, 1.f },
|
||||
{ V4L2_PIX_FMT_UYVY, 2, CV_8U, 1.f, 1.f },
|
||||
// { V4L2_PIX_FMT_SBGGR8, 1, CV_8U, 1.f, 1.f },
|
||||
// { V4L2_PIX_FMT_SN9C10X, 3, CV_8U, 1.f, 1.f },
|
||||
// { V4L2_PIX_FMT_SGBRG8, 1, CV_8U, 1.f, 1.f },
|
||||
{ V4L2_PIX_FMT_SN9C10X, 3, CV_8U, 1.f, 1.f },
|
||||
{ V4L2_PIX_FMT_SRGGB8, 1, CV_8U, 1.f, 1.f },
|
||||
{ V4L2_PIX_FMT_SBGGR8, 1, CV_8U, 1.f, 1.f },
|
||||
{ V4L2_PIX_FMT_SGBRG8, 1, CV_8U, 1.f, 1.f },
|
||||
{ V4L2_PIX_FMT_SGRBG8, 1, CV_8U, 1.f, 1.f },
|
||||
{ V4L2_PIX_FMT_RGB24, 3, CV_8U, 1.f, 1.f },
|
||||
{ V4L2_PIX_FMT_Y16, 1, CV_16U, 1.f, 1.f },
|
||||
{ V4L2_PIX_FMT_Y16_BE, 1, CV_16U, 1.f, 1.f },
|
||||
|
Loading…
Reference in New Issue
Block a user