dynamic
dynamic

Reputation: 48141

opencv VideoCapture.set greyscale?

I would avoid to convert each frame taken by video camera with cvtColor(frame, image, CV_RGB2GRAY);
Is there anyway to set VideoCapture to get directly in greyscale?

Example:

VideoCapture cap(0);

cap.set(CV_CAP_PROP_FRAME_WIDTH,420);
cap.set(CV_CAP_PROP_FRAME_HEIGHT,340);
cap.set(CV_CAP_GREYSCALE,1); //< ???

Upvotes: 8

Views: 22784

Answers (4)

user19069481
user19069481

Reputation:

If you use <raspicam/raspicam_cv.h>]1 you can do it. you need to open a device like this:

RaspiCam_Cv m_rapiCamera;

Set any parametters that you need using below code:

m_rapiCamera.set(CV_CAP_PROP_FORMAT, CV_8UC1);

And then open the stream like below:

m_rapiCamera.open();

And you will get only one channel.

Good luck!

Upvotes: 0

Ayberk &#214;zg&#252;r
Ayberk &#214;zg&#252;r

Reputation: 5300

This is not possible if you use v4l (the default cv capture method on desktop Linux). The CV_CAP_PROP_FORMAT exists but is simply ignored. You have to convert the images to grayscale manually. If your device supports it, you may want to reimplement cap_v4l.cpp in order to interface v4l to set the format to grayscale.

On Android this is possible with the following native code (for the 0th device):

#include<opencv2/highgui/highgui.hpp>
#include<opencv2/highgui/highgui_c.h>

cv::VideoCapture camera(0);
camera->open(0);
cv::Mat dest(480,640,CV_8UC1);
if(camera->grab())
    camera->retrieve(dest,CV_CAP_ANDROID_GREY_FRAME);

Here, passing CV_CAP_ANDROID_GREY_FRAME to the channel parameter of cv::VideoCapture::retrieve(cv::Mat,int) causes the YUV NV21 (a.k.a yuv420sp) image to be color converted to grayscale. This is just a mapping of the Y channel to the grayscale image, which does not involve any actual conversion or memcpy, therefore very fast. You can check this behavior in https://github.com/Itseez/opencv/blob/master/modules/videoio/src/cap_android.cpp#L407 and the "color conversion" in https://github.com/Itseez/opencv/blob/master/modules/videoio/src/cap_android.cpp#L511. I agree that this behavior is not documented at all and is very awkward, but it saved a lot of CPU time for me.

Upvotes: 4

Void
Void

Reputation: 442

If your camera supports YUV420 then you could just take the Y channel: http://en.wikipedia.org/wiki/YUV

How to do that is well explained here: Access to each separate channel in OpenCV

Warning: the Y channel might not be the first Mat you get with split() so you should do an imshow() of all of them separately and chose the one that looks like the "real" gray image. The others will just be waaaay out of contrast so it'll be obvious. For me it was the second mat.

Usually, any camera should be able to do YUV420 since sending frames directly in RGB is slower so YUV is pretty much used by nearly every camera. :)

Upvotes: 6

ArtemStorozhuk
ArtemStorozhuk

Reputation: 8725

This is impossible. Here's list of all codes:

CV_CAP_PROP_POS_MSEC - position in milliseconds from the file beginning
CV_CAP_PROP_POS_FRAMES - position in frames (only for video files)
CV_CAP_PROP_POS_AVI_RATIO - position in relative units (0 - start of the file, 1 - end of the file)
CV_CAP_PROP_FRAME_WIDTH - width of frames in the video stream (only for cameras)
CV_CAP_PROP_FRAME_HEIGHT - height of frames in the video stream (only for cameras)
CV_CAP_PROP_FPS - frame rate (only for cameras)
CV_CAP_PROP_FOURCC - 4-character code of codec (only for cameras).

Or (if it's possible, using some utilities) you can setup your camera to show only grayscale image.

To convert colored image to grayscale you have to call cvtColor with code CV_BGR2GRAY. This shouldn't take much time.

Upvotes: 5

Related Questions