From 620a969285b16e2d0a8fc79ecede950b25a902f5 Mon Sep 17 00:00:00 2001 From: Joe Howse Date: Tue, 16 Dec 2014 20:07:37 -0400 Subject: [PATCH 1/2] Allow BGR, RGB, or gray capture via libv4l --- modules/videoio/include/opencv2/videoio.hpp | 10 ++ .../include/opencv2/videoio/videoio_c.h | 11 ++ modules/videoio/src/cap_libv4l.cpp | 141 +++++++++++++++--- 3 files changed, 139 insertions(+), 23 deletions(-) diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp index 8610fe3e8..c85b4851f 100644 --- a/modules/videoio/include/opencv2/videoio.hpp +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -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 diff --git a/modules/videoio/include/opencv2/videoio/videoio_c.h b/modules/videoio/include/opencv2/videoio/videoio_c.h index d993ab312..723b83ae3 100644 --- a/modules/videoio/include/opencv2/videoio/videoio_c.h +++ b/modules/videoio/include/opencv2/videoio/videoio_c.h @@ -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 diff --git a/modules/videoio/src/cap_libv4l.cpp b/modules/videoio/src/cap_libv4l.cpp index d1f6ac7fb..bcfeaff9b 100644 --- a/modules/videoio/src/cap_libv4l.cpp +++ b/modules/videoio/src/cap_libv4l.cpp @@ -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)); From 13c04120ddd416f05fb345f67ba47554895d65eb Mon Sep 17 00:00:00 2001 From: Joe Howse Date: Tue, 16 Dec 2014 21:37:14 -0400 Subject: [PATCH 2/2] For Java compatibility, avoiding explicit pseudonym in enum --- modules/videoio/include/opencv2/videoio/videoio_c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/videoio/include/opencv2/videoio/videoio_c.h b/modules/videoio/include/opencv2/videoio/videoio_c.h index 723b83ae3..5130fa6f5 100644 --- a/modules/videoio/include/opencv2/videoio/videoio_c.h +++ b/modules/videoio/include/opencv2/videoio/videoio_c.h @@ -161,7 +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_MONOCHROME =19, CV_CAP_PROP_SHARPNESS =20, CV_CAP_PROP_AUTO_EXPOSURE =21, // exposure control done by camera, // user can adjust refernce level