OpenCv - 从网络摄像头捕获帧时内存泄漏
OpenCv - Memory leak when capturing frames from webcam
我正在编写一个 C 应用程序,它使用 OpenCv 从网络摄像头捕获图像,然后将图像保存到文件中。它是 运行 在 Raspian OS Wheezy 上针对 OpenCv 2.3.1-11。
如果我只是像这样打开和关闭网络摄像头,不会有内存泄漏,所以我认为我不会遇到有关 "webcam opening tax":
的旧错误
CvCapture* capture;
while (1) {
// No increase in memory consumption at all
capture = cvCreateCameraCapture(0);
cvReleaseCapture(&capture);
}
然而,当我真正开始获取图像时,内存消耗激增,每次迭代都会消耗另外 2MB 的内存。我已经通过 free -s 2
在命令行确认,同时手动触发图像采集,并注意到最终,我的应用程序抱怨没有足够的内存来采集图像。
capture = cvCreateCameraCapture(0);
while (1) {
if (capture) {
frame = cvQueryFrame(capture);
}
if (frame) {
CvSize size = cvSize(100, 100);
tmp = cvCreateImage(size, IPL_DEPTH_8U, 3);
cvResize(frame, tmp, CV_INTER_CUBIC);
// Do some stuff with tmp
}
}
cvReleaseCapture(&capture);
网上查了各种帖子,都说不支持修改frame
中存储的数据。如果我在 frame
上使用 cvReleaseImage
,它没有任何效果。事实上,内存使用量仅在 cvQueryFrame
调用时就会激增。即使是下面的示例也会导致此问题弹出:
capture = cvCreateCameraCapture(0);
while (1) {
if (capture) {
frame = cvQueryFrame(capture);
}
}
cvReleaseCapture(&capture);
我该如何解决这个问题?
我真的必须使用 C++ API(目前对我来说不是一个真正的选择),还是有其他方法可以解决这个问题?这是一个 Gtk+-2.0 应用程序,我唯一包含的 headers 是:
/*******************************************************************************
* Preprocessor Directives
******************************************************************************/
#include "opencv/cxcore.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
那里似乎混合了 opencv
和 opencv2
,但我找不到只包含 opencv
headers 和 headers 的方法没有它们就可以使用相机。我担心这可能会导致某些仅 C++ 代码以未定义的方式初始化。解决内存泄漏的任何帮助,或者如果需要,在没有泄漏的情况下在 C++ 中创建等效代码将非常有帮助。
感谢您的帮助。
这个对我来说不漏:
#include <opencv2\opencv.hpp>
int main()
{
CvCapture* capture;
IplImage* frame;
capture = cvCreateCameraCapture(0);
while (1)
{
if (capture)
{
frame = cvQueryFrame(capture);
}
}
cvReleaseCapture(&capture);
}
这个明显漏水了:
int main()
{
CvCapture* capture;
IplImage* frame;
IplImage* tmp;
capture = cvCreateCameraCapture(0);
while (1) {
if (capture) {
frame = cvQueryFrame(capture);
}
if (frame) {
CvSize size = cvSize(100, 100);
tmp = cvCreateImage(size, IPL_DEPTH_8U, 3);
cvResize(frame, tmp, CV_INTER_CUBIC);
// Do some stuff with tmp
}
}
cvReleaseCapture(&capture);
}
虽然这个没有泄漏:
int main()
{
CvCapture* capture;
IplImage* frame;
IplImage* tmp;
capture = cvCreateCameraCapture(0);
while (1) {
if (capture) {
frame = cvQueryFrame(capture);
}
if (frame) {
CvSize size = cvSize(100, 100);
tmp = cvCreateImage(size, IPL_DEPTH_8U, 3);
cvResize(frame, tmp, CV_INTER_CUBIC);
// Do some stuff with tmp
// release tmp:
cvReleaseImage(&tmp);
}
}
cvReleaseCapture(&capture);
}
你能试试最后一个例子吗?如果它确实泄漏了,你可能真的有一些错误 headers 或链接库的问题。
我今天 [01/04/2015] 检查了一下,在当前的 wheezy/main 存储库中,opencv 的开发包(除了 gpu)链接到 openCV 2.4.1。这里测试步骤:
安装包:
sudo apt-get install cmake build-essential libopencv-core-dev libcv-dev libcvaux-dev libhighgui-dev libopencv-calib3d-dev libopencv-contrib-dev libopencv-core-dev libopencv-dev libopencv-features2d-dev libopencv-flann-dev libopencv-highgui-dev libopencv-imgproc-dev libopencv-legacy-dev libopencv-ml-dev libopencv-objdetect-dev libopencv-video-dev
验证 openCv 库安装版本:
sudo ldconfig -v | grep opencv
结果:
libopencv_imgproc.so.2.4 -> libopencv_imgproc.so.2.4.1
libopencv_highgui.so.2.4 -> libopencv_highgui.so.2.4.1
libopencv_legacy.so.2.4 -> libopencv_legacy.so.2.4.1
libopencv_objdetect.so.2.4 -> libopencv_objdetect.so.2.4.1
libopencv_calib3d.so.2.4 -> libopencv_calib3d.so.2.4.1
libopencv_videostab.so.2.4 -> libopencv_videostab.so.2.4.1
libopencv_ml.so.2.4 -> libopencv_ml.so.2.4.1
libopencv_core.so.2.4 -> libopencv_core.so.2.4.1
libopencv_ts.so.2.4 -> libopencv_ts.so.2.4.1
libopencv_stitching.so.2.4 -> libopencv_stitching.so.2.4.1
libopencv_photo.so.2.4 -> libopencv_photo.so.2.4.1
libopencv_flann.so.2.4 -> libopencv_flann.so.2.4.1
libopencv_features2d.so.2.4 -> libopencv_features2d.so.2.4.1
libopencv_video.so.2.4 -> libopencv_video.so.2.4.1
ibopencv_contrib.so.2.4 -> libopencv_contrib.so.2.4.1
测试程序
#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <errno.h>
#include "opencv/cxcore.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"
int main(int argc, char * const argv[])
{
struct rusage usage;
long max_resident_set_size = 0;
long frame_no = 0;
CvCapture* capture;
IplImage* frame;
capture = cvCreateCameraCapture(0);
if (!capture) {
// error getting webcam
return 1;
}
// test 100 frames to check memory usage
while (frame_no < 100) {
frame = cvQueryFrame(capture);
frame_no++;
errno = 0;
getrusage(RUSAGE_SELF, &usage);
if (errno == EFAULT)
printf("Error: EFAULT\n");
else if (errno == EINVAL)
printf("Error: EINVAL\n");
else if (max_resident_set_size != usage.ru_maxrss) {
printf("frame %ld maximum resident set size: %ld\n", frame_no, usage.ru_maxrss);
printf("frame %ld maximum resident set size diff : %ld\n", frame_no, (usage.ru_maxrss - max_resident_set_size));
max_resident_set_size = usage.ru_maxrss;
}
}
cvReleaseCapture(&capture);
return 0;
}
我在 OpenCV 2.4 中使用上述代码没有内存问题。
我建议你卸载openCV 2.3.1包,更新系统并安装最新的并使用openCV2表示法。
列出已安装的软件包:
sudo dpkg --get-selections | grep -v deinstall | grep cv
希望对您有所帮助。
经过大量测试后,事实证明 OpenCv 2.3.1-11 在使用 pthread
s 时有一些不稳定的行为。
如果我只是在 main()
的循环中使用以下内容,没有问题。
int main()
{
CvCapture* capture;
IplImage* frame;
IplImage* tmp;
capture = cvCreateCameraCapture(0);
while (1) {
if (capture) {
frame = cvQueryFrame(capture);
}
if (frame) {
CvSize size = cvSize(100, 100);
tmp = cvCreateImage(size, IPL_DEPTH_8U, 3);
cvResize(frame, tmp, CV_INTER_CUBIC);
// Do some stuff with tmp
// release tmp:
cvReleaseImage(&tmp);
}
}
cvReleaseCapture(&capture);
}
如果我在 pthread
中使用相同的循环,每次迭代将导致至少 2MB 的内存丢失。但是,如果在 pthread
中我只调用了 capture = cvCreateCameraCapture(0)
和 cvReleaseCapture(&capture)
一次,问题就不再存在了。
此外,如果我在 main 中调用 cvCreateCameraCapture(0)
并将其分配给可从线程访问的内容(即:全局变量,或将其存储在上下文变量中,当我将其指针传递给线程时我生成了线程),我在 pthread
到 cvQueryFrame()
.
的每次调用中都得到了内存泄漏行为
所以,简而言之,如果在多线程程序中使用 C API(已弃用,我知道),您可以通过多种方式搬起石头砸自己的脚。谢谢大家的意见。
我正在编写一个 C 应用程序,它使用 OpenCv 从网络摄像头捕获图像,然后将图像保存到文件中。它是 运行 在 Raspian OS Wheezy 上针对 OpenCv 2.3.1-11。
如果我只是像这样打开和关闭网络摄像头,不会有内存泄漏,所以我认为我不会遇到有关 "webcam opening tax":
的旧错误CvCapture* capture;
while (1) {
// No increase in memory consumption at all
capture = cvCreateCameraCapture(0);
cvReleaseCapture(&capture);
}
然而,当我真正开始获取图像时,内存消耗激增,每次迭代都会消耗另外 2MB 的内存。我已经通过 free -s 2
在命令行确认,同时手动触发图像采集,并注意到最终,我的应用程序抱怨没有足够的内存来采集图像。
capture = cvCreateCameraCapture(0);
while (1) {
if (capture) {
frame = cvQueryFrame(capture);
}
if (frame) {
CvSize size = cvSize(100, 100);
tmp = cvCreateImage(size, IPL_DEPTH_8U, 3);
cvResize(frame, tmp, CV_INTER_CUBIC);
// Do some stuff with tmp
}
}
cvReleaseCapture(&capture);
网上查了各种帖子,都说不支持修改frame
中存储的数据。如果我在 frame
上使用 cvReleaseImage
,它没有任何效果。事实上,内存使用量仅在 cvQueryFrame
调用时就会激增。即使是下面的示例也会导致此问题弹出:
capture = cvCreateCameraCapture(0);
while (1) {
if (capture) {
frame = cvQueryFrame(capture);
}
}
cvReleaseCapture(&capture);
我该如何解决这个问题?
我真的必须使用 C++ API(目前对我来说不是一个真正的选择),还是有其他方法可以解决这个问题?这是一个 Gtk+-2.0 应用程序,我唯一包含的 headers 是:
/*******************************************************************************
* Preprocessor Directives
******************************************************************************/
#include "opencv/cxcore.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
那里似乎混合了 opencv
和 opencv2
,但我找不到只包含 opencv
headers 和 headers 的方法没有它们就可以使用相机。我担心这可能会导致某些仅 C++ 代码以未定义的方式初始化。解决内存泄漏的任何帮助,或者如果需要,在没有泄漏的情况下在 C++ 中创建等效代码将非常有帮助。
感谢您的帮助。
这个对我来说不漏:
#include <opencv2\opencv.hpp>
int main()
{
CvCapture* capture;
IplImage* frame;
capture = cvCreateCameraCapture(0);
while (1)
{
if (capture)
{
frame = cvQueryFrame(capture);
}
}
cvReleaseCapture(&capture);
}
这个明显漏水了:
int main()
{
CvCapture* capture;
IplImage* frame;
IplImage* tmp;
capture = cvCreateCameraCapture(0);
while (1) {
if (capture) {
frame = cvQueryFrame(capture);
}
if (frame) {
CvSize size = cvSize(100, 100);
tmp = cvCreateImage(size, IPL_DEPTH_8U, 3);
cvResize(frame, tmp, CV_INTER_CUBIC);
// Do some stuff with tmp
}
}
cvReleaseCapture(&capture);
}
虽然这个没有泄漏:
int main()
{
CvCapture* capture;
IplImage* frame;
IplImage* tmp;
capture = cvCreateCameraCapture(0);
while (1) {
if (capture) {
frame = cvQueryFrame(capture);
}
if (frame) {
CvSize size = cvSize(100, 100);
tmp = cvCreateImage(size, IPL_DEPTH_8U, 3);
cvResize(frame, tmp, CV_INTER_CUBIC);
// Do some stuff with tmp
// release tmp:
cvReleaseImage(&tmp);
}
}
cvReleaseCapture(&capture);
}
你能试试最后一个例子吗?如果它确实泄漏了,你可能真的有一些错误 headers 或链接库的问题。
我今天 [01/04/2015] 检查了一下,在当前的 wheezy/main 存储库中,opencv 的开发包(除了 gpu)链接到 openCV 2.4.1。这里测试步骤:
安装包:
sudo apt-get install cmake build-essential libopencv-core-dev libcv-dev libcvaux-dev libhighgui-dev libopencv-calib3d-dev libopencv-contrib-dev libopencv-core-dev libopencv-dev libopencv-features2d-dev libopencv-flann-dev libopencv-highgui-dev libopencv-imgproc-dev libopencv-legacy-dev libopencv-ml-dev libopencv-objdetect-dev libopencv-video-dev
验证 openCv 库安装版本:
sudo ldconfig -v | grep opencv
结果:
libopencv_imgproc.so.2.4 -> libopencv_imgproc.so.2.4.1
libopencv_highgui.so.2.4 -> libopencv_highgui.so.2.4.1
libopencv_legacy.so.2.4 -> libopencv_legacy.so.2.4.1
libopencv_objdetect.so.2.4 -> libopencv_objdetect.so.2.4.1
libopencv_calib3d.so.2.4 -> libopencv_calib3d.so.2.4.1
libopencv_videostab.so.2.4 -> libopencv_videostab.so.2.4.1
libopencv_ml.so.2.4 -> libopencv_ml.so.2.4.1
libopencv_core.so.2.4 -> libopencv_core.so.2.4.1
libopencv_ts.so.2.4 -> libopencv_ts.so.2.4.1
libopencv_stitching.so.2.4 -> libopencv_stitching.so.2.4.1
libopencv_photo.so.2.4 -> libopencv_photo.so.2.4.1
libopencv_flann.so.2.4 -> libopencv_flann.so.2.4.1
libopencv_features2d.so.2.4 -> libopencv_features2d.so.2.4.1
libopencv_video.so.2.4 -> libopencv_video.so.2.4.1
ibopencv_contrib.so.2.4 -> libopencv_contrib.so.2.4.1
测试程序
#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <errno.h>
#include "opencv/cxcore.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"
int main(int argc, char * const argv[])
{
struct rusage usage;
long max_resident_set_size = 0;
long frame_no = 0;
CvCapture* capture;
IplImage* frame;
capture = cvCreateCameraCapture(0);
if (!capture) {
// error getting webcam
return 1;
}
// test 100 frames to check memory usage
while (frame_no < 100) {
frame = cvQueryFrame(capture);
frame_no++;
errno = 0;
getrusage(RUSAGE_SELF, &usage);
if (errno == EFAULT)
printf("Error: EFAULT\n");
else if (errno == EINVAL)
printf("Error: EINVAL\n");
else if (max_resident_set_size != usage.ru_maxrss) {
printf("frame %ld maximum resident set size: %ld\n", frame_no, usage.ru_maxrss);
printf("frame %ld maximum resident set size diff : %ld\n", frame_no, (usage.ru_maxrss - max_resident_set_size));
max_resident_set_size = usage.ru_maxrss;
}
}
cvReleaseCapture(&capture);
return 0;
}
我在 OpenCV 2.4 中使用上述代码没有内存问题。
我建议你卸载openCV 2.3.1包,更新系统并安装最新的并使用openCV2表示法。
列出已安装的软件包:
sudo dpkg --get-selections | grep -v deinstall | grep cv
希望对您有所帮助。
经过大量测试后,事实证明 OpenCv 2.3.1-11 在使用 pthread
s 时有一些不稳定的行为。
如果我只是在 main()
的循环中使用以下内容,没有问题。
int main()
{
CvCapture* capture;
IplImage* frame;
IplImage* tmp;
capture = cvCreateCameraCapture(0);
while (1) {
if (capture) {
frame = cvQueryFrame(capture);
}
if (frame) {
CvSize size = cvSize(100, 100);
tmp = cvCreateImage(size, IPL_DEPTH_8U, 3);
cvResize(frame, tmp, CV_INTER_CUBIC);
// Do some stuff with tmp
// release tmp:
cvReleaseImage(&tmp);
}
}
cvReleaseCapture(&capture);
}
如果我在 pthread
中使用相同的循环,每次迭代将导致至少 2MB 的内存丢失。但是,如果在 pthread
中我只调用了 capture = cvCreateCameraCapture(0)
和 cvReleaseCapture(&capture)
一次,问题就不再存在了。
此外,如果我在 main 中调用 cvCreateCameraCapture(0)
并将其分配给可从线程访问的内容(即:全局变量,或将其存储在上下文变量中,当我将其指针传递给线程时我生成了线程),我在 pthread
到 cvQueryFrame()
.
所以,简而言之,如果在多线程程序中使用 C API(已弃用,我知道),您可以通过多种方式搬起石头砸自己的脚。谢谢大家的意见。