プロが教える店舗&オフィスのセキュリティ対策術

OpenCVのIPLimage構造体にヘッダ無しRaw画像を読み込んで表示させたいのですが、OpenCVではヘッダ無しRaw画像を直接読み込む関数がないため(cvLoadImageは対応せず)自作しなければいけません。まだCプログラムを勉強し始めたばかりなのでなかなか上手くいかなくて困っております。どなたか教えていただけませんか?ここまで作っみました。コンパイルはできますが、原画像どおり表示してくれません。扱う画像はレントゲン画像で512*512 32bit実数データです。

#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char infile[512]; /* (1) */
float *inputimg; /* (3) */
int i, j;
int mszx, mszy;
FILE *fp;
IplImage* img;
strcpy(infile,argv[1]);
mszx = atoi(argv[2]);
mszy = atoi(argv[3]);

static const char* title="display";
inputimg = (float*)malloc(mszx*mszy*sizeof(float));
if((fp=fopen(infile,"rb")) == NULL) {
printf("OPEN FAILED %s\n",infile);
exit(0);
}
fread(inputimg, sizeof(float), mszx*mszy, fp);
fclose(fp);

img = cvCreateImage(cvSize(512,512),IPL_DEPTH_32F,1);
cvSetZero(img);
for (j = 0; j < mszy; j++) {
for (i = 0; i < mszx; i++){
img->imageData[mszx * j + i] = inputimg[mszx * j + i];
}
}
cvNamedWindow(title,CV_WINDOW_AUTOSIZE);
cvShowImage(title,img);
cvWaitKey(0);
cvDestroyWindow(title);
cvReleaseImage(&img);
return 0;
}
ここまでしかできませんでした。

A 回答 (1件)

img->imageData[mszx * j + i] = inputimg[mszx * j + i];



に2つ間違いがあります。

・IplImage.imageDataはchar *型です。よって img->imageData[mszx * j + i] は char型です。
右辺のfloatとは型が違います。float→charへの(暗黙の)型変換が発生します。この場合、「小数点以下切り捨て」になります。
画像データだとすると,0.0~1.0だったりしないでしょうか?それだと、0と1にしかなりません。

・また、imageDataがchar*なのは、様々な深さ+チャンネルのデータに対応するためです。
ちょうど、mallocで char配列でサイズX * sizeof(型) 相当の領域を確保→「型」でサイズXの配列として使用、とするように。
また、横方向については、4バイト単位に揃える、という約束もあります。
そのため、「次の行」までのバイト数を示すwidthStepというメンバがあります。
Y座標=y,X座標=0のデータは imageData[y * widthStep + 0]から始まり、32Fなら +0,+1,+2,+3の4バイトがチャンネル1の要素、+4からが次の要素(マルチチャンネルだったら次のチャンネル)となります。
上の例では、yに対してwidthStepで「次」になっていないし、「隣の要素」へ+1しかずらしてません。


対処法としては
・cvSet~2Dを使う。
「遅い」とマニュアルにはありますが、リアルタイム処理するのでなければ十分に使える速度です。
http://opencv.jp/opencv-1.1.0/document/opencvref …

・float *へキャストする。
float *へキャストすれば、4*X+0,+1..としなくても Xでアクセスできます。

float * yline ;
for (j = 0; j < mszy; j++) {
yline = (float *)(img->imageData + j * widthStep) ;
for (i = 0; i < mszx; i++){
yline[i]=inputimg[mszx * j + i];

・直接読み込み
inputimgにfreadで直接書けるなら、 imgを確保したあとで、imageDataへ直接freadすることもできるはずです。




念のため、RAWデータのフォーマットがfloatの内部表現と一致しているかどうかは確認しておいた方がよいでしょう。
    • good
    • 0
この回答へのお礼

ありがとうございました!(直接読み込み)cvCreateimageで imgを確保したあとで、imageDataへ直接freadするとimgにRAWデータを読み込むことが出来ました。確認のため、読み込んだ後RAWファイル出力してimageJという画像ソフトで開くと原画と同じ画像を表示できました。ありがとうございました。
大変感謝いたします。
しかしcvNamedWindow(title,CV_WINDOW_AUTOSIZE); cvShowImage(title,img); で画像表示すると真っ白の画像になりました。この原因は何でしょうか?windowが32bit float 画像に対応していないのでしょうか?

お礼日時:2011/03/11 16:34

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!