我正在使用Emgu作为OpenCV库的包装器来实现一个小的FaceRecognition程序。似乎工作正常,但是我需要一个函数来返回图像样本与数据库中人脸之间的所有距离(实现的FaceRecognizer.Predict method仅返回最小的距离和标签)。
因此,我从Git构建了Emgu,以适应非托管代码(cvextern.dll)中的功能。
这是face_c.cpp中的原始照片
void cveFaceRecognizerPredict(cv::face::FaceRecognizer* recognizer, cv::_InputArray* image, int* label, double* dist)
{
int l = -1;
double d = -1;
recognizer->predict(*image, l, d);
*label = l;
*dist = d;
}
由于预测功能,可以在l
和d
中存储最小距离和相应的标签。
我在opencv face.hpp中的summary之后编写的方法:
void cveFaceRecognizerPredictCollector(cv::face::FaceRecognizer * recognizer, cv::_InputArray * image, std::vector<int>* labels, std::vector<double>* distances)
{
std::map<int, double> result_map = std::map<int, double>();
cv::Ptr<cv::face::StandardCollector> collector = cv::face::StandardCollector::create();
recognizer->predict(*image, collector);
result_map = collector->getResultsMap();
for (std::map<int, double>::iterator it = result_map.begin(); it != result_map.end(); ++it) {
distances->push_back(it->second);
labels->push_back(it->first);
}
}
还有c#中的调用者
using (Emgu.CV.Util.VectorOfInt labels = new Emgu.CV.Util.VectorOfInt())
using (Emgu.CV.Util.VectorOfDouble distances = new Emgu.CV.Util.VectorOfDouble())
using (InputArray iaImage = image.GetInputArray())
{
FaceInvoke.cveFaceRecognizerPredictCollector(_ptr, iaImage, labels, distances);
}
[DllImport(CvInvoke.ExternLibrary, CallingConvention = CvInvoke.CvCallingConvention)]
internal extern static void cveFaceRecognizerPredictCollector(IntPtr recognizer, IntPtr image, IntPtr labels, IntPtr distances);
该应用程序实时运行,因此c#中的函数被连续调用。我的数据库中只有两张脸和一个标签(同一个人),因此第一个调用正确返回唯一可能的标签并将其存储在labels
中。为了保持应用程序运行,返回的标签和labels
向量的大小不断增长,充满了我不知道他在哪里的未注册标签。在我看来,c ++中的收集器没有得到很好的引用,因此每次调用该函数时,它都会不断存储数据,而不会释放先前的数据,并覆盖它们。但这只是我的猜测,我对c ++不太满意。
还有什么可能是错误的?
希望可以为您提供帮助