Выделение памяти из IplImage, инициализированной из cv :: Mat

Я использую 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?

1

Решение

Проблема в том, что вы создали копии своих объектов здесь:

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)

1

Другие решения

Вам не нужно отменять выделение IplImages, созданных из объектов Mat. Это тонкие обертки, которые не копируют данные, поэтому вам не нужно ничего освобождать.

А поскольку cv :: Mat имеет автоматическое управление памятью, вам ничего не нужно освобождать.

И, как завершение, для вызова cvReleaseImage вам нужно отправить указатель на указатель:

IplImage* pimg= cvLoadImage();
...
cvReleaseImage(pimg);

Конструкция

IplImage img;
...
cvReleaseImage(&&img);

Не работает потому что &img является адресом (адресом памяти), но не обозначает переменную. Итак, следующая оценка &(&img) выдаст ошибку компилятора, потому что &img это значение. У значения не может быть адреса, но это простое число.

1

По вопросам рекламы [email protected]