Closed GoogleCodeExporter closed 8 years ago
Would it possible to verify that this does not happen when using OpenCV
directly in C/C++, without JavaCV? OpenCV has quite a few leaks itself, and it
looks like one of those...
Original comment by samuel.a...@gmail.com
on 23 Feb 2012 at 1:42
Hi I nailed it.. First of all I made some googling trying to reimplement my
program in c/c++ as you suggested. I came back to the original face detection
homepage of opencv found an interesting paragraph:
http://opencv.willowgarage.com/wiki/FaceDetection :
"The above code (function detect and draw) has a serious memory leak when run
in an infinite for loop for real time face detection. Please add
"cvReleaseMemStorage(&storage);" after you release the temp image in the detect
and draw function. The cvClearMemStorage only clears the previous set of values
but does not free memory. I did not modify the initial code as it is simply not
mine. I have also cleared "faces" using cvClearSeq in my process of trying to
find the memory leak as the program would quickly crash for 640x480 res 30fps
video. I am very thankful to the original programmer for the code. Please let
me know if this helps. --AbhinayE"
So I tried to use cvReleaseMemStorage() instead of cvClearMemStorage() in my
program. The first two detections were successful but then I got an internal
native code error. Head of the error file:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f86bd733813, pid=29982, tid=140216804407040
#
# JRE version: 6.0_20-b20
# Java VM: OpenJDK 64-Bit Server VM (19.0-b09 mixed mode linux-amd64 compressed
oops)
# Derivative: IcedTea6 1.9.10
# Distribution: Ubuntu 10.04.1 LTS, package 6b20-1.9.10-0ubuntu1~10.04.2
# Problematic frame:
# C [libopencv_core.so.2.3.1+0x58813]
#
# If you would like to submit a bug report, please include
# instructions how to reproduce the bug and visit:
# https://bugs.launchpad.net/ubuntu/+source/openjdk-6/
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
........
You should be able to reproduce this by using a detection loop and instead of
clearing the storage with cvClearMemStorage() clearing it with
cvReleaseMemStorage().
Ok now my solution: I finally used storage.release() as I do for images. This
solution is somehow obvious since you explain in your README that the
counterpart for create() is release() but all the examples I found use
cvClearMemStorage().
Original comment by cesma...@googlemail.com
on 23 Feb 2012 at 2:53
cvClearMemStorage() does not release any system memory... Read OpenCV's
documentation about it:
http://opencv.willowgarage.com/documentation/c/dynamic_structures.html
The new C++ API tends to do without this little system, and instead rely on STL
data structures, without properly evaluating the differences in performance IMO
Anyway, calling create() and release() all the time fixes the leak?
Original comment by samuel.a...@gmail.com
on 23 Feb 2012 at 11:45
Hi Samuel,
Good to know, thanks for the advice. Yeah it fixed all the leaks. The final
detection code looks like this:
public FaceDetectionResult detectFacesWithoutRotating(BufferedImage image,
double scaleFactor, int minNeighbours, int flags) {
if (this.frontalFaceCasc == null) {
init(FRONTALFACE_CASCADE_FILE);
}
CvMemStorage tempStorage = CvMemStorage.create();
// create IplImage form BufferedImage
IplImage original = IplImage.createFrom(image);
IplImage grayImage = null;
if (original.nChannels() >= 3) {
// We need a grayscale image in order to do the recognition, so we
// create a new image of the same size as the original one.
grayImage = IplImage.create(image.getWidth(), image.getHeight(),
IPL_DEPTH_8U, 1);
// We convert the original image to grayscale.
cvCvtColor(original, grayImage, CV_BGR2GRAY);
} else {
grayImage = original.clone();
}
// if set equalize the image
if (EQUALIZE_HISTOGRAM) {
IplImage grayImageEqualized = IplImage.create(original.width(),
original.height(), IPL_DEPTH_8U, 1);
grayImageEqualized = IplImageUtils.equalizeHist(grayImage);
grayImage.release();
grayImage = null;
grayImage = grayImageEqualized.clone();
grayImageEqualized.release();
grayImageEqualized = null;
}
// We detect the faces.
CvSeq faces = cvHaarDetectObjects(grayImage, this.frontalFaceCasc,
tempStorage, scaleFactor, minNeighbours, flags);
Face[] resultFaces = fillFaceArrayWithCvSeq(faces);
// clear storage and images after detection
tempStorage.release();
return new FaceDetectionResult(resultFaces, image, image, false, 0.0f);
}
/**
* Create a list of Faces out of the CvSeq class which contains the
* CvRectangles defining the faces borders
*
* @param faces
* Sequence of faces
* @return List of the detected faces. If no face is found it returns an
* empty Face List.
*/
private Face[] fillFaceArrayWithCvSeq(CvSeq faces) {
if (faces.total() == 0) {
return new Face[0];
} else {
Face[] result = new Face[faces.total()];
// We iterate over the discovered faces and add them to our
// Face-object list
for (int i = 0; i < faces.total(); i++) {
CvRect r = new CvRect(cvGetSeqElem(faces, i));
result[i] = new Face(r.x(), r.y(), r.width(), r.height());
}
return result;
}
}
I appreciate your help, Cheers
Original comment by cesma...@googlemail.com
on 24 Feb 2012 at 1:02
Great, thanks for the feedback!
Original comment by samuel.a...@gmail.com
on 24 Feb 2012 at 2:21
Original issue reported on code.google.com by
cesma...@googlemail.com
on 23 Feb 2012 at 1:17