CvMat и Imread против IpImage и CvLoadImage
Использование OpenCv 2.4
У меня есть два варианта загрузки изображений:
1- CvMat and Imread
2- IpImage and CvLoadImage
Какой из них лучше использовать? Я попытался смешать два и в конечном итоге ошибка сегмента.
4 ответа
imread
возвращает Mat
не CvMat
, Это два разных интерфейса (Mat
/imread
для C++ и Ipl... и Cv.. для интерфейса C).
Интерфейс C++ более приятный, безопасный и простой в использовании. Он автоматически обрабатывает память и позволяет писать меньше кода для той же задачи. Ребята из OpenCV выступают за использование C++, если только некоторые очень специфические требования проекта не заставят вас перейти к C.
Пример (C++)
cv::Mat image = imread("path/to/myimage.jpg")
if(image.empty())
return;
cv::imshow("Image", image);
cv::Mat bw = image > 128; // threshold image
cv::Mat crop = image(cv::Rect(0, 0, 100, 100)); // a 100px x 100px crop
crop= 0; // set image to 0
cv::waitKey();
// end code here
Обратите внимание, что если не указано иное, все матричные присвоения ссылаются на одни и те же данные. В приведенном выше примере crop
матрица указывает на image
и установка его в ноль установит эту конкретную часть image
до 0.
Чтобы создать новую копию данных, используйте Mat::copyTo или Mat::clone();
И интерфейс C
IplImage* pImg = CvLoadImage("path/to/myimage.jpg");
if(pImg == NULL)
return;
// ... big bloat to do the same operations with IplImage
CvShowImage("Image", pImg);
cvWaitKey();
CvReleaseImage(&pImg); // Do not forget to release memory.
// end code here
Из кулинарной книги OpenCV_2:
Эта структура была унаследована от библиотеки IPL (то есть библиотеки обработки изображений Intel), которая теперь интегрирована с библиотекой IPP (библиотека Intel Integrated Performance Primitive). Если вы используете код и библиотеки, которые были созданы со старым интерфейсом C, вам может потребоваться манипулировать этими структурами IplImage. К счастью, есть удобный способ конвертировать IplImage в объект cv::Mat.
IplImage * iplImage = cvLoadImage ("c: \ img.jpg"); cv::Mat image4 (iplImage, false);
Функция cvLoadImage является функцией C-интерфейса для загрузки изображений. Второй параметр в конструкторе объекта cv::Mat указывает, что данные не будут скопированы (установите его в true, если вы хотите новую копию, в то время как false - значение по умолчанию, поэтому его можно было опустить), то есть оба IplImage и image4 будут использовать одни и те же данные изображения. Вы должны быть осторожны, чтобы не создавать висячие указатели. По этой причине безопаснее инкапсулировать указатель IplImage в класс указателя подсчета ссылок, предоставляемый OpenCV 2:
cv:: Ptr iplImage = cvLoadImage ("c: \ img.jpg");
В противном случае, если вам нужно освободить память, указанную вашей структурой IplImage, вам нужно сделать это явно: cvReleaseImage(&iplImage); Помните, что вам следует избегать использования этой устаревшей структуры данных. Вместо этого всегда используйте cv::Mat.
IplImage и Mat являются взаимозаменяемыми.
Я бы посоветовал вам использовать Mat и imread(), поскольку получить данные из Mat очень просто.
Mat:: data возвращает указатель на фактические данные матрицы, которые в 1D и значения легко доступны. http://opencv.itseez.com/modules/core/doc/old_basic_structures.html?highlight=mat
Если вы хотите добавить концепции машинного обучения в OpenCV для различных алгоритмов отслеживания (например, OpenTLD), вы можете легко получить доступ к данным, используя Mat.data, чтобы получить указатель на фактическую матрицу.
Многие из утилит OpenCV (например, CalcOpticalFlowPyrLK и т. Д.) Требуют Mat. Я бы предложил вам использовать мат. IplImage это старая вещь сейчас.
Это зависит от того, насколько вы удобны с указателями. В IplImage вы можете получить доступ к данным как
data[i*widthstep+j*nchannels +k]
где i,j,k - некоторые целые числа, к которым довольно легко подойти. В обычной матрице 3 измерений это не так легко получить доступ к данным. Для нормальной матрицы доступ к данным для [i][j]
*(*(a + i) + j) is the value of jth element of ith row in matrix a