2016-10-07 18 views
1

バッファ1byte、8bitビットマップからグレースケールイメージをロードするコードがあります。次に、このイメージのサイズを変更します。 enter image description hereグレースケールイメージでcvImageCreate()を使用したOpenCVが失敗し、通常サイズ変更に失敗する

と出力は次のようになります:私はここにビット深度= 8とnoOfChannels = 1 ロードされたイメージを使用しています

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

がある 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私は1バイト* 1101 * 480に等しいサイズ528480のグレースケールバッファを渡しているので興味深い状況がありますが、cvCreateImageの後には内部画像サイズ529920、幅ステップ1104です!多分、この画像の問題はありますが、それはなぜですか?

enter image description here

+0

こんにちは、私はそれが遅れているので、簡単な答えを提供しました。私は無料になるとそれを改善します。 – saurabheights

答えて

1

この問題はwidthstepやIplImageへの幅に関係しています。 Opencvは画像を埋め込み、4バイトの倍数の幅のステップを持つようにします。ここでopencvは1101の幅と1104のwidthstepを使用しています。しかし、ビットマップからIplImageに書き込まれたデータは、行ごとに余分なピクセルが書き込まれることはありません(左上から右下に対角線を書きます)。

画像が傾いていないことに注意してください。次の行が少し左に(3ピクセルだけずらされて)ずれるので、せん断変換のアイデアが得られます。

ビットマップが保持する幅よりも小さい幅を指定している可能性もあります。

ここで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私は各ビットマップ行の任意の多重度のバイトにパディングを行う手順を書いています。

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として使用しています:

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()にビットマップを渡す前に、私はこのパディングをしています。それは正しく動作するようです。

関連する問題