2008-12-27 108 views
11

我需要將8位IplImage轉換爲32位IplImage。使用來自全網的文檔我試過以下的東西:如何將8位OpenCV 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

也許這個link可以幫到您嗎?

編輯爲響應OP的第二編輯和註釋

您是否嘗試過

float value = 0.5

,而不是

float value = 0x0000001;

我以爲範圍對於float顏色值從0.0到1.0,wh 1.0是白色的。

+0

1有該網頁上的一些有趣的信息,代碼段,其解釋我所已經嘗試過了,結果是一樣的,但是請看下面的鏈接,查看一直出錯的例子: http://files.dazjorz.com/cache/conversion.png – sgielen 2008-12-27 15:45:19

+0

哇,是的,那是一個好的,你是對的!所以這給出了以下線索:對於紅點,R是1.0,GB是0.0,而對於白色,三者都是1.0。因此,在轉換時,RGB值爲d從0到255轉換爲0.0到1.0。將值更改爲b/255可使圖像變爲黑色+紅色。 – sgielen 2008-12-27 17:50:57

2

浮點顏色從0.0到1.0,並uchars從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; 

很多很多的感謝斯特凡施密特幫我解決這個問題!

28

您正在尋找的功能是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

1

如果你不把點(。)的比例,一些編譯器會明白是作爲一個int師,給你(在這種情況下,零)INT結果。

1

您可以使用boost :: shared_ptr和模板元編程創建一個IplImage包裝器。我已經做到了,我可以自動進行垃圾收集,以及從一個深度到另一個深度的自動圖像轉換,或者從單通道圖像到多通道圖像。

我已經叫API blImageAPI,它可以在這裏找到: http://www.barbato.us/2010/10/14/image-data-structure-based-shared_ptr-iplimage/

這是非常快,而且使代碼非常可讀的,(有利於維持算法)

它也可以用來而不是在opencv算法中的IplImage而不改變任何東西。

祝你好運,玩得開心寫算法!

0

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 - )

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");