开发者

C++, Access Violation using OpenCV to get RGB value of pixel

I'm trying to use OpenCV to find the RGB values of a pixel in an image. so far I've tried the following:

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];

But in all of the above, I get the same error:

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

The last hex number (0x0...48) never changes. I looks like this can be caused by writing further than the bounds of an array. So I've run each of the examples in isolation without any other code at all, and still get the same error. What is causing this error and how can I fix it?

Extra info: Windows 7, MSVC 2010 Express, OpenCV 2.1

--UPDATE--

I've realised the above code is more compicated than it needs to be, so I took the snippet provided by karlphillip (thanks!) as a base and used a similar method. I'm still getting an error, and this time in an even stranger place:

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

The error occurs on the second line, and is still an Access Violation. There is no code executed before this to do with OpenCV, just some variable initializations. 'test.png' is just a 7*7 pixel 'X' I made in paint to test this out, using a .jpg has hte saem result.

To make sure I hadn't installed OpenCV improperly, I used this code (copied from below) in isolation:

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] << " "; 
    }
}

This didn't return any errors, but I did get some possibly strange results, here are the first few lines of console output:

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

Negative RGB values? Is this to be expected, or is even this not working. If it is normal, then the image I'm loading ('test.png') must be the problem. But, what am I doing wrong if a simple request for the number o开发者_如何学编程f channels causes an access violation?


Without knowing the size of the image and how you are looping through it to read its pixels, its impossible to tell what you are doing wrong. Most probably you are trying to read beyond the image boundaries (therefore, access violation).

Anyway, you could add debugs to your code and pinpoint the exact line that triggers this error.

This is how I usually do to iterate through the pixels of an image:

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] << " "; 
}


The problem probably caused by

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

if the function failed, variable slice will be NULL, and any further dereferencing will leads to access violation.

Since opencv's dll may be installed on different path than your running application, it is advisable to provide "absolute file path" when calling opencv's function.

Try copy your sample image to c:\, and change your code into IplImage *slice = cvLoadImage("c:\\test.png");, I'd bet it will work like magic :)

Edit:

For your odd pixel values, it might caused by uninitialized memory contents


Try simplyfing the expression a little.
Get a pointer the image data, then calculate a pointer to the start of that row, then a pointer to the pixel, then the R,G,B values


As Martin says, precalculate things like your base addresses and offsets so you can more easily see what is going on. This is very important with pointer arithmetic (e.g. if img->ImgData is not a pointer to a byte-sized data type, your pointer arithmetic will be entirely wrong. Indeed, you appear to be indexing the same array (img->imageData) as both a pointer to uchar and a pointer to float...what is it?)

Also, check the inputs - Are you using a 24bpp or 32bpp test image? Is 'img' non-null? Are x,y coming in within the pixel-width and pixel-height ranges? Is widthStep sane, and expressed in terms of bytes? Stick lots of debugging ASSERTs in your code and you'll eliminate the possibility of a lot of simple errors occurring.


I have created a super safe, automatic garbage collection, very fast, IplImage wrapper using boost::shared_ptr.

The image structure is called blImage and is available at: http://www.barbato.us/2010/10/14/image-data-structure-based-shared_ptr-iplimage/

There you can download my blImageAPI and start having fun with opencv instead of sweating about pixel access.

Good luck and have fun creating image algorithms

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜