I am finding a memory leak in this simple OpenCV code:
VideoCapture* capture = new VideoCapture(0);
Mat frame;
while (true) {
capture->set( CV_CAP_PROP_FRAME_WIDTH, 1600 );
capture->set(CV_CAP_PROP_FRAME_HEIGHT, 1200 );
capture->read(frame);
}
This is the whole code. Every time through the while loop, several MB are leaked. I have tried frame.release() just after the read, but it doesn't help. Removing the set-size lines fixes the problem, but in my real code I want to vary the size, so that isn't a solution. It is getting the image at the correct size.
Am I doing something stupid?
By the way, I am using a Logitech B910 webcam.
Thanks!
Do you need to change the readout size on every frame?
Once it is set the camera will produce the same size until you reset it
Related
I have a problem with OpenCV.
I need to read from memory, rotate, resize and save some images.
It happens in a thread in 32-bit app (sadly, there is limitation, due to 3rd party library, that doesn't support 64-bit).
My code looks like this:
void processImage(std::vector<char> data)
{
cv::Mat image = cv::imdecode(data, cv::IMREAD_UNCHANGED);
cv::rotate(image, image, image_rotation_);
cv::imwrite(path_.toStdString(), image);
QString preview_path = path_.replace(path_.section("/",-1),"Previews/"+path_.section("/",-1));
cv::resize(image, image, cv::Size(preview_size_.width(), preview_size_.height()));
cv::imwrite(preview_path.toStdString(), image);
image.release();
}
But it crashes on 1st to 3rd pass of imread with message
OpenCV: terminate handler is called! The last OpenCV error is:
OpenCV(3.4.7) Error: Insufficient memory (Failed to allocate 150962688 bytes) in OutOfMemoryError, file C:\opencv-3.4.7\modules\core\src\alloc.cpp, line 72
My app uses around 500Mb of memory and there is about 40% of physical memory free.
Is there any way to resolve such problem or maybe I'm doing something wrong?
My computer totally crashes if I am trying to store all video frames in a vector. I know it is memory problem according to some other posts. Is there any other way I can store all video frames in just one container. I am trying this:
storage = cvCreateMemStorage(0);
CvSeq* seq = cvCreateSeq(0, sizeof(CvSeq), sizeof(Mat), storage);
but I could not get seq elements from seq. Did anyone tried this before?
Update:
The crash is due to memory full. It is important to allocate appropriate memory before I allocate video frames into the array and replace the old matrix with new one when the buffer is full.
To store these, you need to have enough memory available in ram, which is not possible. You will need to have think of something else. What you’re saying isn’t possible.
I'm currently on a project where I have several picture taken with a camera.
My goal here is to make a video out of those pictures.
The problem is that pictures are not continuous ( there are some pictures missing in between).
And so when I'm trying to use Videowriter functions to create (obviously) a video the result is really messy and very speedy.
So I had an idea about creating an equivalent of a video reader but by reading a vector instead of a video: the display speed would depending on a cooldown between every pictures of my vector.
I would like to know your opinion about my solution and what would be your solution?
Thanking you.
Reduce the FPS in the VideoWriter object,
VideoWriter video(videoname, CV_FOURCC('M','J','P','G'), FPS, Size, true);
Try with FPS = 5 or even lesser, this might work
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.
I want to record video from webcam using opencv.
I put the following code inside a timer event handler function, which is called each 50 ms
IplImage *image = cvQueryFrame(camera);
IplImage *resizeImage = cvCreateImage( size, 8, 3);
cvResize(image, resizeImage);
cvWriteFrame(writer, resizeImage );
With writer is created using cvCreateVideoWriter, and the video is created when I call cvReleaseVideoWriter(&writer)
The problem is I can not release memory allocated by cvWriteFrame until cvReleaseVideoWriter is called. That makes a big issue when I need record a long time video.
How can I handle this situation?
I suppose that the best solution in your case (if you don't want to modify OpenCV code), is to write several video files.
As I can suppose, each frame is grabbed to RAM as is without any compressing. So, you can calculate a number of frames before amount of allocated memory exceed a particular size. Then you finish writing to file and start a new one.