Как преобразовать 8-битный OpenCV IplImage* в 32-битный IplImage*?

StackOverflow https://stackoverflow.com/questions/394488

Вопрос

Мне нужно преобразовать 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.

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

Это было полезно?

Решение

Возможно, это связь могу помочь тебе?

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

Попытался ли ты

float value = 0.5

вместо

float value = 0x0000001;

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

Другие советы

Функция, которую вы ищете, — 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.

Цвета с плавающей запятой варьируются от 0,0 до 1,0, а символы uchar — от 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;

Большое, большое спасибо Стефан Шмидт за то, что помог мне это исправить!

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

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

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

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

Его также можно использовать вместо IplImage в алгоритмах opencv, ничего не меняя.

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

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");
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top