OpenCV to FlyCapture2 Image - c++

I have an bumblebee2 and I'm using the flycapture SDK to capture the incoming images. I then convert the left flycapture2 image to an openCV format so I can do some basic manipulations to it. Then I'd like to feed it back into the Flycapture SDK but I cant seem to figure out how. To convert from Flycapture to OpenCV I do the following:
FlyCapture2::Image cf2Img;
grabbedImage.Convert(FlyCapture2::PIXEL_FORMAT_BGR, &cf2Img );
unsigned int rowBytes = (double)cf2Img.GetReceivedDataSize()/(double)cf2Img.GetRows();
cv::Mat cvImage = cv::Mat( cf2Img.GetRows(), cf2Img.GetCols(), CV_8UC3, cf2Img.GetData(), rowBytes );
I then do my manipulations (thresholding/contour detections/background removal etc), I'd then like to feed this image back into Flycapture. My attempts at converting it back haven't worked.
Does anyone have any code they have used before to take an OpenCV format back to Flycapture?

I work for Point Grey and I'll try to help here. Please note though you can contact us directly via our support site at ptgrey.com/support/ and we can help you out as well.
Looking at the code you attached and looking at the openCV source, when you make the cvImage, you are just reassigning the pointer to the data, you are not making an actual copy of the data.
So as long as the size of the data stays the same (ie. you keep it at 24 bits per pixel), any changes you make to the openCV image should be reflected in the flycapture (cf2Img) data and be able to save properly.
If you can explain the problems you are having trying to move back to a flycapture image, or send us the source code of how you are doing that, we can help you further.
To summarize, I expect any manipulations you do to the cvImage after the code you have provided should just be reflected in cf2Img without the need to convert back, assuming you are not changing the bit depth of the image.
I hope that helps, but please let me know if I can help clarify anything or if you can provide an example of the failure to convert back to fc2.
Thank you,
Point Grey Support

Related

OpenCV Mat corruption

I have been working on a simple video-over-ip program, partly for use in a project and partly to teach myself some basics of networking using high-level interfaces. The trouble is that I can send the data from a cv::Mat over the network just fine, but once I attempt to decode the data, it appears to be missing much of the color data. The code is in this gist, which contains all the files necessary to build and run the project under Linux. Can anyone shine some light on this?
If you need any more information, let me know. You'll need a webcam to test, I'm afraid.
When you copy your data with memcpy(m.data(), frame.data, frame.rows * frame.cols);, you're only copying a third of the total data since your image is a 3-channel one.
Try to change it to memcpy(m.data(), frame.data, 3 * frame.rows * frame.cols); (and allocate enough space before).

Extracting RGB channels in OpenCV under C++

I'm using OpenCV to convert image data captured using an IDS uEye camera into a useful format, using the following code:
IplImage* tmpImg = cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,3);
tmpImg->imageData = pFrameBuffer[k];
frame = cv::cvarrToMat(tmpImg);
This works perfectly - I can then use imwrite(filename,frame); further downstream to write the processed images out as a sensible format. I would ideally like to be able to save the RGB channels as separate 'grayscale' image files, but I don't understand the OpenCV documentation regarding single-channel operations. Can anyone suggest a means of accomplishing this? Preferably it's not overly computationally expensive (looping over an image pixel-by pixel isn't an option - I'm working with 60-230fps video at up to 1280x1064, and all the processing has to be done at the point of capture).
Running the latest Debian Testing if that makes any difference (I don't think it should).
Once you have a cv::Mat object it's pretty simple:
std::vector<cv::Mat> grayPlanes;
cv::split(frame, grayPlanes);
cv::imwrite("blue.png", grayPlanes[0]);
cv::imwrite("green.png", grayPlanes[1]);
cv::imwrite("red.png", grayPlanes[2]);
The split function can directly write to a standard vector and you don't really have to think about memory management and other stuff.

Capture image frames from Kinect and save to Hard drive

My aim is to capture all the frames (RGB) from Kinect at 30 fps and save them to my hard drive. For doing this I took the following approach.
Get the frames from Kinect and store them in an array buffer. Since writing to disk (using imwrite()) takes a bit of time and I may miss some frames while doing so, so instead of directly saving them to the disk, I store them in an array. Now, I have another parallel thread that accesses this array and writes the individual frames to the disk as images.
Now I have used a static array of size 3000 and type Mat. This will suffice since I need to store frames for 1.5 minute videos (1.5 minutes = 2700 frames). I have declared the array as follows :
#define NUM_FRAMES 3000
Mat rgb[NUM_FRAMES];
I have already tested this limit by reading images and saving them to the array using the following code :
for(int i=0; i<NUM_FRAMES; i++)
{
Mat img = imread("image.jpg", CV_LOAD_IMAGE_COLOR);
rgb[i] = img;
imshow("Image", img);
cvWaitKey(10);
}
The above code executed flawlessly.
But one problem is that the code I am using for capturing image using Kinect, captures the image in an IplImage. Thus I need to convert the image to cv::Mat format before using it. I convert it using the following command:
IplImage* color = cvCreateImageHeader(cvSize(COLOR_WIDTH, COLOR_HEIGHT), IPL_DEPTH_8U, 4);
cvSetData(color, colorBuffer, colorLockedRect.Pitch); // colorBuffer and colorLockedRect.Pitch is something that Kinect uses. Not related to OpenCv
rgb[rgb_read++] = Mat(color, FLAG);
Now here lies my problem. Whenever I am setting #define FLAG true, it causes memory leaks and gives me OpenCv Error: Insufficient memory (failed to allocate 1228804 bytes) error.
But if I use #define FLAG false it works correctly, but the frames that I am getting is erroneous as shown below. They are three consecutive frames.
I was moving around my arm and the image got cut in between as can be seen from above.
Can someone please point out the reason for this weird behavior or any other alternate way of obtaining the desired result. I have been struggling with this since a few days now. Please ask for if any further clarifications are required.
I am using OpenCV 2.4.8, Kinect SDK for Windows version-1.8.0 and Microsoft Visual Studio 2010.
Also can someone please explan to me the role of the CopyData parameter in Mat::Mat. I have already gone through this link, but still it's not completely clear. Maybe that's why I could not solve the above error in the first place since it's working is not very clear.
Thanks in advance.
first, do not use IplImages, stick with cv::Mat, please.
the equivalent code for that would be:
Mat img_borrowed = Mat( height, width, CV_8U4C, colorBuffer, colorLockedRect.Pitch );
note, that this does not do any allocation on its own, it's still the kinect's pixels, so you will have to clone() it:
rgb[rgb_read++] = img_borrowed.clone();
this is the same as setting the flag in your code above to 'true'. (deep-copy the data)
[edit] maybe it's a good idea to skip the useless 4th channel (also less mem required), so , instead of the above you could do:
cvtColor( img_borrowed, rgb[rgb_read++], CV_BGRA2BGR); // will make a 'deep copy', too.
so, - here's the bummer: if you don't save a deep-copy in your array, you'll end up with garbled (and all the same!) images, probably even with undefined behaviour due to the locking/unlocking of the kinect buffer, if you do copy it (and you must), you will need a lot of memory.
unlikely, that you can keep 3000 *1024*786*4 = 9658368000 bytes in memory, you'll have to cut it down one way or another.

Detect object stored in Mat image opencv

I'm trying to detect an object using opencv and Visual Studio Ultimate using C++. I'm having problems concerning cv::Mat, I cannot find any example of object detection with that kind of variable but just with IplImage. I tried to use an IplImage code and convert it to Mat, but it didn't work. But i don not want to use IplImage, my first part of code is in Mat and I want to keep using it.
What I'm trying to actually do is to detect the BIGGEST rectangle in the image stored from the cam, after thresholding it.
I have already done the threshold part and it's ok, it works and i can se my object (in white) moving in a black background.
Could someone help me with the tracking part? I have seen on the net some blob filtering solutions but they were way too difficult for me! If you can come up with an easy one it would be better.
thank you!
cv::Mat is the new image class in opencv. I think the most algorithms still use IplImage. For this reason I have asked times ago the following:
openCV mixing IplImage with cv::Mat
For recognition of objects I would say watch the cvMatchTemplate function of opencv. There is also the mat version cv::matchTemplate. There are also other object recognition methods but they are a bit more difficult to implement ;)
I dont know if I maybe understood your other question right but I think you wannt to recognze rectangle in your image. Maybe watch this tutorial:
http://docs.opencv.org/trunk/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.html
I don t know any standard algorithm for rectangles maybe you will need to code it yourself
cv::Mat encapsulate the lower level IplImage and other formats. Regard detection, there is a sample that you could find useful: squares. I googled for it, and found also this other question, that's more recent and could be of interest to you.

cv::Mat detect PixelFormat

I'm trying to use pictureBox->Image (Windows Forms) to display a cv::Mat image (openCV). I want to do that without saving the Image as a file ('cause i want to reset the image every 100ms).
I just found that topic here: How to display a cv::Mat in a Windows Form application?
When i use this solution the image appears to be white only. I guess i took the wrong PixelFormat.
So how do figure out the PixelFormat i need? Haven't seen any Method in cv::Mat to get info about that. Or does this depend on the image Source i use to create this cv::Mat?
Thanks so far :)
Here i took a screen. Its not completely white. So i guess there is some color info. But maybe i'm wrong.
Screen
cv::Mat.depth() returns the pixel type, eg. CV_8U for 8bit unsigned etc.
and cv::Mat.channels() returns the number of channels, typically 3 for a colour image
For 'regular images' opencv generally uses 8bit BGR colour order which should map directly onto a Windows bitmap or most Windows libs.
SO you probably want system.drawing.imaging.pixelformat.Format24bppRgb, I don't know what order ( RGB or BGR) it uses but you can use the opencv cv::cvtColor() with CV_BGR2RGB to convert to RGB
Thanks for the help! The problem was something else.
I just did not allocate memory for the Image Object. So there was nothing to really display.
Using cv::Mat img; in the headerFile and img = new cv::Mat(120,160,0); in Constructor (ocvcamimg Class) got it to work. (ocvcamimg->captureCamMatImg() returns img).