C ++,使用OpenCV的像素的负RGB值

时间:2010-10-04 21:20:34

标签: c++ image opencv rgb pixels

我正在使用OpenCV迭代图像并找到每个像素的颜色,这里是我正在使用的一些代码:

IplImage* img = cvLoadImage("c:\\test.png");

int pixels = img->height * img->width;
int channels = img->nChannels;

for (int i = 0; i < pixels*channels; i+= channels)
{

    unsigned char red = img->imageData[i + 2];
    unsigned char green = img->imageData[i + 1];
    unsigned char blue = img->imageData[i];

    outputRGBValues(red, green, blue);
    if (red == REDCOLOUR && green == GREENCOLOUR && blue == BLUECOLOUR)
    {
        count++;
    }
}
cvReleaseImage(&img);

当我运行它时,outputRGBValues输出负值。最常见的是R,G,B = -1,但偶尔还有其他负数和少数正数。我听说过未初始化的内存内容,以及没有正确分配给内存的像素。但我真的不明白它,绝对不知道如何解决它。我做错了什么,我该如何解决?

更新

使用fschmitt的更改修复代码(如上所示)后,我更接近了。 This是我正在使用的图像,如果有任何帮助的话。很难看,但它只是一个5 * 3'V'的黑色像素,底部有一个绿色像素。

在其上运行代码,我得到了这个输出:

0 0 0
255 255 255
255 255 255
255 255 255
0 0 0
255 255 186
0 0 255
255 255 0
And it continues

前5行很好,正是它们应该是什么。这是图像的第一行。下一行,第6行以后是错误的。它应该是:

255 255 255
255 255 255
0 0 0

我不确定是什么原因造成的。它如何适用于顶线而不是第二线?是否存在某种不匹配问题,并将其值偏离应有的位置左侧一点?

4 个答案:

答案 0 :(得分:4)

试试这个:

IplImage* img = cvLoadImage("c:\\test.png");

for (int i = 0; i < img->height; i++)
{
    for (int j = 0; j < img->width; j += img->nChannels)
    {
        unsigned char red = img->imageData[i * img->widthStep + j + 2];
        unsigned char green = img->imageData[i * img->widthStep + j + 1];
        unsigned char blue = img->imageData[i * img->widthStep + j];

        outputRGBValues(red, green, blue);
        if (red == REDCOLOUR && green == GREENCOLOUR && blue == BLUECOLOUR)
        {
            count++;
        }
    }
}
cvReleaseImage(&img);

答案 1 :(得分:2)

我不明白你为什么要盲目访问像素数据(通过一维索引),而你已经知道图像维度(通过IplImage::heightIplImage::width的使用证明)并且opencv确实提供了功能访问像素值(cvGet*D)。

您在直接指针访问中得到奇数值,因为您没有考虑OpenCV执行的字节填充。出于这个原因,您可以找到8位图像(宽度* nChannels&lt; = widthStep)。

快速修订的代码如下:

IplImage* img = cvLoadImage("c:\\test.png");
for(int iRow=0; iRow<img->height; ++iRow)
{
    for(int iCol=0; iCol<img->width; ++iCol)
    {
        CvScalar pixelVal = cvGet2D( img, iRow, iCol);
        unsigned char red = pixelVal.val[2];
        unsigned char green = pixelVal.val[1];
        unsigned char blue = pixelVal.val[0];

        outputRGBValues(red, green, blue);
        if (red == REDCOLOUR && green == GREENCOLOUR && blue == BLUECOLOUR)
        {
            count++;
        }
    }
}
cvReleaseImage(&img);

另外,请注意,OpenCV通常以BGR格式排列数据,可以在IplImage::channelSeq验证。 请勿与IplImage::colorModel混淆,后者告诉颜色模型。

我将与Paul R建议您在尝试使用它们之前找到参考资料并理解该库。

答案 2 :(得分:1)

我从未使用OpenCV,但我认为cvCreateImage不会初始化图像的内容,当然也不会有任何意义。

答案 3 :(得分:1)

这里有一些问题:

  • 您需要使用有意义的数据填充图像
  • 根据图像的构造方式,您可能已经交换了红色和蓝色
  • 您应该使用unsigned char red
  • 您为每个像素声明了一个矢量而不使用它