无法访问IplImage数据

时间:2013-01-31 15:51:32

标签: c++ c pointers opencv iplimage

我一直在尝试对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()); 

使用IplImage *共有6个蒙版图像。此刻,我正在谴责决定在IplImage *中执行此操作的程序员。当我试图加载这些蒙版图像时出现问题,这就是我的方法:

// Passing pointer to the address of the mask stored (alive in the memory)
motionHistory.setLongHistory(&(matcher.getCurrentSceneObject().getLongHistory()));

我相信我遇到了IplImage对象的深拷贝和浅拷贝的问题。我相信将它保存为来自IplImage *的cv :: Mat并将其加载为来自cv :: Mat的IplImage *可能会减轻负担,因为我怀疑它可能会在高级函数下面 SOMETHING 复制数据和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&amp; A之后,我现在这样做是为了防止浅层复制:

  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 ++,首先我犯了将它们混合在一起的罪行(我没有选择!!这是一个传统的应用程序!)。其次,在alloc.cpp文件(产生问题的地方)中存在不匹配,即对malloc / free的不正确调用集。或者可能只是堆已损坏或已满。我是傻瓜吗?

1 个答案:

答案 0 :(得分:2)

不要将OpenCV的C接口与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()代替。有几篇文章解释了如何执行此操作,请使用搜索框

如果您决定继续混合接口(请不要),check this thread,因为它解释了如何将IplImage*转换为cv::Mat