Я использую cvBlobs для отслеживания некоторых объектов в видео. cvBlobs использует старый интерфейс C с такими типами, как IplImage, cvMat, .. и я использую интерфейс C ++, который использует cv :: Mat.
Поэтому я должен конвертировать между двумя типами, чтобы использовать библиотеку. Это работает, но у меня проблемы с освобождением памяти. Память, используемая моей программой, продолжает расти.
Это мой код, и внизу вы можете увидеть мою попытку освободить память (ошибка компилятора).
void Tracker::LabelConnectedComponents(Mat& Frame, Mat& Foreground)
{
// Convert to old format, this is the method used in the opencv cheatsheet
IplImage IplFrame = Frame;
IplImage IplForeground = Foreground;
IplImage *LabelImg = cvCreateImage(cvGetSize(&IplFrame), IPL_DEPTH_LABEL, 1);
// Make blobs (IplForeground is the segmented frame, 1 is foreground, 0 background)
unsigned int result = cvLabel(&IplForeground, LabelImg, Blobs);
// Remove small blobs
cvFilterByArea(Blobs, 500, 1000000);
// Draw bounding box
cvRenderBlobs(LabelImg, Blobs, &IplFrame, &IplFrame, CV_BLOB_RENDER_BOUNDING_BOX | CV_BLOB_RENDER_CENTROID);
// Convert back to c++ format
Frame = cvarrToMat(&IplFrame);
// Here are the problems
cvReleaseImage(&IplFrame); // error
cvReleaseImage(&IplForeground); // error
cvReleaseImage(&LabelImg); // ok
}
В качестве аргумента cvReleaseImage имеет тип IplImage **, и это ошибка компилятора:
tracker.cpp|35 col 33 error| cannot convert ‘IplImage* {aka _IplImage*}’ to ‘IplImage** {aka _IplImage**}’ for argument ‘1’ to ‘void cvReleaseImage(IplImage**)’
я знаю &IplFrame не правильный аргумент, но &&IplFrame не работает. Как я могу выпустить эти 2 IplImages?
Проблема в том, что вы создали копии своих объектов здесь:
IplImage IplFrame = Frame;
IplImage IplForeground = Foreground;
Поэтому эти звонки:
cvReleaseImage(IplFrame);
cvReleaseImage(IplForeground);
не выпустит исходные изображения, даже если это скомпилируется. Если вы уже удаляете объекты (т. Е. Меняете их), почему вы отправляете их в метод как ссылки, а не как указатели? Я немного запутался, так как кажется, что вы делаете что-то вроде этого:
Mat frame = ...
Mat fg = ...
LabelConnectedComponents(frame, fg); // function releases the frame/fg memory
// at this point you are left with invalid frame/fg
Я должен проверить документацию, и там написано Mat::operator IplImage() doesn't copy data
Это означает, что IplFrame не владеет памятью, поэтому некорректно освобождать ее.
Я думаю, это зависит от того, как Mat
экземпляр был создан — если он был создан из IplImage*
с copyData
установлен в false
тогда вам нужно будет выпустить оригинал IplImage
пример. Если он был создан с copyData
установлен в true
, затем Mat
экземпляр автоматически позаботится об этом (если вы не сделаете это явно с Mat::release
)
Вам не нужно отменять выделение IplImages, созданных из объектов Mat. Это тонкие обертки, которые не копируют данные, поэтому вам не нужно ничего освобождать.
А поскольку cv :: Mat имеет автоматическое управление памятью, вам ничего не нужно освобождать.
И, как завершение, для вызова cvReleaseImage вам нужно отправить указатель на указатель:
IplImage* pimg= cvLoadImage();
...
cvReleaseImage(pimg);
Конструкция
IplImage img;
...
cvReleaseImage(&&img);
Не работает потому что &img является адресом (адресом памяти), но не обозначает переменную. Итак, следующая оценка &(&img) выдаст ошибку компилятора, потому что &img это значение. У значения не может быть адреса, но это простое число.