C++ C++;,使用OpenCV获取像素的RGB值的访问冲突

C++ C++;,使用OpenCV获取像素的RGB值的访问冲突,c++,image,opencv,C++,Image,Opencv,我正在尝试使用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-

我正在尝试使用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(谢谢!)提供的代码片段为基础,使用了类似的方法。我仍然有一个错误,这次在一个更陌生的地方:

IplImage *slice = cvLoadImage("test.png");
int bpp = slice ->nChannels;
错误发生在第二行,仍然是访问冲突。在此之前,没有执行与OpenCV相关的代码,只有一些变量初始化。”“test.png”只是一个7*7像素的“X”,我在画作中用一个.jpg来测试这个结果

为了确保我没有错误地安装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] << " "; 
    }
}

负RGB值?这是意料之中的事,还是根本不起作用。如果是正常的,那么我正在加载的图像('test.png')一定是问题所在。但是,如果一个简单的通道数请求导致访问冲突,那么我做错了什么呢?

尝试将表达式简化一点。

获取一个指向图像数据的指针,然后计算一个指向该行开头的指针,然后计算一个指向像素的指针,然后计算R、G、B值

如果不知道图像的大小以及如何循环读取图像中的像素,就无法判断出您做错了什么。最可能的情况是,您试图读取超出图像边界的内容(因此,访问冲突)

无论如何,您可以向代码中添加调试,并精确定位触发此错误的确切行

这是我通常对图像像素进行迭代的方式:

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] << " "; 
}
IplImage*pRGBImg=cvLoadImage(input_file.c_str(),CV_LOAD_IMAGE_不变);
int width=pRGBImg->width;
int height=pRGBImg->height;
int bpp=pRGBImg->nChannels;
对于(int i=0;istd::cout正如Martin所说,预先计算诸如基址和偏移量之类的内容,以便更容易地看到发生了什么。这对于指针算法非常重要(例如,如果img->ImgData不是指向字节大小的数据类型的指针,那么指针算法将完全错误。实际上,您似乎在为同一数组编制索引(img->imageData)作为指向uchar的指针和指向float的指针……这是什么?)


此外,请检查输入-您使用的是24bpp还是32bpp测试映像?'img'是否非空?'x,y是否在像素宽度和像素高度范围内?宽度步长是否正常,并以字节表示?在代码中插入大量调试断言,您将消除发生大量简单错误的可能性。

问题在于巧妙地由

IplImage *slice = cvLoadImage("test.png");
如果函数失败,变量
slice
将为空,任何进一步的解引用都将导致访问冲突

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

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

编辑:


对于奇数像素值,它可能是由未初始化的内存内容引起的。我使用boost::shared\u ptr创建了一个超级安全、自动垃圾收集、非常快速的IplImage包装

图像结构称为blImage,可在以下位置获得:

在那里,你可以下载我的blImageAPI,开始享受opencv带来的乐趣,而不用为像素访问而焦头烂额


祝你好运,创建图像算法玩得开心

这些行中的哪一行实际上是违规的来源?这应该可以通过使用调试器来检测。在前两个示例中,错误发生在第一行。在第三个示例中,错误发生在第二行感谢代码,它让我意识到我的方法比以前复杂得多它确实需要,并且启发了我去弄清楚它到底做了什么。我试图使用(int)img->imageData[I]的修改版本来查找RGB值,但仍然遇到访问冲突。因此,为了看看我是否可能搞砸了安装,我复制/粘贴了你的代码,它就工作了(没有错误)但可能会有奇怪的结果。我更新了更多的问题info@JBenson当然,没问题。如果这对你有帮助的话,别忘了投赞成票。我会的,但我只有8个代表):等我到了15岁,我会把它放在我的待办事项清单上。注意:答案是你和YeenFei之间有一个tossup,但因为他/她代表较少,我想他更需要它e:-)你,好先生/女士,是我的英雄!像一个符咒一样工作:-)在旁注上,“未初始化的内存内容”是什么?API cvCreateImage仅负责分配用作图像缓冲区的内存块。由于没有关于像素应以什么值开始的提示,因此它们处于未初始化/先前/未确定状态。啊,这是有道理的。我仍在处理此问题,是否有解决方案?可能是某个函数允许将第一个像素设置为内存的开始?可以使用cvZero()将所有像素设置为0。
IplImage *slice = cvLoadImage("test.png");