Я пытался сделать сравнение содержимого данных в моем объекте IplImage.
У меня есть следующее:
IplImage img1 = IplImage(cv::imread("C:\\TestIm\\barrier_snapshot1.png"),
CV_LOAD_IMAGE_GRAYSCALE);
for (int i=0; i < img1.widthStep * img1.height; i++) {
cout << img1.imageData[i] << endl;
}
Но когда я пытаюсь распечатать его, это вызывает исключение, и я даже не могу поймать его, чтобы напечатать сообщение и посмотреть, что я делаю неправильно. Мое изображение серого цвета, и я верю, что если я не использую cvCreateImage (), это нормально? Я знаю, что это будет что-то глупое или связанное с доступом к массиву, которое я не могу легко получить из документации IplImage.
*ПОЧЕМУ Я СОДЕРЖАЛСЯ, ЧТОБЫ СМЕШАТЬ C И C ++ КОД В МОЕЙ ДИЗАЙНЕ? *
К сожалению, у меня нет выбора! Я работаю над проектом с улучшенными приложениями для обнаружения движения. Мой унаследованный исходный код приложения использует тяжелые материалы BOOST и OpenCV. В частности, он использует IplImage * (я ненавижу его, усложняю жизнь и вызывает утечку памяти) для хранения таких вещей, как маски изображений. Я понимаю, что если я сохраню IplImage * в долгосрочной перспективе, у меня будет незаконная ссылка и нарушение доступа. поэтому я сохраняю копию фактического содержимого, указанного IplImage *. В качестве примера:
// getLongHistory() returns IplImage*
IplImage history_long = *(motionHistory.getLongHistory());
Всего есть 6 изображений масок, которые сделаны с использованием IplImage *. На данный момент я осуждаю программиста, который решил сделать это в IplImage *. Проблема возникает, когда я пытаюсь загрузить эти изображения маски, и вот как я это делаю:
// Passing pointer to the address of the mask stored (alive in the memory)
motionHistory.setLongHistory(&(matcher.getCurrentSceneObject().getLongHistory()));
Я полагаю, что у меня проблема с глубокой и мелкой копией объектов IplImage. Я считаю, что сохранение его как cv :: Mat из IplImage * и загрузка его как IplImage * из cv :: Mat, вероятно, уменьшит нагрузку, так как я подозреваю, что это возможно ЧТО-ТО под высокоуровневыми функциями, чтобы копирование для данных и ROI делалось соответственно. Но как новичок я могу предположить что угодно. Пожалуйста помоги!
ОБНОВИТЬ
В моем коде я делал это в прошлом:
/* I store all my mask images in a vector of pairs made of <int, IplImage>
* __MASK_LONG__ etc. are predefined intergers
* getMaskLong() etc. methods return IplImage* to the respective mask images.
*/
myImages.clear(); // To make sure that I have no extra stuff
myImages.push_back(std::make_pair<int, IplImage>(_MASK_LONG_, maskHistory.getMaskLong()));
myImages.push_back(std::make_pair<int, IplImage>(_MASK_SHORT_, maskHistory.getMaskShort()));
Тем не менее, после получения предложений и выполнения некоторых основных R&А, сейчас я делаю это, чтобы предотвратить поверхностное копирование:
myImages.clear();
myImages.push_back(std::make_pair<int, IplImage>(_MASK_LONG_, *cvCloneImage(maskHistory.getMaskLong())));
myImages.push_back(std::make_pair<int, IplImage>(_MASK_SHORT_, *cvCloneImage(maskHistory.getMaskShort())));
Я могу подтвердить, что это работает, поскольку я вижу, как последние изображения маски загружаются в окне OpenCV! И я совершенно уверен, насколько важно делать Deep Copy как минимум 2/3 раза в любой задаче программирования. Так что спасибо, что поставили меня на правильный путь. Но теперь у меня есть проблема, которую я имел в виду при реализации этих изменений — ошибка выделения памяти. И сообщение было найдено:
OpenCV Error: Insufficient memory (Failed to allocate 3686404 bytes) in OutOfMemoryError,
file /home/naresh/OpenCV-2.4.0/modules/core/src/alloc.cpp, line 52
Если я достаточно глубок, чтобы знать о C / C ++, во-первых, я совершаю преступление, смешивая их вместе (У меня нет выбора !! Это приложение для LEGACY!). Во-вторых, существует несоответствие, то есть неправильный набор вызовов malloc / free в файле alloc.cpp (где возникает проблема). Или, может быть, куча повреждена или заполнена. Я глупый?
Не смешивай интерфейс C OpenCV с интерфейсом C ++.
В идеале вы бы решили проблему, используя исключительно интерфейс C ++, например:
cv::Mat gray = cv::imread("C:\\TestIm\\barrier_snapshot1.png", CV_LOAD_IMAGE_GRAYSCALE);
cv::Mat_<uchar>::iterator it = gray.begin<uchar>();
cv::Mat_<uchar>::iterator end = gray.end<uchar>();
for (; it != end; ++it)
{
cout << *it << endl;
}
Или же:
cv::Mat gray = cv::imread("C:\\TestIm\\barrier_snapshot1.png", CV_LOAD_IMAGE_GRAYSCALE);
for (int i = 0; i < gray.cols; i++)
{
for (int j = 0; j < gray.rows; j++)
{
cout << gray[gray.cols * j + i] << endl;
}
}
Да, cv::imread()
Можно также загрузить входное изображение в градациях серого. Но если вам действительно нужно придерживаться интерфейса C, то бросьте cv::imread()
и использовать cvLoadImage()
вместо. Есть несколько постов, объясняющих, как это сделать, используйте поисковая строка.
Если вы решили продолжить смешивать интерфейсы (пожалуйста, не надо), проверить эту тему поскольку он объясняет, как конвертировать IplImage*
в cv::Mat
,
Других решений пока нет …