• ベストアンサー

SDKにてRAW画像(ヘッダ情報0)の表示

現在RAW画像(ヘッダ情報0)の表示プログラムをSDKにて作成中です。 色々と細かな質問に対してお答えいただいた皆様に感謝します。 おかげで一応表示することができました。 しかし新たな疑問が出てきてしまいました。 詳しく説明します。 まず入力画像情報をグローバルな構造体により管理するため、 typedef struct{ unsigned char *Input_Image; int Width; int Height; HWND hwnd; char szFileName[MAX_PATH]; char szFileTitle[MAX_PATH]; LPBITMAPINFO lpBitmapInfo; HANDLE hMemBitmapInfo; HANDLE hMemInput_Image; int flag; }IMAGEINFORMATION; static IMAGEINFORMATION *Image; このように定義しました。 ちなみにこの構造体メンバの最初のメンバ*Input_Imageは入力画像が格納するポインタです。今回の問題に対しこの*Input_Imageメンバのみ注意をお願いします。 画像入力処理として Image->hMemInput_Image = GlobalAlloc(GHND, sizeof(unsigned char) * Image->Height * Image->Width); Image->Input_Image = (unsigned char *)GlobalLock(Image->hMemInput_Image); により画像情報のポインタをImage->Input_Imageに格納します。 しかし入力した情報をそのまま使用すると、表示した場合に上下さかさまに反転して表示されてしまうので、この後に画像情報の反転処理を行わなければなりません。この反転処理を行う関数をvoid ReverseBitmap(unsigned char *)として、内容を次に示します。 void ReverseBitmap(unsigned char *Input) {   int i, j, width, height;   unsigned char temp;   width = Image->Width-1;   height = Image->Height-1;   for(i=0; i<=height; i++){     for(j=0; j<=width; j++){       temp = Input[width * (height - i) + j];       Input[width * (height - i) + j] = Input[width * i + j];       Input[width * i + j] = temp;     }   } } 関数実行の記述は  ReverseBitmap(Image->Input_Image);  のように行いました。 これにより反転した配列が ReverseBitmap関数の引数に格納されていると考えたのですが、結果は反映されていませんでした。 結果として色々と試してみたのですが、どうやってもさかさまのまま表示されてしまいます。 関数への引数の渡し方、反転の仕方に問題があるようならアドバイスをお願いします。 そして、反転処理を記述した場合、2次元画像を1次元配列で操作するのは結構めんどくさいです。なのでこの上の定義をもとに、反転処理を2次元配列にて行うような方法はないでしょうか? こちらの疑問もよろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★横一列を1ブロックとして上下をミラー反転すればよい。 ・横の Image->Width バイト分のデータを CopyMemory() 関数で一括操作します。  (1)上部ラインを一時ラインにコピー  (2)下部ラインを上部ラインにコピー  (3)一時ラインを下部ラインにコピー  この3ステップで1ラインのデータを交換(反転)出来ます。 ・あとは  スキャンする上部ポインタを1ライン分だけ下に進め、  スキャンする下部ポインタを1ライン分だけ上に進めます。  そして、上部ポインタと下部ポインタが交差するときに処理を終了します。→while ( top < end ) 実装例: void ReverseBitmap( unsigned char *Input ) {  unsigned char *tmp; ←一時メモリ領域  unsigned char *top; ←上部ライン領域  unsigned char *end; ←下部ライン領域    if ( (tmp = (unsigned char *)GlobalAlloc(GPTR,Image->Width)) != NULL ){   top = &Input[ 0 ];   end = &Input[ (Image->Height - 1) * Image->Width ];      while ( top < end ){    CopyMemory( tmp, top, Image->Width );    CopyMemory( top, end, Image->Width );    CopyMemory( end, tmp, Image->Width );    top += Image->Width; ←1ライン下に進む    end -= Image->Width; ←1ライン上に進む   }   GlobalFree( tmp );  } } その他: ・StretchBlt() 関数でコピー先のサイズをマイナス指定すると反転します。  『コピー先長方形の横幅』をマイナス値に指定すると左右反転、  『コピー先長方形の高さ』をマイナス値に指定すると上下反転します。 ・この関数が使えるのならば、描画時は ReverseBitmap() でデータ反転しなくても  『生データ』のままで上下反転できます。ただし、マイナス値にしたら座標位置にも  注意して下さい。上下反転の場合は、y 座標が 0 位置ならば Image->Height の数を  y 座標に指定します。これは指定された y 座標の位置からマイナスのサイズ分上に  向かって描画することになるからです。横の場合は、x 座標に Image->Width の数を  足します。 ・つまり、  通常描画が(0,0)の座標から横100、縦80のサイズは  左右反転では(100,0)の座標から横-100、縦80のサイズで左右反転の描画となり、  上下反転では(0,80)の座標から横100、縦-80のサイズで上下反転の描画となります。  上下左右の反転では(100,80)の座標から横-100、縦-80のサイズで上下左右反転の描画となります。 ・以上。参考に!

参考URL:
http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpgdi/html/_win32_stretchblt.asp
noconan
質問者

お礼

返信ありがとうございました。 CopyMemoryという関数があることにはじめて知りました。 無知でしたね・・・・ プログラムを見れば一発でどのような動作を振舞うのか、各引数の意味など即時に理解できる簡単な関数ですね。 これからも必要に応じて使用していきたいと思います。 またStretchBlt() 関数の説明までいただきありがとうございました。

その他の回答 (2)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

画像バッファを上から下まで反転させてしまったら 元通りになりますよ 元   1234  5678 ABCD EFGH 1回目 EFGH ... B 5678 ABCD 1234 ... T 2回目 EFGH ABCD ... B 5678 ... T 1234 0ラインから2ラインまで反転させれば 元の状態の反転ですよね 3回目 EFGH 5678 ... B ABCD ... T 1234 4回目 1234 ... B 5678 ABCD EFGH ... T

noconan
質問者

お礼

返信ありがとうございました。 自分の厳密性のなさにあきれてしまいました。 確かにそうですよね・・・・・元に戻りますよね・・・・・ 頭の中では1行の入れ替えのみ完璧に動作すれば、後は全ての行で同じ処理を行えばいいと考えていたことがそもそもの失敗でしたね。 参考意見に感謝します。

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.1

# > sizeof(unsigned char) * Image->Height * Image->Width # 1点あたりsizeof(unsigned char)=1でよいのですか?256色モード? > これにより反転した配列が ReverseBitmap関数の引数に格納されていると考えたのですが、結果は反映されていませんでした。 どんな処理を書いてるか知りませんが、 マイナスの高さを指定して描画すれば反転しませんでしたっけ>ビットマップ系API メモリ上できちんと反転できてることは、デバッガ等で確認してますか? > 反転処理を記述した場合、2次元画像を1次元配列で操作するのは結構めんどくさいです。 > なのでこの上の定義をもとに、反転処理を2次元配列にて行うような方法はないでしょうか? 1ライン単位で上下反転するのでしょうから、処理効率的にも、 内側のループで1byteづつ反転する意味は薄いと思います。 memcpy等で1ラインづつ処理すればよいかと。

noconan
質問者

お礼

返信ありがとうございました。 現在作成しているのは256階調のグレースケール画像を扱うソフトなんです。 色々と参考になる情報を教えていただきありがとうございました。

関連するQ&A

  • RGB→YUV変換のプログラム

    RGB→YUV変換を行っているのですが、 うまくいきません。 以下であっているのでしょうか? //RGB > YUV変換 void RGBtoYUV(char *filename,int width,int height) { FILE *fpt,*fpt_output; unsigned char *Input,*head; unsigned char Y=0,U=0,V=0; int i,j,b_flag=1; int modification=0; modification=width%4; //ファイルのオープン fopen_s(&fpt,filename,"rb"); if(fpt==NULL) { char DebugStr[256]; wsprintf(DebugStr,"%sが存在しません",filename); MessageBox(NULL,DebugStr,"File Error",MB_OK); } else { fopen_s(&fpt_output,"YUV.bmp","wb"); //ヘッダ情報の書き込み head=(unsigned char*)malloc(54); fread(head,sizeof(unsigned char),54,fpt); fwrite(head,sizeof(unsigned char),54,fpt_output); free(head); Input=(unsigned char*)malloc(3*width*height*sizeof(unsigned char)); //メモリに展開 for(i=0;i<height;i++) { fread(&Input[i*(3*width)],sizeof(unsigned char),3*width,fpt); fseek(fpt,modification,SEEK_CUR); } fclose(fpt);//Inputファイルのクローズ for(i=0;i<3*width*height;i+=3*width) { for(j=0;j<3*width;j+=3) { Y=(unsigned char)(0.299*Input[i+j+2]+0.587*Input[i+j+1]+0.114*Input[i+j]); U=(unsigned char)(-0.169*Input[i+j+2]-0.3316*Input[i+j+1]+0.500*Input[i+j]); V=(unsigned char)(0.500*Input[i+j+2]-0.4186*Input[i+j+1]-0.0813*Input[i+j]); //Y if(Y<0) { Input[i+j]=0x00; } else if(Y>255) { Input[i+j]=0xff; } else { Input[i+j]=Y; } //U if(U<0) { Input[i+j+1]=0x00; } else if(U>255) { Input[i+j+1]=0xff; } else { Input[i+j+1]=U; } //V if(V<0) { Input[i+j+2]=0x00; } else if(V>255) { Input[i+j+2]=0xff; } else { Input[i+j+2]=V; } } }//i fseek(fpt_output,54,SEEK_SET); for(i=0;i<height;i++) { fwrite(&Input[3*width*i],sizeof(unsigned char),3*width,fpt_output); //修正値の代入 for(j=0;j<modification;j++) { fwrite("\x000",sizeof(unsigned char),1,fpt_output); } } fclose(fpt_output); free(Input); } } 又 YUV→RGBにすると元の画像に戻らずに困っています。 プログラムに対するご指摘お願いします。 このプログラムはWindowGUIで幅と高さとファイル名を入力して 走らせるプログラムです。24bpp BMPが対象です。

  • c言語でソーベルフィルタが作りたい

    c言語で画像処理のソーベルのフィルタが作りたいのですが、どうにもうまく動きません。おかしい点をご指摘していただけないでしょうか。一次元配列で作りたいです。 /*wiは読み込んだ画素値、woは書き出す画素値、m1,m2はフィルタ係数、widthは画像の幅、heightは画像の高さ*/ void sobel(unsigned char wi[], unsigned char wo[], char m1[],char m2[],int width, int height){ int i,j,k,l,z; unsigned char *w; unsigned char *wo2; w = (char*)malloc(sizeof(char)*(MW*MH)); wo2 = (char*)malloc(sizeof(char)*(MW*MH)); /*フィルタの適用*/ for(i=width+1; i<width*height; i++) wo[i]=wi[i-1-width]*m1[0]+wi[i-width]*m1[1]+wi[i+1-width]*m1[2]+wi[i-1]*m1[3]+wi[i]*m1[4]+wi[i+1]*m1[5]+wi[i-1+width]*m1[6]+wi[i+width]*m1[7]+wi[i+1+width]*m1[8]; for(j=width+1; j<width*height; j++) wo2[j]=wi[j-1-width]*m2[0]+wi[j-width]*m2[1]+wi[j+1-width]*m2[2]+wi[j-1]*m2[3]+wi[j]*m2[4]+wi[j+1]*m2[5]+wi[j-1+width]*m2[6]+wi[j+width]*m2[7]+wi[j+1+width]*m2[8]; for(k=width+1; k<width*height; k++) wo[k] = (unsigned char)sqrt(wo[k]*wo[k]+wo2[k]*wo2[k]); /*画素値を0から255に*/ for(l=width+1; l<width*height; l++){ if((unsigned char)wo[l] < 0) w[l] = 0; else if((unsigned char)wo[l] > 255) w[l] = 255; else w[l] = wo[l]; } for(z=width+1; z<width*height; z++) wo[z] = w[z]; free(w); free(wo2); } よろしくお願いしますm(_ _)m

  • OpenGL 画像のα値操作

    こんにちは。 現在、授業の一環でGLUTを用いたOpenGLのプログラムを作っています。 そのプログラムの機能の中に、読み込んだ画像のα値を記憶した後、キー操作によって表示・非表示を切り替える機能を作ろうとしています。 目的の機能自体は一応途中まで(各ピクセルのα値を255⇔0への切り替え)は作れたのですが、原理がよく分かりません。 具体的に書くと、(幅)×(高さ)×(色のチャンネル数) の画像を読み込んだのに、4倍の高さの範囲までα値に関する処理を加えないと、処理後の効果が画像全体に現れないのです。 下にプログラムの断片を張るので、わかる方がいたら解説お願いします。 出来れば、後々のために理由を知っておきたいので。 -*-*-*-*-*-*-*-*-*- /* テクスチャの情報を格納する構造体 */ typedef struct{ unsigned int name; /* 識別番号 */ unsigned char* data; /* 画像のデータ */ int width; /* 画像の幅 */ int height; /* 画像の高さ */ int channels; /* 画像の色成分の数 */ }texture; /* テクスチャ(グローバル変数) */ texture a; /* 画面表示用の関数 */ void display (void) {  /* 初期化 */ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* 透明色を描けるようにする */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  /* 描画 */ glDrawPixels(a.width, a.height, GL_RGBA, GL_UNSIGNED_BYTE, a.data); glutSwapBuffers (); } /* α値の操作(代入値がかわるだけなので、255にする方は省略) */ void alpham(void) { int i, j; for (i = 0; i < a.height * 4; ++i) { for (j = 0; j < (a.width); ++j) { a.data[(a.width * i) + (a.channels * j) +3] = 0; } } } ※画像データ の メモリ確保サイズ a.data = (unsigned char*) malloc(width * height * channels)

  • RGBをCMYKに変換するプログラム

    Windows7 VS2008 SP1 RGBからCMYKに変換するプログラムを以下の様に書いている ([詳解]画像処理プログラミング という本に載っている ソースです) のですがうまくいきません。 おそらく型の扱い??だと思うのですが・・ 具体的にどの部分を修正すればいいのかご指摘お願いします。 INPUT:24bpp raw int RawToCMYK(WCHAR *filename,int width,int height) { FILE *fpt; FILE *fpt_C,*fpt_M,*fpt_Y,*fpt_K; unsigned char *layer; unsigned char *C,*M,*Y,*K; int i,j; _wfopen_s(&fpt,filename,L"rb"); if(fpt==0x00) { MessageBox(NULL,L"RawToCMYK Error",L"RawToCMYK Error",MB_OK); return -1; } else { layer=(unsigned char*)malloc(3*width*height); C=(unsigned char *)malloc(width*height); M=(unsigned char *)malloc(width*height); Y=(unsigned char *)malloc(width*height); K=(unsigned char *)malloc(width*height); fread(&layer[0],sizeof(unsigned char),3*width*height,fpt); fclose(fpt); _wfopen_s(&fpt_C,L"RawToC.raw",L"wb"); _wfopen_s(&fpt_M,L"RawToM.raw",L"wb"); _wfopen_s(&fpt_Y,L"RawToY.raw",L"wb"); _wfopen_s(&fpt_K,L"RawToK.raw",L"wb"); for(i=0;i<3*width*height;i+=3*width) { for(j=0;j<3*width;j+=3) { C[i/3+j/3]=255-layer[i+j]; M[i/3+j/3]=255-layer[i+j+1]; Y[i/3+j/3]=255-layer[i+j+2]; K[i/3+j/3]=min3(C[i/3+j/3],M[i/3+j/3],Y[i/3+j/3]); if(K[i/3+j/3]==0xff) { C[i/3+j/3]=0x00; M[i/3+j/3]=0x00; Y[i/3+j/3]=0x00; } else { C[i/3+j/3]=(C[i/3+j/3]-K[i/3+j/3])*255/(255-K[i/3+j/3]); M[i/3+j/3]=(M[i/3+j/3]-K[i/3+j/3])*255/(255-K[i/3+j/3]); Y[i/3+j/3]=(Y[i/3+j/3]-K[i/3+j/3])*255/(255-K[i/3+j/3]); } } } fwrite(&C[0],sizeof(unsigned char),width*height,fpt_C); fwrite(&M[0],sizeof(unsigned char),width*height,fpt_M); fwrite(&Y[0],sizeof(unsigned char),width*height,fpt_Y); fwrite(&K[0],sizeof(unsigned char),width*height,fpt_K); fclose(fpt_C); fclose(fpt_M); fclose(fpt_Y); fclose(fpt_K); free(C); free(M); free(Y); free(K); return 0;

  • 1bppファイルを8bpp(raw)に変換する。

    環境 Windows7 VS2008 SP1 1bppの画像を8bppに変換しようとしているのですが うまくいきません。自分ではこれで 合っていると思うのですが・・・ 何かアドバイスお願いしますm(__)m int Main1bppTo8bpp(WCHAR *filename,int width,int height) { //width,heightは8bppになったときの幅,高さを指定する。 FILE *fpt; _wfopen_s(&fpt,filename,L"rb"); if(fpt==0x00) { MessageBox(NULL,L"1bppTo8bpp Error",L"1bppTo8bpp Error",MB_OK); return -1; } else { unsigned char *layer,*Output; layer=(unsigned char*)calloc(((width/8)+1)*height*sizeof(unsigned char),sizeof(unsigned char)); Output=(unsigned char*)malloc(width*height); //読み込み fread(&layer[0],sizeof(unsigned char),((width/8)+1)*height,fpt); FILE *fpt_output; _wfopen_s(&fpt_output,L"1bppTo8bpp.raw",L"wb"); int i,j,flag=0x00; for(i=0;i<((width/8)+1)*height;i+=((width/8)+1)) { for(j=0;j<((width/8)+1);j++) { //8bit目 if((layer[i+j]&BIT8)==BIT8) { Output[i+j+flag]=0x00; } else { Output[i+j+flag]=0xff; } //7bit目 if((layer[i+j]&BIT7)==BIT7) { Output[i+j+flag+1]=0x00; } else { Output[i+j+flag+1]=0xff; } //6bit目 if((layer[i+j]&BIT6)==BIT6) { Output[i+j+flag+2]=0x00; } else { Output[i+j+flag+2]=0xff; } //5bit目 if((layer[i+j]&BIT5)==BIT5) { Output[i+j+flag+3]=0x00; } else { Output[i+j+flag+3]=0xff; } //4bit目 if((layer[i+j]&BIT4)==BIT4) { Output[i+j+flag+4]=0x00; } else { Output[i+j+flag+4]=0xff; } //3bit目 if((layer[i+j]&BIT3)==BIT3) { Output[i+j+flag+5]=0x00; } else { Output[i+j+flag+5]=0xff; } //2bit目 if((layer[i+j]&BIT2)==BIT2) { Output[i+j+flag+6]=0x00; } else { Output[i+j+flag+6]=0xff; } //1bit目 if((layer[i+j]&BIT1)==BIT1) { Output[i+j+flag+7]=0x00; } else { Output[i+j+flag+7]=0xff; } flag=flag+8; } flag=0x00; } //最終的な「fwrite」はここでする。 fwrite(&Output[0],sizeof(unsigned char),width*height,fpt_output); free(layer); free(Output); fclose(fpt); fclose(fpt_output); } return 0;

  • 画像を読み込んでヒストグラムを作るプログラム

    2値化画像を読み込んで、ヒストグラムを表示させるプログラムを作りたいのですが、 以下のソースを作成したのですが実行中にエラーが発生して困っています。 よろしくお願いします。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> #define width 640 #define height 480 int main(int argc, char* argv[]) { unsigned char image[640*480]; unsigned char header32[1078];//ビットマップ情報 int i; int *histogram; FILE *fp1; unsigned char buffer1[640*480]; for(i=0; i<640*480; i++) { image[i]=0; buffer1[i]=0; } fp1=fopen("koshimizu1.bmp","rb"); // fread(image,1,640*480,fp1); fread(header32,1,1078,fp1); fread(buffer1,width,height,fp1); fclose(fp1); for(i=0;i<256;i++){ histogram[i]=0; } for(i=0;i<640*480;i++){ histogram[image[i]]++; } for(i=0;i<256;i++){ printf("%d %d \n",i,histogram[i]); } return 0; }

  • C言語による間引き拡大縮小

    http://csharpimage.blog60.fc2.com/blog-entry-18.html をみて、単純間引きによる拡大縮小を C言語風に書こうとしているのですが、 rescale[i+j] =layer[(int)xpos+(int)ypos];部分がよくわかりません。 24bppのRawファイル(RGB)を拡大縮小しようとしています。 rescale[i+j] =layer[(int)xpos+(int)ypos];の layer[(int)xpos+(int)ypos];部分をどうしたらいいのか悩んでいます。 layer:24bppRawを読み込むメモリ アドバイスお願い致します。m(___)m FILE *fpt_output; int width=Common_Data_Raw->width; int height=Common_Data_Raw->height; // 拡大縮小後の画像サイズ int hxSize=Common_Data_Raw->width_rescale; int hySize=Common_Data_Raw->height_rescale; // 拡大縮小用 int xSize=width; int ySize=height; double xpos, ypos; double hokanX = (double)xSize / hxSize; double hokanY = (double)ySize / hySize; unsigned char *layer,*rescale; //読み込み layer=(unsigned char*)malloc(3*width*height*sizeof(unsigned char)); fread(&layer[0],sizeof(unsigned char),3*width*height,fpt); //拡大縮小後のサイズ rescale=(unsigned char*)malloc(3*hxSize*hySize*sizeof(unsigned char)); ypos = 0.0; for (int i = 0; i < 3*hxSize*hySize; i+= 3*hxSize) { xpos = 0.0; for (int j=0;j<3*hxSize;j+=3) { // 単純補間・間引き rescale[i+j] =layer[(int)xpos+(int)ypos]; rescale[i+j+1]=layer[(int)xpos, (int)ypos]; rescale[i+j+2]=layer[(int)xpos, (int)ypos]; xpos += hokanX; } ypos += hokanY; } _wfopen_s(&fpt_output,L"output.raw",L"wb"); fwrite(&rescale[0],sizeof(unsigned char),3*width*height,fpt_output); fclose(fpt); fclose(fpt_output); free(layer); free(rescale); return 0;

  • VBAで画像処理

    以下のプログラムは、C言語で記載されたプラグラムで、画像に鏡映変換を施すプログラムです。 これを、ExcelVBAでやりたいとおもうのですが、 特に、一度Excelのセルに読みだして、そこで数字を処理してトしたいと考えています。 (単に画像Excelの機能だけをつかってを反転するだけならば、たいしたことではないので 自分で判るのですが、一度配列なりセルに画素情報を読み込む方法は、見当もつかないので 知りたいと思っています。) ということで、特に以下の(1)、(2)に注意して、ExcelVBAで下記のプログラムを変換する方法を教えてください。よろしくお願いします。 (1)特に、以下の部分の記述がどう変化するか、教えてください。 void main(void) { char input[100], output[100]; printf("入力画像ファイル名(input.bmp):"); scanf("%s", input); printf("出力画像ファイル名(output.bmp):"); scanf("%s", output); /* 画像の入力 */ readBmp(input, image_in); /* RGB24ビットカラーBMP画像を配列に格納 */ /* 画像処理 */ mirror(image_in, image_out); /* 鏡像を作る */ /* 画像の出力 */ writeBmp(image_out, output); /* RGB24ビット画像をファイルに出力 */ } (2)特に、一度BMPの画素情報を、Excelのセルに読み込めるようにしていただけると助かります。 ========= #include <stdio.h> #include <stdlib.h> /* 最大画像サイズ */ #define Y_SIZE 1280 #define X_SIZE 1280 /* BMPファイル用 */ typedef short INT2; typedef long INT4; INT2 bfType; INT4 bfSize; INT2 bfReserved1, bfReserved2; INT4 bfOffBits; INT4 biSize, biWidth, biHeight; INT2 biPlanes, biBitCount; INT4 biCompression, biSizeImage, biXPelsPerMeter, biYPelsPerMeter, biClrUsed, biClrImportant; #define HIGH 255 /* 2値画像の白 */ #define LOW 0 /* 2値画像の黒 */ #define LEVEL 256 /* 濃度レベル数 */ unsigned char image_in[Y_SIZE][X_SIZE][3]; /* 入力カラー画像配列 */ unsigned char image_out[Y_SIZE][X_SIZE][3]; /* 出力カラー画像配列 */ /* 鏡像を作る(左右逆) */ void mirror( unsigned char in[Y_SIZE][X_SIZE][3], unsigned char out[Y_SIZE][X_SIZE][3]) { int i,j,k; for (i=0; i<biHeight; i++) for (j=0; j<biWidth; j++) for (k=0; k<3; k++) out[i][j][k] = in[i][biWidth-1-j][k]; } void main(void) { char input[100], output[100]; printf("入力画像ファイル名(input.bmp):"); scanf("%s", input); printf("出力画像ファイル名(output.bmp):"); scanf("%s", output); /* 画像の入力 */ readBmp(input, image_in); /* RGB24ビットカラーBMP画像を配列に格納 */ /* 画像処理 */ mirror(image_in, image_out); /* 鏡像を作る */ /* 画像の出力 */ writeBmp(image_out, output); /* RGB24ビット画像をファイルに出力 */ }

  • 画像処理プログラム

    プログラムどう改良していいか全然わかりません 教えてください Sobel フィルタは垂直成分しか見ていないため、エッジ検出としては不十分である。任 意方向のエッジを検出するためには、図4 のような垂直方向と水平方向のオペレータを用いて各成分を抽出し、それらを合成する必要がある(図5 参照)。そこで、プログラムを次のように改良し、全方向のエッジに対応したプログラムにする。 <変更前> <変更後> c =1 􀀀2 􀀀1      cy=-1 -2 -1   cx=-1 0 1 0 0 0    →     0 0 0     -2 0 2 1 2 1          1 2 1     -1 0 1 畳み込み演算     畳み込み演算 L = c・img   →  Ly = cy・img, Lx = cx・img エッジの強さ     エッジの強さ |L|        → |L|=√Lx^2+Ly^2 /** Sobel.c **/ #include <stdio.h> #include <stdlib.h> #define V_width 320 #define V_height 240 #define amp 1.0 int d[9]; int i, j, dat; float L; unsigned char img [V_height][V_width]; /* input image */ unsigned char work[V_height][V_width]={0}; /* work space */ /******* filter coefficients *******/ static int c[9] = {-1, -2, -1, 0, 0, 0, 1, 2, 1}; /*************************************/ int main(int argc, char *argv[]) { FILE *fpi, *fpo; unsigned char data; char str[256]; int width, height; /* check arg number */ if (argc != 3) { fprintf(stderr, "Usage: %s [input] [output]\n", argv[0]); exit(1); } /* open input file */ if ((fpi = fopen(argv[1], "rb")) == NULL) { fprintf(stderr, "input file open error!\n"); exit(1); } /* open output file */ if ((fpo = fopen(argv[2], "wb")) == NULL) { fprintf(stderr, "output file open error!\n"); exit(1); } /* read PGM header */ while(1){ fgets(str, 256, fpi); if(str[0] == '#'){ fprintf( stderr, "%s", str); } else if( !strncmp( str, "P5", 2)){ fprintf( stderr, "This file is a PGM file.\n"); } else if( !strncmp( str, "255", 3)){ fprintf( stderr, "The file is opened.\n"); break; } else{ sscanf( str, "%d %d", &width, &height); fprintf( stderr, "SIZE: %3d x %3d\n", width, height); } } /* read data */ for (i=0; i<height; i++) { for (j=0; j<width; j++) { fread( &data, 1, 1, fpi); img[i][j] = data; } } /* image processing */ for (i=1; i < height-1; i++) { for (j=1; j < width-1; j++) { d[0]=img[i-1][j-1]; d[1]=img[i-1][j]; d[2]=img[i-1][j+1]; d[3]=img[i][j-1]; d[4]=img[i][j]; d[5]=img[i][j+1]; d[6]=img[i+1][j-1]; d[7]=img[i+1][j]; d[8]=img[i+1][j+1]; L = (float)(c[0]*d[0] + c[1]*d[1] + c[2]*d[2] + c[3]*d[3] + c[4]*d[4] + c[5]*d[5] + c[6]*d[6] + c[7]*d[7] + c[8]*d[8]); L = amp*L; dat = (int)(L); if (dat < 0) dat = -dat; if (dat > 255) dat = 255; work[i][j] = (unsigned char)dat; } } /* write data */ fprintf(fpo,"P5\n %d %d\n 255\n", width, height); for (i= 0; i<height; i++) { for (j= 0; j<width; j++) { fwrite( &work[i][j], 1, 1, fpo); } } fclose(fpi); fclose(fpo); return 0; }

  • 画像処理プログラム

    以下の問題でプログラムを改良したのですが合っていますか?間違ってたら教えてください 図3 は、画像中の全ての画素に対する、濃度値の頻度分布を示すヒストグラムの例である。サンプルプロググラムhistogram.c をもとに、入力画像の濃度値のヒストグラムを作成するプログラムを完成させる。 1. Histogram.c をそのまま実行すると、ダミーデータを用いた結果画像が出力される。 $ gcc □ Histogram.c -o □ Histogram ↓ $ ./Histogram ○○○.pgm □ Histogram.pgm ↓ 2. Histogram.c を次のように変更し、プログラムを完成させる。 (a)入力画像のヒストグラムを求める。 各画素を参照し、その画素値img[i][j] に対応する番号の配列histogram[0255] の値を1 増やす。 (b)頻度の最大値を求める。 濃度値i=0255 について調べ、もし頻度histogram[i] の値がそれまでの最大値max frequency より大きければ、最大値max frequency を更新する。 (c)ヒストグラム画像を作成する。 最大頻度を1 としたときの割合(histogram[i]/max frequency)を求め、それに画像の大きさH_height を掛けることで各濃度値のグラフの長さlength を求める。 length = H height * histogram[i] / max frequency #include <stdio.h> #include <stdlib.h> #define V_width 320 #define V_height 240 #define amp 1.0 #define GLEVEL 256 /* 最大階調 */ #define MAX_BRIGHTNESS 255 #define H_width GLEVEL #define H_height 256 int d[9]; int i, j, dat; float z, zz; unsigned char img [V_height][V_width]; /* input image */ unsigned char work[H_height][H_width]={0}; /* work space */ long int histogram[GLEVEL]={0}; /* ヒストグラム */ long int max_frequency=0; /* 頻度の最大値 */ float length; /* 頻度を表すグラフの長さ */ int main(int argc, char* argv[]) { FILE *fpi, *fpo; unsigned char data; char str[ 256]; int width, height; /* check arg number */ if (argc != 3) { fprintf(stderr, "Usage: %s [input] [output]\n", argv[0]); exit(1); } /* open input file */ if ((fpi = fopen(argv[1], "rb")) == NULL) { fprintf(stderr, "input file open error!\n"); exit(1); } /* open output file */ if ((fpo = fopen(argv[2], "wb")) == NULL) { fprintf(stderr, "output file open error!\n"); exit(1); } /* read PGM header */ while(1){ fgets(str, 256, fpi); if(str[0] == '#'){ fprintf( stderr, "%s", str); } else if( !strncmp( str, "P5", 2)){ fprintf( stderr, "This file is a PGM file.\n"); } else if( !strncmp( str, "255", 3)){ fprintf( stderr, "The file is opened.\n"); break; } else{ sscanf( str, "%d %d", &width, &height); fprintf( stderr, "SIZE: %3d x %3d\n", width, height); } } /* read data */ for (i=0; i<height; i++) { for (j=0; j<width; j++) { fread( &data, 1, 1, fpi); img[i][j] = data; } } /* (a) 入力画像のヒストグラムを求める */ for(i=0; i<height; i++){ for(j=0; j<width; j++){ // histogram([i][j])++; } } /* (b) 頻度の最大値を求める */ for ( i=0; i<GLEVEL; i++) { // if (histogram[i]>max_frequency) max_frequency = histogram[i]; } /* (c) ヒストグラム画像を作成する */ for (j=0; j<H_width; j++) { length = (float) H_height * j / H_width; //仮のデータ for (i=0; i<length; i++) { work[H_height-1-i][j] = MAX_BRIGHTNESS; length = H_height * histogram[i] / max_frequency } } /* write data */ fprintf(fpo,"P5\n %d %d\n 255\n", H_width, H_height); for (i= 0; i<H_height; i++) { for (j= 0; j<H_width; j++) { fwrite( &work[i][j], 1, 1, fpo); } } fclose(fpi); fclose(fpo); return 0; }

専門家に質問してみよう