Как преобразовать 8-битный OpenCV IplImage * в 32-битный IplImage *? - PullRequest
12 голосов
/ 27 декабря 2008

Мне нужно преобразовать 8-битный IplImage в 32-битный IplImage. Используя документацию со всего Интернета, я попробовал следующее:

// general code
img2 = cvCreateImage(cvSize(img->width, img->height), 32, 3);
int height    = img->height;
int width     = img->width;
int channels  = img->nChannels;
int step1     = img->widthStep;
int step2     = img2->widthStep;
int depth1    = img->depth;
int depth2    = img2->depth;
uchar *data1   = (uchar *)img->imageData;
uchar *data2   = (uchar *)img2->imageData;

for(h=0;h<height;h++) for(w=0;w<width;w++) for(c=0;c<channels;c++) {
   // attempt code...
}

// attempt one
// result: white image, two red spots which appear in the original image too.
// this is the closest result, what's going wrong?!
// see: http://files.dazjorz.com/cache/conversion.png
((float*)data2+h*step2+w*channels+c)[0] = data1[h*step1+w*channels+c];

// attempt two
// when I change float to unsigned long in both previous examples, I get a black screen.

// attempt three
// result: seemingly random data to the top of the screen.
data2[h*step2+w*channels*3+c] = data1[h*step1+w*channels+c];
data2[h*step2+w*channels*3+c+1] = 0x00;
data2[h*step2+w*channels*3+c+2] = 0x00;

// and then some other things. Nothing did what I wanted. I couldn't get an output
// image which looked the same as the input image.

Как видите, я действительно не знаю, что делаю. Я бы хотел узнать, но мне бы понравилось больше, если бы я мог сделать это правильно. Спасибо за любую помощь, которую я получаю!

Ответы [ 6 ]

29 голосов
/ 20 января 2009

Функция, которую вы ищете - cvConvertScale (). Он автоматически делает любое преобразование типов для вас. Вы просто должны указать, что хотите масштабировать с коэффициентом 1/255 (который отображает диапазон [0 ... 255] в [0 ... 1]).

Пример:

IplImage *im8 = cvLoadImage(argv[1]);
IplImage *im32 = cvCreateImage(cvSize(im8->width, im8->height), 32, 3);

cvConvertScale(im8, im32, 1/255.);

Обратите внимание на точку в 1/255. - для двойного деления. Без этого вы получите шкалу 0.

6 голосов
/ 27 декабря 2008

Возможно, эта ссылка может вам помочь?

Редактировать В ответ на второе редактирование ОП и комментария

Вы пробовали

float value = 0.5

вместо

float value = 0x0000001;

Я думал, что диапазон для значения цвета с плавающей точкой изменяется от 0,0 до 1,0, где 1,0 - белый.

2 голосов
/ 28 декабря 2008

Цвета с плавающей точкой изменяются от 0,0 до 1,0, а учары - от 0 до 255. Следующий код исправляет это:

// h is height, w is width, c is current channel (0 to 2)
int b = ((uchar *)(img->imageData + h*img->widthStep))[w*img->nChannels + c];
((float *)(img2->imageData + h*img2->widthStep))[w*img2->nChannels + c] = ((float)b) / 255.0;

Большое, большое спасибо Stefan Schmidt за помощь в исправлении этого!

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

Вы можете создать оболочку IplImage, используя boost :: shared_ptr и template-metaprogramming. Я сделал это и получаю автоматическую сборку мусора вместе с автоматическим преобразованием изображений из одной глубины в другую или из одноканальных в многоканальные изображения.

Я вызвал API blImageAPI, и его можно найти здесь: http://www.barbato.us/2010/10/14/image-data-structure-based-shared_ptr-iplimage/

Это очень быстро и делает код очень читабельным (хорошо для поддержки алгоритмов)

Он также может использоваться вместо IplImage в алгоритмах opencv без каких-либо изменений.

Удачи и веселья написание алгоритмов !!!

1 голос
/ 15 апреля 2009

Если вы не поставите точку (.), Некоторые компиляторы поймут, что это деление на int, что дает вам результат int (в данном случае ноль).

0 голосов
/ 07 ноября 2011

IplImage * img8, * img32;
img8 = cvLoadImage ("a.jpg", 1);

    cvNamedWindow("Convert",1);
    img32 = cvCreateImage(cvGetSize(img8),IPL_DEPTH_32F,3);
    cvConvertScale(img8,img32,1.0/255.0,0.0);

// Для подтверждения Проверьте значения пикселей (от 0 до 1)

    for(int row = 0; row < img32->height; row++ ){
                float* pt = (float*) (img32->imageData + row * img32->widthStep);
                for ( int col = 0; col < width; col++ )
                            printf("\n %3.3f , %3.3f , %3.3f ",pt[3*col],pt[3*col+1],pt[3*col+2]);                  
            }

    cvShowImage("Convert",img32);
    cvWaitKey(0);
    cvReleaseImage(&img8);
    cvReleaseImage(&img32);
    cvDestroyWindow("Convert");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...