3

我正在使用 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 的更改修复代码(如上)之后,我离得更近了一点。 是我正在使用的图像,如果有帮助的话。很难看到,但它只是一个 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

4 回答 4

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);
于 2010-10-04T22:10:22.773 回答
2

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

您在直接指针访问中得到了奇怪的值,因为您没有考虑 OpenCV 执行的字节填充。由于这个原因,您可能会在 8 位图像中找到 (width*nChannels <= 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 的建议,即您应该在尝试使用它们之前找到参考并了解该库。

于 2010-10-05T05:43:41.333 回答
1

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

于 2010-10-04T21:25:29.620 回答
1

这里有很多问题:

  • 您需要用有意义的数据填充图像
  • 根据图像的构建方式,您可能已经交换了红色和蓝色
  • 你应该使用 unsigned char red
  • 您为每个像素声明一个向量并且不使用它
于 2010-10-04T21:29:55.633 回答