OpenCv 3.2.0 在线程中的内存泄漏

Posted

技术标签:

【中文标题】OpenCv 3.2.0 在线程中的内存泄漏【英文标题】:Memory leak with OpenCv 3.2.0 when in thread 【发布时间】:2017-03-21 20:35:59 【问题描述】:

在 Win7 上,在 msys2 上使用 mingw-64 工具链(但同样发生在 linux gcc 上),使用 OpenCv-3.2.0(但与 3.1.0 相同)。

这是我试图尽可能简化以显示我的问题的代码:

#include <thread>
#include <iostream>
#include <iomanip>

#include "opencv_detector.h"
#include <windows.h>
#include <psapi.h>

/**
* Returns the current resident set size (physical memory use) measured in bytes
*/
inline size_t getCurrentRSS( )

  PROCESS_MEMORY_COUNTERS info;
  GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
  return (size_t)info.WorkingSetSize;


int main(int argc, char** argv)

  auto opencvDetector = new wl::ds::OpencvDetector();
  cv::Mat img = cv::imread("./test.png");
  int i = 0;
  long rss = getCurrentRSS();
  long rss_start = rss;
  long rss1 = rss;
  std::cout << std::setw(7) << "START " << rss <<std::endl;
  while(i++<1000) 
    // If I just call the function no memory leak
    //opencvDetector->process(img);
    // If I call the function in a thread, memory leak
    auto opencvDetectProfile = std::thread(&wl::ds::OpencvDetector::process, opencvDetector, img);
    opencvDetectProfile.join();

    rss1 = getCurrentRSS();
    if(rss!=rss1) 
      std::cout << std::setw(6) << i << " " << rss1 << " (" << std::setw(8) << (rss1-rss) << " / " << std::setw(7) << (rss1-rss_start) << ")" << std::endl;
      rss = rss1;
    
  
  std::cout << std::setw(7) << "STOP " << rss1 << " (" << std::setw(8) << (rss1-rss) << " / " << std::setw(7) << (rss1-rss_start) << ")" << std::endl;
  return 0;

这是一个非常简单的 openCvDetector 类:

#ifndef WL_DS_OPENCVDETECTOR_H
#define WL_DS_OPENCVDETECTOR_H

#include <string>
#include <opencv2/opencv.hpp>

namespace wl 
namespace ds 


class OpencvDetector 
 private:
   cv::CascadeClassifier cascadeClassifier;
 public:
   OpencvDetector()  cascadeClassifier.load("haarcascade_frontalface.xml"); ;
   void process(cv::Mat img) 
     cv::cvtColor(img, img, CV_BGR2GRAY);
     cv::equalizeHist(img, img);
     std::vector<cv::Rect> faces;
     cascadeClassifier.detectMultiScale(img, faces, 1.05, 3, 0|CV_HAAR_SCALE_IMAGE);
   ;
;

 // wl
 // ds

#endif // WL_DS_OPENCVDETECTOR_H

如果我直接调用opencvDetector-&gt;process(img);,内存使用会迅速稳定:

START 18280448
     1 30892032 (12611584 / 12611584)
     2 30908416 (   16384 / 12627968)
     4 30928896 (   20480 / 12648448)
     5 30941184 (   12288 / 12660736)
     8 30945280 (    4096 / 12664832)
    11 30953472 (    8192 / 12673024)
    12 30957568 (    4096 / 12677120)
  STOP 30957568 (       0 / 12677120)

但是如果我运行线程版本(OpenCvDetector的成员函数在一个线程中调用),内存使用量一直在增长:

START 18280448                      
    1 30965760 (12685312 / 12685312)
    2 30879744 (  -86016 / 12599296)
    3 30883840 (    4096 / 12603392)
    8 30916608 (   32768 / 12636160)
   10 31035392 (  118784 / 12754944)
   11 31047680 (   12288 / 12767232)
   12 30961664 (  -86016 / 12681216)
   14 30965760 (    4096 / 12685312)
   20 30969856 (    4096 / 12689408)
  120 31346688 (  376832 / 13066240)
  121 31084544 ( -262144 / 12804096)
  153 31088640 (    4096 / 12808192)
  213 31092736 (    4096 / 12812288)
  233 31096832 (    4096 / 12816384)
  248 31100928 (    4096 / 12820480)
  294 31105024 (    4096 / 12824576)
  335 31109120 (    4096 / 12828672)
  417 31113216 (    4096 / 12832768)
  499 31117312 (    4096 / 12836864)
  504 31121408 (    4096 / 12840960)
  540 31125504 (    4096 / 12845056)
  581 31129600 (    4096 / 12849152)
  665 31133696 (    4096 / 12853248)
  749 31137792 (    4096 / 12857344)
  781 31141888 (    4096 / 12861440)
  833 31145984 (    4096 / 12865536)
  848 31207424 (   61440 / 12926976)
 STOP 31207424 (       0 / 12926976)

我很失望,因为我想在很多线程中实现很多 OpenCv 检测,所以看起来很小的内存泄漏正在迅速成为资源的巨大浪费。 任何提示将不胜感激...

【问题讨论】:

【参考方案1】:

您在所有线程中使用相同的opencvDetector,这可能会导致未定义的行为。在您的情况下,它会导致内存泄漏。

试试这个方法:

auto opencvDetector = new wl::ds::OpencvDetector();
auto opencvDetectProfile = std::thread(&wl::ds::OpencvDetector::process, opencvDetector, img);
opencvDetectProfile.join();
delete opencvDetector;

【讨论】:

嗨拉玛。纠正我如果我错了,opencvdetector单实例本身没有问题,问题与CascadeClassifier单实例的使用有关吗?我明天早上必须尝试,但这会很烦人,因为加载级联不是一件很轻松的事情...... 无论如何,感谢新的探索途径!虽然,我每次都加入线程时不明白这怎么可能是个问题,但是知道这是否可能是个问题仍然很有趣。 你好@Rama。经过多次其他测试,看起来,即使您的解决方案不符合我的需求(因为它只会降低性能而不是内存),您是对的,一个人不能在多个相同的 cv::CascadeClassifier 上调用 detectMultiScale线程(这里特别说明:github.com/opencv/opencv/issues/4287)。

以上是关于OpenCv 3.2.0 在线程中的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

javascript中的关闭和回调内存泄漏

OpenGL VBO 会泄漏内存吗?

内存泄漏和内存溢出的区别

OpenCV Python:如何避免 py3 中的 cv2.imwrite() 内存“泄漏”?

与opencv链接时内存泄漏

内存泄漏与垃圾回收机制