Перейти к содержимому
Compvision.ru
mrgloom

Mat управление памятью

Recommended Posts

написал процедуру где просто накладываются 2 изображения

так возвращает пустую матрицу

void align(Mat src, Mat tmp,Mat out,int cx,int cy)
так норм
void align(Mat src, Mat tmp,Mat& out,int cx,int cy)
и так норм
Mat align(Mat src, Mat tmp,int cx,int cy)
так получается когда я в функцию передаю Mat src всё таки происходит копирование? и еще вопрос Mat* использовать нигде смысла нет? как я понимаю например
Mat temp= src; //просто проставляем ссылку(копирование не происходит)
а если
vector<Mat> vec;

vec.push_back(src);// происходит ли копирование?

//надо ли использовать Mat* ?

опять же если я в функцию передаю Mat уже какого то размера допустим ,а потом делаю .create() и меняю размеры, то

старое автоматически удаляется и получается новая матрица нового размера(утечки не происходит?)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Есть разные типы присвоения, вот что в руководстве:

cv::Mat::operator =

Mat& Mat::operator = (const Mat& m)

Mat& Mat::operator = (const MatExpr_Base& expr)

Mat& operator = (const Scalar& s)

Matrix assignment operators

Parameters:

m – The assigned, right-hand-side matrix. Matrix assignment is O(1) operation, that is, no data is copied. Instead, the data is shared and the reference counter, if any, is incremented. Before assigning new data, the old data is dereferenced via Mat::release .

expr – The assigned matrix expression object. As opposite to the first form of assignment operation, the second form can reuse already allocated matrix if it has the right size and type to fit the matrix expression result. It is automatically handled by the real function that the matrix expressions is expanded to. For example, C=A+B is expanded to cv::add(A, B, C) , and add() will take care of automatic C reallocation.

s – The scalar, assigned to each matrix element. The matrix size or type is not changed.

These are the available assignment operators, and they all are very different, so, please, look at the operator parameters description.

И по поводу копирующего конструктора Mat::Mat(const Mat& m) вызываемого при передаче параметра функции:

The matrix that (in whole, a partly) is assigned to the constructed matrix. No data is copied by these constructors. Instead, the header pointing to m data, or its rectangular submatrix, is constructed and the associated with it reference counter, if any, is incremented. That is, by modifying the newly constructed matrix, you will also modify the corresponding elements of m .

Что касается векторов, то я обычно создавал матрицу как локальную переменную, присваивал ей то что хотел, и затем записывал в вектор. При этом счетчик указателей на данные увеличивается, в векторе остается заголовок, указывающий на эти данные, при выходе из области видимости цикла (если заполняю циклом) локальная переменная уничтожается, счетчик указателя на данные уменьшается на единицу и становится равен единице. На следующем витке все повторяется локальной переменной выделяется новая область и т.д.

Когда освобождаем вектор, вызываются деструкторы матирц и счетчики указателей на данные уменьшаются еще на единиуц и становятся равными нулю, и происходит фактическое освобождение памяти.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Mat align(const Mat& src,const Mat& tmp,int cx,int cy)

так лучше передавать, иначе будет заново объект создаваться

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
И по поводу копирующего конструктора Mat::Mat(const Mat& m) вызываемого при передаче параметра функции:

так ничего не копируется? т.е. без разницы что передавать Mat или Mat&?

но тогда всё же непонятно про

так возвращает пустую матрицу

void align(Mat src, Mat tmp,Mat out,int cx,int cy)
так норм
void align(Mat src, Mat tmp,Mat& out,int cx,int cy)
т.е. по идее то мы ссылаемся на те же данные при изменении в функции при передаче Mat, так почему при выходе они не сохраняются?
Что касается векторов, то я обычно создавал матрицу как локальную переменную, присваивал ей то что хотел, и затем записывал в вектор. При этом счетчик указателей на данные увеличивается, в векторе остается заголовок, указывающий на эти данные, при выходе из области видимости цикла (если заполняю циклом) локальная переменная уничтожается, счетчик указателя на данные уменьшается на единицу и становится равен единице. На следующем витке все повторяется локальной переменной выделяется новая область и т.д. Когда освобождаем вектор, вызываются деструкторы матирц и счетчики указателей на данные уменьшаются еще на единиуц и становятся равными нулю, и происходит фактическое освобождение памяти.
ага, теперь понятно. а если мы сделаем cv::Mat::release у локальной переменной, то получается память всё равно не освободится, т.к. есть ссылка еще в векторе есть? еще вопрос про Mat_ допустим имею функцию
void func(Mat_<uchar> src, Mat_<uchar> tmp)

чтобы можно было удобно обращаться как src[y][x] (хотя вроде говорят так медленней работает).

так вот я хочу чтобы можно было передавать не только uchar но и другие типы, как это сделать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

так возвращает пустую матрицу

void align(Mat src, Mat tmp,Mat out,int cx,int cy)

так норм

void align(Mat src, Mat tmp,Mat& out,int cx,int cy)

Когда передаете Mat out, в функции создается объект типа Mat, в функции его меняем, но после выхода из функции к нему доступа нет.

Когда передаете Mat &out, мы передаем ссылку на объект, после выхода из функции, изменения в силе остаются.

В вике более менее подробно рассказано

http://ru.wikipedia.org/wiki/%D0%A1%D1%81%D1%8B%D0%BB%D0%BA%D0%B0_(C%2B%2B)

Если необходимо передавать матрицы, которые не изменяются то лучше передавать так const Mat&, т.к. так быстрее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
а если мы сделаем cv::Mat::release у локальной переменной, то получается память всё равно не освободится, т.к. есть ссылка еще в векторе есть?

cv::Mat::release - уменьшает счетчик на единицу, и если он обнулится, то память данных освободится.

This method can be called manually to force the matrix data deallocation. But since this method is automatically called in the destructor, or by any other method that changes the data pointer, it is usually not needed.

еще вопрос про Mat_

допустим имею функцию

void func(Mat_<uchar> src, Mat_<uchar> tmp)

чтобы можно было удобно обращаться как src[y][x] (хотя вроде говорят так медленней работает).

так вот я хочу чтобы можно было передавать не только uchar но и другие типы, как это сделать?

Так же через шаблоны, я думаю. В качестве параметра шаблона передавать тип данных ( как Mat::at<тип данных>(i,j)=.... ).

Вот как объявлена Mat::at :

template<typename _Tp> _Tp& at(int y, int x);
template<typename _Tp> _Tp& at(Point pt);
template<typename _Tp> const _Tp& at(int y, int x) const;
template<typename _Tp> const _Tp& at(Point pt) const;[/code] Типы данных заменяйте на _Tp где Вам нужно. Кстати, указатель на счетчик ссылок в классе Mat:
[code] // when matrix points to user-allocated data, the pointer is NULL
int* refcount;

То есть его значение вполне можно посмотреть. И еще там говорится, что если данные выделял пользователь, а не конструктор матрицы, то и освобождать их должен пользователь, а не деструктор, т.к. указатель на счетчик ссылок в таком случае равен NULL.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Когда передаете Mat out, в функции создается объект типа Mat, в функции его меняем, но после выхода из функции к нему доступа нет.

Когда передаете Mat &out, мы передаем ссылку на объект, после выхода из функции, изменения в силе остаются.

В вике более менее подробно рассказано

http://ru.wikipedia....%D0%B0_(C%2B%2B)

Если необходимо передавать матрицы, которые не изменяются то лучше передавать так const Mat&, т.к. так быстрее.

чем передача в функцию T& от T отличается я знаю, но тут то дело в том, что при передаче Mat копия внутри функции вроде как не создается.(хотя я не знаю, как проверить?)

как было написано выше

И по поводу копирующего конструктора Mat::Mat(const Mat& m) вызываемого при передаче параметра функции:

The matrix that (in whole, a partly) is assigned to the constructed matrix. No data is copied by these constructors. Instead, the header pointing to m data, or its rectangular submatrix, is constructed and the associated with it reference counter, if any, is incremented. That is, by modifying the newly constructed matrix, you will also modify the corresponding elements of m .

Так же через шаблоны, я думаю. В качестве параметра шаблона передавать тип данных ( как Mat::at<тип данных>(i,j)=.... ).

так мне надо произвольный тип.

а Mat_<T> вроде не прокатывает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
так мне надо произвольный тип.

а Mat_<T> вроде не прокатывает.

У меня такое компилируется:

template<typename _Tp> Mat_<_Tp> func(Mat_<_Tp> src, Mat_<_Tp> tmp, Mat_<_Tp>& tmp2)
{
Mat_<_Tp> res;
res=src+tmp;
tmp2=src*2+tmp;
return res;
}[/code]

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Подскажите, пожалуйста, что не так?


    image = imread("test.png", 1);

    image.create(image.size(), image.type());

    cvtColor(image, gray, CV_BGR2GRAY);

    cvThreshold(gray, gray, 100,255, CV_THRESH_BINARY);

Выдает ошибку error C2664: cvThreshold: невозможно преобразовать параметр 1 из 'cv::Mat' в 'const CvArr *'

До этого работал с IPLimage и cvMat не использовал. Теперь все функции предобработки ругаются на невозможность преобразования. :( Может конвертировать нужно.

Подскажите где почитать за это дело можно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

скорее cvThreshold -> cv::Threshold должно стать ,если речь о cv::Mat

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

скорее cvThreshold -> cv::Threshold должно стать ,если речь о cv::Mat

Спасибо заработало. Подскажите где можно новый референс мануал взять? С описанием функций cv:: ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

http://opencv.org/documentation.html

Справа есть ссылки на pdf-ки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

http://opencv.willowgarage.com/documentation/cpp/memory_management.html

IplImage* src= cvLoadImage("1.tif");

	Mat m= src;//копирование не происходит

	Mat m1(src);//копирование не происходит

	m.release();//не удаляет память

	cvReleaseImage(&src);//удаляет память
вопрос как удалить память через Mat ? не удаляет видимо потому, что на память ссылается еще IplImage* src? так удаляет
Mat m2= imread("1.tif");

	m2.release();
так же можно так
Ptr<IplImage> src= cvLoadImage("1.tif");

src.delete_obj(); // и так работает

src.release(); // и так, но так наверно правильней

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×