C ++, Отрицательные значения RGB пикселей с использованием OpenCV - PullRequest
3 голосов
/ 05 октября 2010

Я использую 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 голосов
/ 05 октября 2010

Попробуйте это:

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);
2 голосов
/ 05 октября 2010

Я не понимаю, почему вы обращаетесь к пиксельным данным вслепую (по индексу 1D), в то время как вы уже знаете размер изображения (подтвержденный использованием IplImage::height и IplImage::width), а opencv предоставляет функцию для доступа к значению пикселя(cvGet*D).

При прямом доступе к указателю вы получаете нечетные значения, поскольку вы не учитываете заполнение байтов, выполняемое OpenCV .По этой причине вы можете найти в 8-битных изображениях (width * nChannels <= widthStep). </p>

Кратко пересмотренный код может выглядеть следующим образом:

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, который сообщает цветовую модель.

Я пойду с предложением Пола Р., что вы должны найти ссылку и понять библиотеку, прежде чем пытаться их использовать.

1 голос
/ 05 октября 2010

Довольно много вопросов здесь:

  • Вам необходимо заполнить изображение значимыми данными
  • В зависимости от того, как было построено изображение, вы могли поменять местами красный и синий
  • Вы должны использовать красный без знака
  • Вы объявляете вектор для каждого пикселя и не используете его
1 голос
/ 05 октября 2010

Я никогда не использовал OpenCV, но я бы предположил, что cvCreateImage не инициализирует содержимое изображения и, конечно, не имеет ничего значащего.

...