2016-10-07 71 views
1

我有這樣的代碼,從緩衝區1byte,8位位圖加載灰度圖像。然後它調整這個圖像。使用cvImageCreate()與灰度圖像OpenCV失敗,並調整大小通常失敗

int resizeBitmap(const unsigned char *inData, const size_t inDataLength, const size_t inWidth, const size_t inHeight, 
       const int bitDepth, const int noOfChannels, unsigned char **outData, size_t *outDataLength, const size_t outWidth, const size_t outHeight) { 

    // create input image 
    IplImage *inImage = cvCreateImage(cvSize(inWidth, inHeight), bitDepth, noOfChannels); 
    cvSetData(inImage, inData, inImage->widthStep); 

     // show input image 
     cvNamedWindow("OpenCV Input Image", CV_WINDOW_FREERATIO); 
     cvShowImage("OpenCV Input Image", inImage); 
     cvWaitKey(0); 
     cvDestroyWindow("OpenCV Input Image"); 
    /* */ 

    // create output image 
    IplImage *outImage = cvCreateImage(cvSize(outWidth, outHeight), inImage->depth, inImage->nChannels); 

    // select interpolation type 
    double scaleFactor = (((double) outWidth)/inWidth + ((double) outHeight)/inHeight)/2; 
    int interpolation = (scaleFactor > 1.0) ? CV_INTER_LINEAR : CV_INTER_AREA; 

    // resize from input image to output image 
    cvResize(inImage, outImage, interpolation); 

    /* // show output image 
     cvNamedWindow("OpenCV Output Image", CV_WINDOW_FREERATIO); 
     cvShowImage("OpenCV Output Image", outImage); 
     cvWaitKey(0); 
     cvDestroyWindow("OpenCV Output Image"); 
    */ 

    // get raw data from output image 
    int step = 0; 
    CvSize size; 
    cvGetRawData(outImage, outData, &step, &size); 
    *outDataLength = step*size.height; 

    cvReleaseImage(&inImage); 
    cvReleaseImage(&outImage); 

    return 0; 
} 

我使用這裏位深度= 8和noOfChannels = 1 加載的圖像是: enter image description here

並且輸出是: enter image description here

該輸出不總是寫爲程序通常失敗,錯誤:

OpenCV Error: Bad number of channels (Source image must have 1, 3 or 4 channels) in cvConvertImage, file /tmp/opencv-20160915-26910-go28a5/opencv-2.4.13/modules/highgui/src/utils.cpp, line 611 
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: /tmp/opencv-20160915-26910-go28a5/opencv-2.4.13/modules/highgui/src/utils.cpp:611: error: (-15) Source image must have 1, 3 or 4 channels in function cvConvertImage 

我附上de因爲我傳遞了大小爲528480(等於1字節* 1101 * 480)的灰度緩衝區,但在cvCreateImage之後,imageSize爲529920,widthStep爲1104!也許這是這張圖片的問題,但爲什麼呢?

enter image description here

+0

嗨,我已經提供了一個快速的答案,因爲它遲到了。一旦我獲得免費,會改善它。 – saurabheights

回答

1

此問題與widthstep和IplImage結構的寬度有關。 Opencv爲圖像填充4個字節的倍數。這裏opencv使用1101的寬度和1104的寬度步長。但是,當從位圖寫入IplImage時,每行寫入的額外像素很少(注意從左上角到右下角的對角線)。

請注意,圖像沒有傾斜。只是每下一行稍微向左移動(3個像素),從而給出剪切變換的想法。

也可能是您給出的寬度小於Bitmap的寬度。

請參閱docs此處並搜索填充。您可以嘗試按行逐行復制所有列數據。

爲什麼崩潰:有時opencv最終會超出位圖緩衝區讀取範圍,並可能觸及不可觸及的內存地址,從而導致異常。

注意:位圖可能還有填充,您從中收到黑色對角線。

+0

任何代碼如何以通用的方式避免此問題?灰度位圖可以是任何大小的W x H,如果每個像素都有1個字節,則不能保證每行都是4個字節的倍數。 –

+0

嘗試將'cvSetData(inImage,inData,inImage-> widthStep)'更改爲'cvSetData (inImage,inData,1101);' – saurabheights

+0

我改變了它,但它沒有幫助我使用計算值:(inWidth * noOfChannels * bitDepth)/ CHAR_BIT - >應該評估爲1101 –

1

基於回答saurabheights我已經寫了過程,使每個位圖行的填充行中的任何給定的多個字節。

int padBitmap(const unsigned char *data, const size_t dataLength, const size_t width, const size_t height, 
       const int bitDepth, const int noOfChannels, unsigned char **paddedData, size_t *paddedDataLength, const size_t row_multiple) { 


    size_t row_length = (width*noOfChannels*bitDepth)/CHAR_BIT; 
    size_t row_padding_size = row_multiple - row_length % row_multiple; 

    if(row_padding_size == 0) return 0; 

    size_t new_row_length = row_length + row_padding_size; 
    size_t newDataLength = height * new_row_length; 
    unsigned char *newData = malloc(sizeof(unsigned char) *newDataLength); 

    unsigned char padding[3] = {0, 0, 0}; 
    for(int i=0; i<height; i++) { 
     memcpy(newData + i*new_row_length, data + i*row_length, row_length); 
     memcpy(newData + i*new_row_length + row_length, padding, row_padding_size); 
    } 

    *paddedData = newData; 
    *paddedDataLength = newDataLength; 

    return row_padding_size; 
} 

現在通過位圖resizeBitmap()之前,我這樣做填充:

unsigned char *paddedData = 0; 
    size_t paddedDataLength = 0; 
    int padding = padBitmap(gData, gDataLength, width, height, PNG_BIT_DEPTH_8, GRAYSCALE_COMPONENTS_PER_PIXEL, &paddedData, &paddedDataLength, 4); 
    width += padding; 

,我使用位圖paddedData。它似乎工作正常