在使用OpenCV从视频预处理人脸训练数据时,在正常运行一段时间后,程序报错 。
上述错误是典型的内存溢出错误,肯定是程序中存在使用后的指针没有释放,检查后发现使用是使用的IplImage* srcCopy参数在函数结束(或者已经不用了)的地方没有释放,只需要在相应的位置使用cvReleaseImage(&srcCopy)释放掉就可以。其他情况可类似排查,实例代码如下:
// 截取人脸,并保存
void CropFaceAndSave(const Mat& imgInput, bool isRight, const string& filename){
IplImage* src = &IplImage(imgInput);
IplImage* srcCopy;
int ratio = 3; // imgorl/imgdeal = 3 将图像缩小3倍处理
if (isRight)
{
srcCopy = cvCreateImage(cvSize(src->height, src->width), src->depth, src->nChannels);
cvTranspose(src, srcCopy);
cvFlip(srcCopy, NULL, 0);
}
else{
srcCopy = cvCreateImage(cvSize(src->width, src->height), src->depth, src->nChannels);
cvCopy(src, srcCopy, 0);
}
Mat imgOriginal(srcCopy), imgResult;
resize(imgOriginal, imgResult, Size(srcCopy->width / ratio, srcCopy->height / ratio));
// 对imgcopy检测人脸
Mat face_gray;
cvtColor(imgResult, face_gray, CV_BGR2GRAY); //rgb类型转换为灰度类型
equalizeHist(face_gray, face_gray); //直方图均衡化
face_cascade.detectMultiScale(face_gray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
for (int i = 0; i < faces.size(); i++){
// 起始点
Point pointStart(faces[i].x, faces[i].y);
Point pointEnd(faces[i].x + faces[i].width, faces[i].y + faces[i].height);
Point center(int(faces[i].x + faces[i].width*0.5), int(faces[i].y + faces[i].height*0.5));
rectangle(imgResult, pointStart, pointEnd, Scalar(255, 0, 0), 2, 8, 0);
// 阈值选取,滤除小的干扰
if (ratio*faces[i].width < srcCopy->width / 3){
//cout << "滤除 x = " << ratio*faces[i].x << ", y = " << ratio*faces[i].y << endl;
continue;
}
// 计算原图上的截取区域,并截取
Point centerInOrignal(ratio*center.x, ratio*center.y);
// cout << "x = " << centerInOrignal.x << ", y = " << centerInOrignal.y << endl;
// 可以剪裁
if (centerInOrignal.y >= 360){
if (centerInOrignal.y > 720){
centerInOrignal.y = 720;
}
// 新建ROI大小的图片
cvSetImageROI(srcCopy, cvRect(0, centerInOrignal.y - 360, srcCopy->width, srcCopy->width));
IplImage* imgCrop = cvCreateImage(cvSize(srcCopy->width, srcCopy->width), srcCopy->depth, srcCopy->nChannels);
cvCopy(srcCopy, imgCrop, 0);
cvResetImageROI(srcCopy);
Mat imgCropResult(imgCrop);
imshow("Crop ROI", imgCropResult);
stringstream ss;
string indexStr;
ss << saveIndex;
ss >> indexStr;
imwrite(filename + "\\real" + indexStr + ".png", imgCropResult);
cvReleaseImage(&imgCrop); // 不用的指针一定要释放掉,不然内存会泄露
saveIndex++;
}
}
imshow("检测人脸", imgResult);
// 注意,这个指针不用释放,他不是我们新建出来的,只是指向了现有内存空间,而那块空间在栈中,系统会自动释放
//cvReleaseImage(&src);
// 只需要释放我们申请的内存
cvReleaseImage(&srcCopy);
}