2008-12-27 46 views
11

Tôi cần chuyển đổi IplImage 8 bit thành IplImage 32 bit. Sử dụng tài liệu từ khắp nơi trên web Tôi đã thử những điều sau đây:Làm thế nào để chuyển đổi một OpenCV IplImage 8-bit * thành IplImage 32-bit *?

// 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. 

Như bạn thấy tôi không thực sự biết mình đang làm gì. Tôi rất muốn tìm hiểu, nhưng tôi sẽ thích nó hơn nếu tôi có thể thực hiện điều này một cách chính xác. Cảm ơn bạn đã giúp tôi!

Trả lời

6

Có lẽ điều này link có thể giúp bạn?

Sửa Để đối phó với các chỉnh sửa thứ hai của OP và nhận xét

Bạn đã thử

float value = 0.5

thay vì

float value = 0x0000001;

Tôi nghĩ phạm vi cho một giá trị màu float đi từ 0,0 đến 1,0, wh ere 1.0 có màu trắng.

+0

Có một số thông tin thú vị trên trang đó, mẩu mã mà giải thích những gì tôi đã Tuy nhiên, kết quả cũng giống nhau. Vui lòng xem liên kết sau để biết ví dụ về sự cố xảy ra mọi lúc: http://files.dazjorz.com/cache/conversion.png – sgielen

+0

whoa, yeah, đó là tốt nhất, bạn nói đúng! Vì vậy, nó cho manh mối sau đây: cho các đốm đỏ, R là 1.0 và GB là 0.0, và cho màu trắng, cả ba đều là 1.0.Vì vậy, trong khi chuyển đổi, các giá trị RGB shoul d được chuyển đổi từ 0 đến 255 thành 0.0 thành 1.0. Thay đổi giá trị thành b/255 làm cho hình ảnh có màu đen + đỏ. – sgielen

+0

OK! int b = ((uchar *) (img-> imageData + h * img-> widthStep)) [w * img-> nChannels + 0]; // B ((float *) (img2-> imageData + h * img2-> widthStep)) [w * img2-> nChannels + 0] = ((phao) b)/255,0; – sgielen

2

Floating màu sắc điểm đi 0,0-1,0, và uchars đi từ 0 đến 255. Các mã sau sửa chữa nó:

// 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; 

Nhiều, rất nhiều nhờ vào Stefan Schmidt vì đã giúp tôi sửa lỗi này!

28

Hàm bạn đang tìm kiếm là cvConvertScale(). Nó tự động thực hiện bất kỳ chuyển đổi kiểu nào cho bạn. Bạn chỉ cần xác định rằng bạn muốn chia tỷ lệ theo hệ số là 1/255 (ánh xạ dải ô [0 ... 255] đến [0 ... 1]).

Ví dụ:

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

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

Lưu ý các dấu chấm trong 1/255. - để buộc một bộ phận kép. Nếu không có nó, bạn có thang điểm 0.

+0

Tôi đã thử điều đó, nhưng nó không chấp nhận đầu ra hoặc quy mô đầu vào. Hoặc có lẽ tôi chỉ sử dụng nó không chính xác. – sgielen

+11

Điều quan trọng là bạn vượt qua một gấp đôi là yếu tố mở rộng quy mô (đó là lý do tại sao có '.' Đằng sau 255). 1/255 sẽ đánh giá là phân chia số nguyên và dẫn đến hệ số chia tỷ lệ 0. Mã chính xác của bạn không hoạt động với cvConvertScale() là gì? – Martin

+1

Tôi ước gì tôi có thể đặt nhiều upvotes hơn, tôi upvoted bình luận của bạn và câu trả lời của bạn là tốt. Tôi đã đấu tranh về điều này trong ít nhất 8 giờ chết tiệt! – Eric

1

Nếu bạn không đặt dấu chấm (.), Một số trình biên dịch sẽ hiểu là một bộ phận int, cho bạn kết quả int (0 trong trường hợp này).

1

Bạn có thể tạo trình bao bọc IplImage bằng cách sử dụng boost :: shared_ptr và lập trình meta-template. Tôi đã làm điều đó, và tôi nhận được bộ sưu tập rác tự động, cùng với chuyển đổi hình ảnh tự động từ độ sâu này sang độ sâu khác hoặc từ một kênh sang hình ảnh đa kênh.

Tôi đã gọi blImageAPI API và nó có thể được tìm thấy ở đây: http://www.barbato.us/2010/10/14/image-data-structure-based-shared_ptr-iplimage/

Nó rất nhanh, và làm cho mã rất dễ đọc, (tốt cho các thuật toán duy trì)

Người ta cũng có thể được sử dụng thay vì IplImage trong thuật toán opencv mà không thay đổi gì cả.

Chúc may mắn và có các thuật toán viết thú vị !!!

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

// Đối với Chứng nhận Kiểm tra các giá trị pixel (từ 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"); 
Các vấn đề liên quan