【问题标题】:C++, Access Violation using OpenCV to get RGB value of pixelC ++,使用OpenCV获取像素的RGB值的访问冲突
【发布时间】:2011-04-20 13:53:08
【问题描述】:

我正在尝试使用 OpenCV 来查找图像中像素的 RGB 值。到目前为止,我已经尝试了以下方法:

int blue = ((uchar *)(img->imageData + y*img->widthStep))[x*img->nChannels + 0];
int green = ((uchar *)(img->imageData + y*img->widthStep))[x*img->nChannels + 1];
int red = ((uchar *)(img->imageData + y*img->widthStep))[x*img->nChannels + 2];

int blue = ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0];
int green = ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1];
int red = ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2];

CvPoint pt = {5,5};
uchar* temp_ptr = &((uchar*)(img->imageData + img->widthStep*pt.y))[pt.x*3];
int blue = temp_ptr[0];
int green = temp_ptr[1];
int red = temp_ptr[2];

但在上述所有情况下,我都会遇到同样的错误:

Unhandled exception at 0x00f5104f in test.exe: 0xC0000005: Access violation reading location: 0x00000048

最后一个十六进制数字 (0x0...48) 永远不会改变。我看起来这可能是由于写得比数组的边界更远。所以我在没有任何其他代码的情况下单独运行了每个示例,但仍然得到相同的错误。是什么导致了这个错误,我该如何解决?

额外信息:Windows 7、MSVC 2010 Express、OpenCV 2.1

--UPDATE--

我意识到上面的代码比它需要的更复杂,所以我以 karlphillip 提供的 sn-p(谢谢!)作为基础并使用了类似的方法。我仍然遇到错误,这次是在一个更陌生的地方:

IplImage *slice = cvLoadImage("test.png");
int bpp = slice ->nChannels;

错误发生在第二行,仍然是访问冲突。在此之前没有执行与 OpenCV 相关的代码,只是一些变量初始化。 'test.png' 只是一个 7*7 像素的 'X' 我在油漆中制作来测试它,使用 .jpg 有 hte saem 结果。

为了确保我没有错误地安装 OpenCV,我单独使用了这段代码(从下面复制):

int main ()
{
    IplImage* pRGBImg = cvCreateImage(cvSize(5,5),IPL_DEPTH_8U,3);

    int width = pRGBImg->width; 
    int height = pRGBImg->height;
    int bpp = pRGBImg->nChannels; 

    cvNamedWindow("Image view", 1);
    cvShowImage("Image view", pRGBImg);
    cvWaitKey(0);
    cvDestroyWindow("Image view");

    for (int i=0; i < width*height*bpp; i+=bpp) 
    {
      if (!(i % (width*bpp))) // print empty line for better readability
          std::cout << std::endl;

      std::cout << std::dec << "R:" << (int) pRGBImg->imageData[i] <<  
                              " G:" << (int) pRGBImg->imageData[i+1] <<  
                              " B:" << (int) pRGBImg->imageData[i+2] << " "; 
    }
}

这没有返回任何错误,但我确实得到了一些可能很奇怪的结果,这是控制台输出的前几行:

R:13 G:-16 B:-83
R:-70: G:13 B:-16
R:-83 G:-70 B: 13

负 RGB 值?这是可以预期的,还是这不起作用。如果正常,那么我正在加载的图像('test.png')一定是问题所在。但是,如果一个简单的频道数量请求导致访问冲突,我做错了什么?

【问题讨论】:

  • 这些行中的哪一行实际上是违规的来源?这应该可以使用调试器检测到。
  • 在前两个示例中,错误发生在第一行。第三次发生在第二次

标签: c++ image opencv


【解决方案1】:

我使用 boost::shared_ptr 创建了一个超级安全、自动垃圾收集、速度非常快的 IplImage 包装器。

图像结构称为 blImage,可在以下位置获得: http://www.barbato.us/2010/10/14/image-data-structure-based-shared_ptr-iplimage/

在那里你可以下载我的 blImageAPI 并开始享受 opencv 的乐趣,而不是为像素访问而烦恼。

祝你好运,享受创建图像算法的乐趣

【讨论】:

    【解决方案2】:

    这个问题可能是由

    IplImage *slice = cvLoadImage("test.png");
    

    如果函数失败,变量 slice 将为 NULL,任何进一步的取消引用都会导致访问冲突。

    由于 opencv 的 dll 可能安装在与您正在运行的应用程序不同的路径上,因此建议在调用 opencv 的函数时提供“绝对文件路径”。

    尝试将您的示例图像复制到c:\,并将您的代码更改为IplImage *slice = cvLoadImage("c:\\test.png");,我敢打赌它会像魔术一样工作:)

    编辑:

    对于奇数像素值,可能是内存内容未初始化

    【讨论】:

    • 您,好先生/女士,是我的英雄!像魅力一样工作:-)在旁注中,什么是/是“未初始化的内存内容”?
    • API cvCreateImage 只负责分配一块内存用作图像缓冲区。由于没有提示像素应该从什么值开始,因此它们处于未初始化/先前/未确定状态。
    • 啊,有道理。我仍然遇到这个问题,有解决办法吗?也许某些函数将第一个像素分配到 hte 内存的开头?
    • 您可以使用 cvZero() 将所有像素设置为 0。
    【解决方案3】:

    正如 Martin 所说,预先计算诸如基址和偏移量之类的东西,这样您就可以更轻松地了解正在发生的事情。这对于指针算术非常重要(例如,如果 img->ImgData 不是指向字节大小数据类型的指针,那么您的指针算术将完全错误。事实上,您似乎正在索引同一个数组(img->imageData)作为一个指向 uchar 的指针和一个指向 float 的指针......它是什么?)

    另外,检查输入 - 您使用的是 24bpp 还是 32bpp 测试图像? 'img' 是非空的吗? x,y 是否在像素宽度和像素高度范围内? widthStep 是否正常,并以字节表示?在你的代码中加入大量的调试断言,你就会消除很多简单错误发生的可能性。

    【讨论】:

      【解决方案4】:

      如果不知道图像的大小以及如何循环读取它的像素,就不可能知道你做错了什么。很可能您正在尝试读取图像边界之外的内容(因此,访问冲突)。

      无论如何,您都可以在代码中添加调试并查明触发此错误的确切行。

      这就是我通常如何遍历图像的像素:

      IplImage* pRGBImg = cvLoadImage(input_file.c_str(), CV_LOAD_IMAGE_UNCHANGED); 
      int width = pRGBImg->width; 
      int height = pRGBImg->height;
      int bpp = pRGBImg->nChannels; 
      for (int i=0; i < width*height*bpp; i+=bpp) 
      {
        if (!(i % (width*bpp))) // print empty line for better readability
            std::cout << std::endl;
      
        std::cout << std::dec << "R:" << (int) pRGBImg->imageData[i] <<  
                                " G:" << (int) pRGBImg->imageData[i+1] <<  
                                " B:" << (int) pRGBImg->imageData[i+2] << " "; 
      }
      

      【讨论】:

      • 感谢代码,它让我意识到我的方法比它需要的复杂得多,并启发我真正弄清楚它的作用。我尝试使用 (int) img->imageData[i] 的修改版本来查找 RGB 值,但我仍然遇到了访问冲突。因此,为了查看我是否可能搞砸了安装,我复制/粘贴了您的代码,它可以工作(没有错误),但结果可能很奇怪。我已经用更多信息更新了问题
      • @JBenson 当然,没问题。如果它对您有所帮助,请不要忘记投票。
      • 我愿意,但我只有 8 个代表)-:一旦我终于达到 15 个,我会把它放在我的待办事项列表上。注意:答案是你和 YeenFei 之间的一个折腾,但是因为他/她的代表较少,我认为他更需要它:-)
      【解决方案5】:

      试着简化一下表达式。
      获取图像数据的指针,然后计算指向该行开头的指针,然后是指向像素的指针,然后是 R、G、B 值

      【讨论】:

        猜你喜欢
        • 2011-04-21
        • 2012-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-28
        • 1970-01-01
        • 2013-05-07
        相关资源
        最近更新 更多