Win7では、mingw-64ツールチェーンを使用したmsys2(Linux gcc上でも同じことが起こります)、OpenCv-3.2.0(ただし3.1.0 )。ここでスレッド中のOpenCv 3.2.0でのメモリリーク
は、私は私の問題を示すために、可能な限り簡素化しようとしたコードです:私はopencvDetector->process(img);
直接呼び出す場合
#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
:
#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クラスですメモリ使用量が急速に安定します。
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)
ただし、 nはスレッド・バージョン(OpenCvDetectorのメンバ関数がスレッドで呼び出される)、メモリ使用量が増え続けて:私はたくさんのスレッドでOpenCVの検出の多くを達成したいので
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)
は、私は失望しています、だから少しのメモリリークが急速にリソースの巨大な浪費になっているようです。 ヒントをいただければ幸いです...
こんにちはラーマ。私が間違っている場合、opencvdetectorの単一インスタンス自体に問題はありません。問題はCascadeClassifierの単一インスタンスの使用に関連していますか?私は明日の朝にそれを試さなければならないが、カスケードを読み込むことは非常に軽いものではないので、迷惑になるだろう。 – VirgileD
とにかく、新しい道を探検してくれてありがとう! スレッドごとにスレッドに参加するときに、これがどのように問題になるかは分かりませんが、問題があるかどうかはまだ分かりません。 – VirgileD
こんにちは@Rama。他の複数のテストの後、あなたのソリューションが私のニーズに合っていなくても(メモリの代わりにパフォーマンスを落とすような)、あなたは正しいと思います。複数の同じcv :: CascadeClassifierでdetectMultiScaleを呼び出すことはできませんスレッド(特にここに記載されています:https://github.com/opencv/opencv/issues/4287)。 – VirgileD