запись в IplImage imageData

Я хочу записать данные непосредственно в массив imageData IplImage, но не могу найти много информации о том, как он отформатирован. Меня особенно беспокоит то, что, несмотря на создание изображения с тремя каналами, на каждый пиксель приходится четыре байта.

Функция, которую я использую для создания изображения:

IplImage *frame = cvCreateImage(cvSize(1, 1), IPL_DEPTH_8U, 3);

Судя по всему, это должно создать трехканальное изображение RGB, но, похоже, это не так.

Как мне, например, записать один красный пиксель в это изображение?

Спасибо за любую помощь, это ставит меня в тупик.


person wyatt    schedule 01.08.2011    source источник
comment
stackoverflow.com/questions/6868723/   -  person karlphillip    schedule 01.08.2011
comment
Этот ответ предполагает, что на самом деле будет три бита на пиксель. Я подтвердил, что nChannels моего изображения равно 3, но для каждого пикселя все еще есть 4 бита. Что бы это ни стоило, они на самом деле не сгруппированы с пикселями. кажется, что они хранятся в конце каждой строки, и все они установлены на 0.   -  person wyatt    schedule 01.08.2011


Ответы (3)


Если вы смотрите на frame->imageSize, имейте в виду, что это frame->height * frame->widthStep, а не frame->height * frame->width.

BGR — это родной формат OpenCV, а не RGB.

Кроме того, если вы только начинаете, вам следует подумать об использовании интерфейса C++ (где Mat заменяет IplImage), так как это будущее направление, и с ним намного проще работать.

Вот пример кода, который напрямую обращается к данным пикселей:

int main (int argc, const char * argv[]) {

    IplImage *frame = cvCreateImage(cvSize(41, 41), IPL_DEPTH_8U, 3);

    for( int y=0; y<frame->height; y++ ) { 
        uchar* ptr = (uchar*) ( frame->imageData + y * frame->widthStep ); 
        for( int x=0; x<frame->width; x++ ) { 
            ptr[3*x+2] = 255; //Set red to max (BGR format)
        }
    }

    cvNamedWindow("window", CV_WINDOW_AUTOSIZE);
    cvShowImage("window", frame);
    cvWaitKey(0);
    cvReleaseImage(&frame);
    cvDestroyWindow("window");
    return 0;
}
person SSteve    schedule 01.08.2011
comment
Спасибо за это. Я, наконец, обнаружил это, будучи ослеплен тем досадным фактом, что для строк в один и два пикселя, которые я использовал при тестировании, округление строк добавляет один и два пикселя соответственно. Посмотрю мат, при просмотре показалась более непрозрачная система, но полагаю это просто незнание. - person wyatt; 01.08.2011
comment
Я не являюсь мировым авторитетом в OpenCV, но я не вижу, где Mat более непрозрачен, чем IplImage. А такие навороты C++, как перегрузка операторов, облегчают работу. Документация находится по адресу opencv.itseez.com/modules/core/doc/ basic_structures.html#mat - person SSteve; 02.08.2011

unsigned char* imageData = [r1, g1, b1, r2, g2, b2, ..., rN, bn, gn]; // n = высота*ширина рамки изображения->imageData = imageData.

Возьмите свое изображение, представляющее собой размерный массив высоты N и ширины M, и поместите его в построчный вектор длины N * M. Сделайте это типом unsigned char* для образов IPL_DEPTH_8U.

person rossb83    schedule 01.08.2011
comment
Проблема в том, что на каждый пиксель приходится четыре байта. Дополнительные байты, кажется, сгруппированы в конце каждой строки, и все они равны нулю, но я не знаю, почему. Кроме того, я не знаю, важно ли это, но изображения, похоже, хранятся в BGR, а не в RGB. - person wyatt; 01.08.2011
comment
Не уверены в дополнительных 4 байтах? Как вы это видите? В любом случае попробуйте присвоить данные изображения массиву char*. Это то, что работает для меня. Да, некоторые библиотеки С++ используют BGR, а некоторые используют RGB. Если цветовые слои выглядят переключенными при отображении, используйте cvCvtColor(frame, frame, CV_BRG2RGB) для переключения слоев R и B. - person rossb83; 01.08.2011
comment
Размер изображения последовательно равен 4 * количество пикселей. Я нашел позиции, просто распечатав массив imageData, пытаясь выяснить, как хранились данные. Во всяком случае, я попробую это. - person wyatt; 01.08.2011

Прямо к вашему ответу, окрашивая пиксель в красный цвет:

IplImage *frame = cvCreateImage(cvSize(1, 1), IPL_DEPTH_8U, 3);
int y,x;
x=0;y=0; //Pixel coordinates. Use this for bigger images than a single pixel.
int C=2; //0 for blue, 1 for green and 2 for red (BGR is the default format).
frame->imageData[y*frame->widthStep+3*x+C]=(uchar)255;
person LovaBill    schedule 20.12.2012