Como converter um 8-bit OpenCV IplImage * para a 32-bit IplImage *?
-
23-08-2019 - |
Pergunta
Eu preciso converter um 8-bit IplImage a um 32-bits IplImage. Usando a documentação de todo o web Eu tentei o seguinte:
// 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.
Como você vê eu realmente não sei o que estou fazendo. Eu adoraria saber, mas eu adoraria que mais se eu pudesse conseguir este feito corretamente. Obrigado por qualquer ajuda que conseguir!
Outras dicas
A função que você está procurando é cvConvertScale (). Ele automagicamente faz qualquer conversão de tipo para você. Você apenas tem que especificar que você quer escala por um fator de 1/255 (que mapeia o intervalo [0 ... 255] para [0 ... 1]).
Exemplo:
IplImage *im8 = cvLoadImage(argv[1]);
IplImage *im32 = cvCreateImage(cvSize(im8->width, im8->height), 32, 3);
cvConvertScale(im8, im32, 1/255.);
Observe o ponto em 1/255.
- para forçar uma divisão dupla. Sem ele você começa uma escala de 0.
flutuantes cores pontuais vão de 0.0 a 1.0, e uchars ir de 0 a 255. As seguintes correções de código-lo:
// 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;
Muitos, muitos graças ao Stefan Schmidt por me ajudar a corrigir isso!
Se você não colocar o ponto (.), Alguns compiladores vai entender é como uma divisão int, dando-lhe um resultado int (zero neste caso).
Você pode criar um IplImage invólucro usando boost :: shared_ptr e template-metaprogramming. Eu tenho feito isso, e eu recebo a coleta de lixo automática, juntamente com conversões de imagem automáticos de uma profundidade para outro, ou de um canal para imagens multi-canal.
chamei de blImageAPI API e pode ser encontrada aqui: http://www.barbato.us/ 2010/10 / 14 / imagem-data-estrutura baseada em shared_ptr-iplimage /
É muito rápido e código make muito legível, (bom para manter algoritmos)
É também pode ser usado em vez de IplImage em algoritmos OpenCV sem mudar nada.
Boa sorte e se divertir escrevendo algoritmos !!!
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);
// Para Confirmação Verifique os valores de pixel (entre 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");