1

我正在尝试迭代一些包含大约 3000 个图像的目录。我加载图像。如果图像已加载,我将其释放。那是我可以编写的最小的程序来重现错误。

加载和释放 124 张图像后,程序停止加载图像。我认为这是一个内存问题,但我不明白究竟是什么导致程序停止加载图像。

我在我的Mac上使用OpenCV。我不知道我怎么能弄清楚我正在使用哪个版本。

这是我项目中的代码。

bool FaceDetectionStrategy::detectFace(std::string imagePath) {

   IplImage *img = cvLoadImage(imagePath.c_str(), CV_LOAD_IMAGE_COLOR);
   if (img) {
      std::cout << "Image loaded " << imagePath << std::endl;
      cvReleaseImage(&img);
   } else {
      std::cout << "Image not loaded " << imagePath << std::endl;
   }
return true;

}

我正在迭代的目录中的每个图像都会调用此方法。在 124 张图像之后, if(img) 部分评估为 false 并执行 else 分支。如果我稍后尝试从程序的其他部分加载图像,它们也不会加载。

编辑它不是内存问题。Mac OS 标准最大打开文件数为 256 后将其更改为 512 我可以打开 251 个图像。所以看起来OpenCV在加载图像文件后并没有关闭它们。

4

2 回答 2

3

从 OpenCv 搜索 bugtracker 显示了这个问题的答案:cvLoadImage with Mac ImageIO leave file handles open

这似乎是 OpenCV mac 实现中的一个错误,解决它的唯一方法是安装更新版本的 OpenCV。

编辑从存储库主干安装 OpenCV 的最新版本解决了这个问题。有时它有助于检查您正在使用的框架的 BugTracker...

于 2009-07-25T17:51:05.730 回答
2

根据我的经验,有关记忆的行为很少与一致的数字有关。唯一可能保持一致的方法是,如果有某种内部限制cvLoadImage恰好是不常见的数字 124。但你的逻辑对我来说似乎很好,你的图像应该被释放。

更有可能的是,因为我假设您的目录在测试之间没有变化,所以第 125 个图像是坏的。

您是否验证了您尝试加载的图像确实存在?如果是(可能是这样),请检查OpenCV 是否支持图像文件格式。如果这也是正确的,请确保文件没有被其他编辑器打开而损坏。

您可以让 OpenCV帮助您解决错误。用于cvGetErrStatus()检查是否有错误,然后用于cvErrorStr()获取它的文本描述。你可以这样做:

// I would recommend putting this in a file, like CVUtility.h

#include <exception>

void check_CV_Error(void)
{
    int errorCode = cvGetErrStatus();
    if (errorCode) // I'm assuming 0 means no reportable error
    {
        throw std::runtime_error(cvErrorStr(errorCode));
        // std::cerr << cvErrorStr(errorCode);
        // ^ if you would rather not use exceptions
    }
}

然后您的代码变为:

bool FaceDetectionStrategy::detectFace(std::string imagePath) {

   IplImage *img = cvLoadImage(imagePath.c_str(), CV_LOAD_IMAGE_COLOR);
   if (img) {
      std::cout << "Image loaded " << imagePath << std::endl;
      cvReleaseImage(&img);
   } else {
      std::cout << "Image not loaded " << imagePath << std::endl;
      check_CV_Error(); // find reason for error
   }
return true;

这将引发异常,让您捕获和记录,并可能做出反应。std::cerr(或者如果您使用该版本,则将错误打印到控制台)

于 2009-07-25T02:10:45.550 回答