【问题标题】:C++, Negative RGB values of pixels using OpenCVC++,使用 OpenCV 的像素的负 RGB 值
【发布时间】:2011-04-21 00:40:40
【问题描述】:

我正在使用 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

我不确定是什么原因造成的。它如何适用于第一行而不是第二行?是否存在某种不匹配,并将值取到它应该在左侧的一位?

【问题讨论】:

  • 如果红色绿色和蓝色应该是从 0 到 255,为什么要使用 int?为什么不是无符号字符?

标签: c++ image opencv rgb pixels


【解决方案1】:

试试这个:

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

【讨论】:

  • 请注意 widthstep 是 IplImage 的成员,而不是给定代码中的实例变量。
  • @YeenFei:感谢您的更正-现在进行了相应的编辑-不确定您在第二条评论中对字节对齐的意思是什么?
  • 我误认为您正在通过 nChannels 增加指针偏移量,这是一个严重的错误。删除了我的第二条回复。
【解决方案2】:

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

您在直接指针访问中得到了奇怪的值,因为您没有考虑 OpenCV 执行的字节填充。由于这个原因,您可能会在 8 位图像中找到 (width*nChannels

快速修改的代码如下:

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 的建议,即在尝试使用它们之前,您应该找到参考并理解该库。

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      这里有很多问题:

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

      【讨论】:

      • 我认为像素颜色存储为 BGR,而不是 imageData 中的 RGB?感谢您收集这些内容,我将根据更改进行编辑。
      • 这取决于你如何构建图像,但确实你是对的,默认是BGR,我编辑了答案。
      • 好的,我越来越近了。更新后,第一行像素找到正确,但是从第二行开始就错了
      • @JBenson:您访问像素数据的方法不正确,因为它没有考虑widthwidthStep 之间的差异(每行末尾可能有填充,因此区别)。推荐阅读 O'Reilly “Learning OpenCV”,其中详细介绍了此类基础知识。
      猜你喜欢
      • 1970-01-01
      • 2011-04-20
      • 2011-03-18
      • 2023-02-14
      • 1970-01-01
      • 2012-02-14
      • 2017-06-08
      • 2020-05-18
      相关资源
      最近更新 更多