Allow BGR, RGB, or gray capture via libv4l

This commit is contained in:
Joe Howse 2014-12-16 20:07:37 -04:00
parent fed1b3fd59
commit 620a969285
3 changed files with 139 additions and 23 deletions

View File

@ -110,6 +110,7 @@ enum { CAP_PROP_POS_MSEC =0,
CAP_PROP_WHITE_BALANCE_BLUE_U =17,
CAP_PROP_RECTIFICATION =18,
CAP_PROP_MONOCROME =19,
CAP_PROP_MONOCHROME =CAP_PROP_MONOCROME,
CAP_PROP_SHARPNESS =20,
CAP_PROP_AUTO_EXPOSURE =21, // DC1394: exposure control done by camera, user can adjust refernce level using this feature
CAP_PROP_GAMMA =22,
@ -130,6 +131,14 @@ enum { CAP_PROP_POS_MSEC =0,
};
// Generic camera output modes.
// Currently, these are supported through the libv4l interface only.
enum { CAP_MODE_BGR = 0, // BGR24 (default)
CAP_MODE_RGB = 1, // RGB24
CAP_MODE_GRAY = 2 // Y8
};
// DC1394 only
// modes of the controlling registers (can be: auto, manual, auto single push, absolute Latter allowed with any other mode)
// every feature can have only one mode turned on at a time
@ -268,6 +277,7 @@ enum { CAP_PROP_ANDROID_AUTOGRAB = 1024,
enum { CAP_ANDROID_COLOR_FRAME_BGR = 0, //BGR
CAP_ANDROID_COLOR_FRAME = CAP_ANDROID_COLOR_FRAME_BGR,
CAP_ANDROID_GREY_FRAME = 1, //Y
CAP_ANDROID_GRAY_FRAME = CAP_ANDROID_GREY_FRAME,
CAP_ANDROID_COLOR_FRAME_RGB = 2,
CAP_ANDROID_COLOR_FRAME_BGRA = 3,
CAP_ANDROID_COLOR_FRAME_RGBA = 4

View File

@ -161,6 +161,7 @@ enum
CV_CAP_PROP_WHITE_BALANCE_BLUE_U =17,
CV_CAP_PROP_RECTIFICATION =18,
CV_CAP_PROP_MONOCROME =19,
CV_CAP_PROP_MONOCHROME =CV_CAP_PROP_MONOCROME,
CV_CAP_PROP_SHARPNESS =20,
CV_CAP_PROP_AUTO_EXPOSURE =21, // exposure control done by camera,
// user can adjust refernce level
@ -292,6 +293,15 @@ enum
CV_CAP_INTELPERC_GENERATORS_MASK = CV_CAP_INTELPERC_DEPTH_GENERATOR + CV_CAP_INTELPERC_IMAGE_GENERATOR
};
// Generic camera output modes.
// Currently, these are supported through the libv4l interface only.
enum
{
CV_CAP_MODE_BGR = 0, // BGR24 (default)
CV_CAP_MODE_RGB = 1, // RGB24
CV_CAP_MODE_GRAY = 2 // Y8
};
enum
{
// Data given from depth generator.
@ -322,6 +332,7 @@ enum
CV_CAP_ANDROID_COLOR_FRAME_BGR = 0, //BGR
CV_CAP_ANDROID_COLOR_FRAME = CV_CAP_ANDROID_COLOR_FRAME_BGR,
CV_CAP_ANDROID_GREY_FRAME = 1, //Y
CV_CAP_ANDROID_GRAY_FRAME = CV_CAP_ANDROID_GREY_FRAME,
CV_CAP_ANDROID_COLOR_FRAME_RGB = 2,
CV_CAP_ANDROID_COLOR_FRAME_BGRA = 3,
CV_CAP_ANDROID_COLOR_FRAME_RGBA = 4

View File

@ -180,6 +180,16 @@ make & enjoy!
15th patch: May 12, 2010, Filipe Almeida filipe.almeida@ist.utl.pt
- Broken compile of library (include "_videoio.h")
16th patch: Dec 16, 2014, Joseph Howse josephhowse@nummist.com
- Allow getting/setting CV_CAP_PROP_MODE. These values are supported:
- CV_CAP_MODE_BGR : BGR24 (default)
- CV_CAP_MODE_RGB : RGB24
- CV_CAP_MODE_GRAY : Y8, extracted from YUV420
- Tested successfully on these cameras:
- PlayStation 3 Eye
- Logitech C920
- Odroid USB-CAM 720P
*/
/*M///////////////////////////////////////////////////////////////////////////////////////
@ -300,6 +310,7 @@ typedef struct CvCaptureCAM_V4L
int FirstCapture;
int width; int height;
int mode;
struct video_capability capability;
struct video_window captureWindow;
@ -630,6 +641,16 @@ static void v4l2_scan_controls(CvCaptureCAM_V4L* capture) {
}
}
static inline int channels_for_mode(int mode)
{
switch(mode) {
case CV_CAP_MODE_GRAY:
return 1;
default:
return 3;
}
}
static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName)
{
int detect_v4l2 = 0;
@ -689,20 +710,41 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName)
return -1;
}
/* libv4l will convert from any format to V4L2_PIX_FMT_BGR24 */
/* libv4l will convert from any format to V4L2_PIX_FMT_BGR24,
V4L2_PIX_FMT_RGV24, or V4L2_PIX_FMT_YUV420 */
unsigned int requestedPixelFormat;
int width;
int height;
switch (capture->mode) {
case CV_CAP_MODE_RGB:
requestedPixelFormat = V4L2_PIX_FMT_RGB24;
width = capture->width;
height = capture->height;
break;
case CV_CAP_MODE_GRAY:
requestedPixelFormat = V4L2_PIX_FMT_YUV420;
width = capture->width;
height = capture->height;
break;
default:
requestedPixelFormat = V4L2_PIX_FMT_BGR24;
width = capture->width;
height = capture->height;
break;
}
CLEAR (capture->form);
capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
capture->form.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
capture->form.fmt.pix.pixelformat = requestedPixelFormat;
capture->form.fmt.pix.field = V4L2_FIELD_ANY;
capture->form.fmt.pix.width = capture->width;
capture->form.fmt.pix.height = capture->height;
capture->form.fmt.pix.width = width;
capture->form.fmt.pix.height = height;
if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form)) {
fprintf(stderr, "VIDEOIO ERROR: libv4l unable to ioctl S_FMT\n");
return -1;
}
if (V4L2_PIX_FMT_BGR24 != capture->form.fmt.pix.pixelformat) {
if (requestedPixelFormat != capture->form.fmt.pix.pixelformat) {
fprintf( stderr, "VIDEOIO ERROR: libv4l unable convert to requested pixfmt\n");
return -1;
}
@ -813,7 +855,8 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName)
cvInitImageHeader( &capture->frame,
cvSize( capture->captureWindow.width,
capture->captureWindow.height ),
IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
IPL_DEPTH_8U, channels_for_mode(capture->mode),
IPL_ORIGIN_TL, 4 );
/* Allocate space for RGBA data */
capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
@ -899,21 +942,33 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName)
return -1;
}
capture->imageProperties.palette = VIDEO_PALETTE_RGB24;
capture->imageProperties.depth = 24;
int requestedVideoPalette;
int depth;
switch (capture->mode) {
case CV_CAP_MODE_GRAY:
requestedVideoPalette = VIDEO_PALETTE_YUV420;
depth = 8;
break;
default:
requestedVideoPalette = VIDEO_PALETTE_RGB24;
depth = 24;
break;
}
capture->imageProperties.depth = depth;
capture->imageProperties.palette = requestedVideoPalette;
if (v4l1_ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties) < 0) {
fprintf( stderr, "VIDEOIO ERROR: libv4l unable to ioctl VIDIOCSPICT\n\n");
icvCloseCAM_V4L(capture);
icvCloseCAM_V4L(capture);
return -1;
}
if (v4l1_ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) {
fprintf( stderr, "VIDEOIO ERROR: libv4l unable to ioctl VIDIOCGPICT\n\n");
icvCloseCAM_V4L(capture);
icvCloseCAM_V4L(capture);
return -1;
}
if (capture->imageProperties.palette != VIDEO_PALETTE_RGB24) {
if (capture->imageProperties.palette != requestedVideoPalette) {
fprintf( stderr, "VIDEOIO ERROR: libv4l unable convert to requested pixfmt\n\n");
icvCloseCAM_V4L(capture);
icvCloseCAM_V4L(capture);
return -1;
}
@ -950,7 +1005,8 @@ static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName)
cvInitImageHeader( &capture->frame,
cvSize( capture->captureWindow.width,
capture->captureWindow.height ),
IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
IPL_DEPTH_8U, channels_for_mode(capture->mode),
IPL_ORIGIN_TL, 4 );
/* Allocate space for RGBA data */
capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
@ -1224,9 +1280,10 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) {
|| ((unsigned long)capture->frame.height != capture->form.fmt.pix.height)) {
cvFree(&capture->frame.imageData);
cvInitImageHeader( &capture->frame,
cvSize( capture->form.fmt.pix.width,
capture->form.fmt.pix.height ),
IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
cvSize( capture->form.fmt.pix.width,
capture->form.fmt.pix.height ),
IPL_DEPTH_8U, channels_for_mode(capture->mode),
IPL_ORIGIN_TL, 4 );
capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
}
@ -1237,9 +1294,10 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) {
|| (capture->frame.height != capture->mmaps[capture->bufferIndex].height)) {
cvFree(&capture->frame.imageData);
cvInitImageHeader( &capture->frame,
cvSize( capture->captureWindow.width,
capture->captureWindow.height ),
IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
cvSize( capture->captureWindow.width,
capture->captureWindow.height ),
IPL_DEPTH_8U, channels_for_mode(capture->mode),
IPL_ORIGIN_TL, 4 );
capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
}
@ -1260,14 +1318,16 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) {
switch(capture->imageProperties.palette) {
case VIDEO_PALETTE_RGB24:
case VIDEO_PALETTE_YUV420:
memcpy((char *)capture->frame.imageData,
(char *)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
capture->frame.imageSize);
break;
default:
fprintf( stderr,
"VIDEOIO ERROR: V4L: Cannot convert from palette %d to RGB\n",
capture->imageProperties.palette);
"VIDEOIO ERROR: V4L: Cannot convert from palette %d to mode %d\n",
capture->imageProperties.palette,
capture->mode);
return 0;
}
@ -1300,6 +1360,9 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture,
}
}
return (property_id == CV_CAP_PROP_FRAME_WIDTH)?capture->form.fmt.pix.width:capture->form.fmt.pix.height;
case CV_CAP_PROP_MODE:
return capture->mode;
break;
case CV_CAP_PROP_BRIGHTNESS:
sprintf(name, "Brightness");
capture->control.id = V4L2_CID_BRIGHTNESS;
@ -1394,12 +1457,24 @@ static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) {
icvCloseCAM_V4L(capture);
_capture_V4L2(capture, deviceName);
int cropHeight;
int cropWidth;
switch (capture->mode) {
case CV_CAP_MODE_GRAY:
cropHeight = h*8;
cropWidth = w*8;
break;
default:
cropHeight = h*24;
cropWidth = w*24;
break;
}
CLEAR (capture->crop);
capture->crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
capture->crop.c.left = 0;
capture->crop.c.top = 0;
capture->crop.c.height = h*24;
capture->crop.c.width = w*24;
capture->crop.c.height = cropHeight;
capture->crop.c.width = cropWidth;
/* set the crop area, but don't exit if the device don't support croping */
xioctl (capture->deviceHandle, VIDIOC_S_CROP, &capture->crop);
@ -1636,6 +1711,26 @@ static int icvSetPropertyCAM_V4L(CvCaptureCAM_V4L* capture, int property_id, dou
width = height = 0;
}
break;
case CV_CAP_PROP_MODE:
int mode;
mode = cvRound(value);
if (capture->mode != mode) {
switch (mode) {
case CV_CAP_MODE_BGR:
case CV_CAP_MODE_RGB:
case CV_CAP_MODE_GRAY:
capture->mode = mode;
/* recreate the capture buffer for the same output resolution
but a different pixel format */
retval = icvSetVideoSize(capture, capture->width, capture->height);
break;
default:
fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: Unsupported mode: %d\n", mode);
retval=0;
break;
}
}
break;
case CV_CAP_PROP_FPS:
struct v4l2_streamparm setfps;
memset (&setfps, 0, sizeof(struct v4l2_streamparm));