• 締切済み

C++画像処理に困っています。。

#include<iostream> #include<fstream> using namespace std; int main() { char outfile[]="256x256x100.bin";     ifstream fin(outfile, ios::in| ios::binary); ofstream fout; if(!fin){ cout << "ファイル1はオープンできません。endl"; return 1; } } const int SIZE=256; const int SLICE=100; signed short int* matrix= new signed short int[(SIZE)*(SIZE)*(SLICE)]; for(int i=0; i<SIZE*SIZE*SLICE; i++){ fin.read((char*) &matrix[i],sizeof(signed short int)); cout << matrix[i]; } delete[] matrix; fin.close(); fout.close(); return 0; } 上のように256x256x100の三次元データ(XxYxZ)を読み込む事ができ、256 pixelx256 pixelの画像が100枚表示することが出来ました。 次に、その画像データをXZ軸方面から見た画像データにしたいのですが、どのようにすればいいのでしょうか? たぶんY方向のデータを足し算して平均を求めればよいとは思うのですが、 プログラミング初心者なので、処理の方法が全く思い浮かびません。 どなたか教えて頂けますでしょうか?

みんなの回答

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.5

 デバッグはしていませんがソースを見た感じ次の問題があります。  ・inでファイルから読み取っていますが,それを何もしていません。  ・またmatrixには何にも入っていないので何も処理出来ません。  本来はmatrixにinを代入する処理が必要なのでしょう。 ☆改善案を提示します。 【変更前】 signed short int (*in)[SIZE][SIZE]= new signed short int[SLICE][SIZE][SIZE]; 【変更後】 double (*matrix)[SIZE][SIZE]=new double[SLICE][SIZE][SIZE]; 【変更前】 for(int xx=0; xx<SIZE; xx++){ fin.read((char*) &in[zz][yy][xx], sizeof(signed short int)); //256x256x100_int16binの読込 } 【変更後】 for(int xx=0; xx<SIZE; xx++){ signed short int item; fin.read((char*) &item, sizeof(signed short int)); //256x256x100_int16binの読込 matrix[zz][yy][xx] = (double)item; // short → doubleへ変換 } 【変更前】 //256x256x100→256x100x256の配列に格納する double (*out)[SLICE][SIZE]=new double[SIZE][SLICE][SIZE]; double (*matrix)[SIZE][SIZE]=new double[SLICE][SIZE][SIZE]; 【変更後】 //256x256x100→256x100x256の配列に格納する double (*out)[SLICE][SIZE]=new double[SIZE][SLICE][SIZE]; //double (*matrix)[SIZE][SIZE]=new double[SLICE][SIZE][SIZE];

momoharata
質問者

お礼

すみません!無事解決できました。 今度は、別の配列に格納する方法でも試してみたいと思います。

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.4

>>out[zz][yy][xx] = matrix[3-1-yy][zz][xx]; >の部分で3-1-yyとなるということがなかなか理解出来ません。 >どのように考えたらよいのでしょうか? ・「3-1-yy」は「2-yy」でも問題ありませんが「5x5x3の配列をサンプルにしていますが256x256x100の配列でも数字を置換することで対応出来ます」と書いたので,3の部分を100に置換して「100-1-yy」として動作出来るように計算式を分けています。本来3はdefineまたはconstの定数とすべきです。 ・「2-yy」でもなぜと思うのであれば,添付画像右側を見て下さい,左から右へ,上から下へピクセルを取得する場合,(x,y,z)=(0,0,2)から(4,0,0)へ順に行う為,zだけを見ると初期値z=2から1引いていき0までのループになります。ループ内の複写先で使うyyが0から2まで加算されていくのでそれを利用してzの値を作っています。

momoharata
質問者

補足

#include <iostream> #include <fstream> #include <iomanip> using namespace std; int main() { char outfile[]="256x256x100_int16bin"; ifstream fin(outfile, ios::in| ios::binary); if(!fin){ cout << "256x256x100_int16binはオープン出来ません。endl"; return 1; } ofstream fout; fout.open("Projection.bin", ios::out|ios::binary|ios::trunc); if(!fout){ cout << "Projection.binはオープン出来ません。endl"; return 1; } const int SIZE=256; const int SLICE=100; signed short int (*in)[SIZE][SIZE]= new signed short int[SLICE][SIZE][SIZE]; for(int zz=0; zz<SLICE; zz++){ for(int yy=0; yy<SIZE; yy++){ for(int xx=0; xx<SIZE; xx++){ fin.read((char*) &in[zz][yy][xx], sizeof(signed short int)); //256x256x100_int16binの読込 } } } //256x256x100→256x100x256の配列に格納する double (*out)[SLICE][SIZE]=new double[SIZE][SLICE][SIZE]; double (*matrix)[SIZE][SIZE]=new double[SLICE][SIZE][SIZE]; for(int zz=0; zz<SIZE; zz++){ for(int yy=0; yy<SLICE; yy++){ for(int xx=0; xx<SIZE; xx++){ out[zz][yy][xx]=matrix[SLICE-1-yy][zz][xx]; } } } //256x256x100配列からXZ軸から256x100の配列にY軸の平均を格納する方法 double avg[SLICE][SIZE]; memset(avg, 0, sizeof(avg)); //初期化 for(int zz=0; zz<SIZE; zz++){ for(int yy=0; yy<SLICE; yy++){ for(int xx=0; xx<SIZE; xx++){ avg[yy][xx]+=matrix[SLICE-1-yy][zz][xx]; } } } for(int yy=0; yy<SLICE; yy++){ for(int xx=0; xx<SIZE; xx++){ avg[yy][xx]/=SIZE; //合計÷要素数 cout << avg[yy][xx]; fout.write((char*)&avg[yy][xx], sizeof(double)); } } fin.close(); fout.close(); delete[] in; delete[] out; delete[] matrix; return 0; } アドバイス通り256x256x100の配列でトライしてみたのですが、出力される数字が全部同じ数字になってしまい、きちんと出力されてないように思われます。動的メモリの確保の仕方がまずいのではないかと疑っているのですが、まだきちんと理解していないため上手くいきません。 もしよろしければ、アドバイスください! よろしくお願いします。

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.3

配列の考え方についてサンプルを貼っておきます。 その2 //5x5x3→5x3x5の配列に格納する方法 int out[5][3][5]; for (zz=0;zz<5;zz++) { for (yy=0;yy<3;yy++) { for (xx=0;xx<5;xx++) { out[zz][yy][xx] = matrix[3-1-yy][zz][xx]; } } } //5x5x3配列からXZ軸から5x3の配列にY軸の平均を格納する方法 long avg[3][5]; memset(avg, 0, sizeof(avg)); // 初期化 for (zz=0;zz<5;zz++) { for (yy=0;yy<3;yy++) { for (xx=0;xx<5;xx++) { avg[yy][xx] += matrix[3-1-yy][zz][xx]; } } } for (yy=0;yy<3;yy++) { for (xx=0;xx<5;xx++) { avg[yy][xx] /= 5; // 合計÷要素数 } } ☆avgに小数までの精度が必要ならlongではなくdoubleで宣言が必要です。 ☆5x5x3の配列をサンプルにしていますが256x256x100の配列でも数字を置換することで対応出来ます。

momoharata
質問者

お礼

なるほど!図を見ながらの解説で、大変良く理解することができました。 本当に助かります。どうもありがとうございました。

momoharata
質問者

補足

>out[zz][yy][xx] = matrix[3-1-yy][zz][xx]; の部分で3-1-yyとなるということがなかなか理解出来ません。 どのように考えたらよいのでしょうか?

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.2

配列の考えたについてサンプルを貼っておきます。

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.1

とりあえず考え方を確認したい為,どんな配列での結果を求めているのか提示してください。

この投稿のマルチメディアは削除されているためご覧いただけません。

関連するQ&A

  • 動的メモリの確保の仕方を教えて下さい。

    プログラミングの初心者なのですが、現在256x256x100のバイナリファイルを読み込もうとしているのですが、下のように書くとエラーになってしまいます。動的メモリの確保を行えば、上手くいくと思うのですが。。どなたか教えて頂けないでしょうか?どうぞよろしくお願いします。 const short int SIZE=256; const short int SLICE=100; signed short int matrix[SLICE][SIZE][SIZE]; for(int i=0; i<SLICE; i++){ for(int j=0;j <SIZE; j++){ for(int k=0;k<SIZE; k++){ fin.read((char*) &matrix[i][j][k],sizeof(signed short int)); cout<< matrix[i][j][k]<<endl; } } }

  • 三次元配列の動的メモリの確保?

    const int SLICE=2; const int SIZE=256; signed short int *matrix=new signed short int[SLICE][SIZE][SIZE]; for(int i=0; i<SLICE; i++){ for(int j=0; j<SIZE; j++){ for(int k=0; k<SIZE; k++){ fin.read((char*) &matrix[SLICE][SIZE][SIZE],sizeof(signed short int)); } } } delete[] data; 三次元データを読み込むために、三次元配列を使って読み込もうとしたのですが、上手く読み込めません。 三行目の所で、error C2440: '初期化中' : 'short (*)[256][256]' から 'short *' に変換できません。 七行目の所で、error C2109: 配列または、ポインタでない変数に添字が使われました。 というエラーがでます。動的メモリの確保の仕方がまずいのでしょうか? どなたか教えて頂けますでしょうか?よろしくお願いします。

  • 100x100x100のファイルの読み込み方

    プログラミング全くの初心者なのですが、 100x100x100の整数で表されたファイルを読み込む場合、 #include<iostream> #include<fstream> using namespace std; int main(){ ifstream fin; fin.open("100x100x100.txt"); int matrix[100][100][100]; const int SIZE=100; for(int i=0; i<SIZE; i++){ for(int j=0; j<SIZE; j++){ for(int k=0; k<SIZE; k++){ fin>> matrix[i+1][j+1][k+1]; } } } fin.close(); return 0; } としてファイルを読み込んでいるのですが、他に良い方法はないでしょうか?最終的には、読み込んだファイルの各列ごとの平均値をとりたいと思っています。 誰かご教授お願いします。

  • カラー画像からグレースケール画像フォーマットの変換

    カラー画像からグレースケール画像フォーマットの変換するプログラムなんですが、いまいち理解できていません。 プログラムはRGB構造体を使ってのものなんですが添削お願いいたします。 #include<stdio.h> #include<stdlib.h> typedef struct _RGB { unsigned char r; unsigned char g; unsigned char b; } RGB; int main(int argc, char *argv[]) { int x, y; unsigned char *in, *out; int i, j, Magic, level; unsigned char tmp[255]; RGB **pixels; int width = 255; int height = 255; int size = width * height; FILE *fin, *fout; if(argc != 3){ printf("Usage : %s input outpu \n", argv[0]); exit(1); } fin = fopen(argv[1], "rb"); fgets(tmp, 255, fin); if(tmp[0] != 'P'){ return 0; } sscanf(tmp, "P%d", &Magic); if(Magic < 1 || Magic > 6){ return 0; } do{ fgets(tmp, 255, fin); } while(tmp[0] == '#'); sscanf(tmp, "%d %d", &x, &y); if(x < 1 || y < 1){ return 0; } fgets(tmp, 255, fin); sscanf(tmp, "%d", &level); printf("P%d\n", &Magic); printf("%d %d\n", x, y); printf("%d\n", level); in = (unsigned char *)malloc(sizeof(unsigned char) *x*y); fread(in, sizeof(unsigned char), x*y, fin); pixels = (RGB**)malloc(width*sizeof(RGB*)); pixels[0] = (RGB* )malloc(size * sizeof(RGB)); for(i = 1; i < width; i++){ pixels[i] = pixels[i - 1] + height; } free(pixels[0]); for(i = 1; i < width * height * 3; i++){ out[i] = pixels[i][0].r * 0.299 + pixels[i][1].g * 0.587 + pixels[i][2].b * 0.114; } fout = fopen(argv[2], "wb"); fprintf(fout,"P%d\n",Magic); fprintf(fout,"# My new PGM\n"); fprintf(fout,"%d %d\n",x, y); fprintf(fout,"%d\n",level); fwrite(out, sizeof(unsigned char),x*y, fout); free(pixels); free(in); free(out); free(fin); free(fout); }

  • ファイル入出力で

    現在ファイル入出力の項目をしているのですが、以下の内容で実行すると エラーが出てどうしても実行できません。主にどこを直せばいいのでしょうか? /* ファイルをコピーするプログラム */ #include <stdio.h> int main(void) { FILE *fin, *fout; char infile[40], outfile[40]; char str[256]; printf("コピー元ファイル = "); scanf("%39s", infile); printf("コピー先ファイル = "); scanf("%39s", outfile); if( (fin = fopen(infile, "r") ) == NULL) { printf("Input file open error.\n"); return 1; } if( (fout = fopen(outfile, "w") ) == NULL) { printf("Output file open error.\n"); fclose(fin); return 1; } while(fgets(str, sizeof(str), fin) != NULL) { fputs(str, fout); } fclose(fin); fclose(fout); return 0; } エラーは FILE 、fin, fout,NULLの未定義です。 よろしくお願いします。

  • C++の関数テンプレートで分からないところがあります。

    C++の関数テンプレートで分からないところがあります。 C++の入門書を読んで勉強しているのですが、その演習問題(答えはついてないです)で、以下のような問題がありました。 ----------------------------------------------------- 配列の全要素の最小値を求める関数テンプレートを作成せよ。 teplate <class Type> Type minof(const Type x[], int n); という形で作ること。 なお、最も小さい文字列を求められるようにするために、const char *型に明示的に特殊化したものも合わせて作成すること。 ------------------------------------------------ という問題なのですが、これにたいして僕は以下のように答えました。ヘッダのインクルードなどは省きます。 template<class Type> Type minof(const Type x[], const int n) {     int min = 0;     for(int i = 1; i < n; i++)         if(x[min] < x[i])             min = i;     return x[min]; } template<> const char* minof<const char *>(const char x[][64], const int n) {     int min = 0;     for(int i = 1; i < n; i++)         if(strcmp(x[min], x[i]) < 0)             min = i;     return x[min]; } int main() {     const int n = 5;     int a[n];     char s[n][64];     for(int i = 0; i < n; i++){         cout << i + 1 << "番目---";         cin >> a[i];     }     cout << "文字列\n";     for(int i = 0; i < n; i++){         cout << i + 1 << "番目---";         cin >> s[i];     }     cout << "整数の最小値---" << minof(a, n) << "です\n";     cout << "文字列の最小値---" << minof<const char *>(s, n) << "です\n"; } これをコンパイルすると、エラーで 明示的な特殊化; 'const char *minof<const char*>(const char [][64],const int)' は関数テンプレートの特殊化ではありません と 'minof' : 1 番目の引数を 'char [5][64]' から 'const char *const []' に変換できません。 とでてしまいます。 色々探してみたのですが、解決できませんでした・・。 特に最初のほうのエラーがよくわかりません。ちゃんと特殊化してる気はするのですが・・。 間違っている箇所の正当を載せていただけるとわかりやすくて、ありがたいです。 よろしくお願いします!

  • ファイル中のデータの読むとき・・・・

    こんにちは。ファイルにあるテキストデータを用意してそれを読み込んでいって、処理をするというプログラム書いてるんですけど、たとえば 大まかな構造として、 int fncCheck(char*pch,char item) { int count=0; int i=0; for(i=0;i<strlen(pch);i++) {if(pch[i]==item) { count++; } } return count; } int main() { FILE *fin,*fout;  //ここでいろいろ宣言 if((fin=fopen("Thermoplasmaacidophilum ","r"))==NULL) { cout<<"No files exist in current directory!\n"; exit(-1); } if((fout=fopen("Thermoplasmaacidophilum _out","wb"))==NULL) { cout<<"Output file can't open!\n"; exit(-1); } if((fin=fopen("Thermoplasmaacidophilum ","r"))!=NULL) { fwrite(SMF_header,14,1,fout); fwrite(SMF_firsttrack,36,1,fout); fwrite(SMF_track,13,1,fout); do {    //ここにdoに関する処理 } while(numread==100); while(c=fscanf(fin,"%c",c)!=EOF) {   //ここに処理をずらずら } printf("There are %d bases!!\n",n); fclose(fin); fclose(fout); } return 0; } ・・・のように書くと、一つ目のdo-while文は実行されるんですが、二つ目のwhile文が実行されません。一回目でファイルのデータを最後まで読んでるので、元にもどってもう一回やってくれないんでしょうか?初心者なものでそこらへんがよくわかんないんですが・・。どなたか助けてください。

  • c++について

    入力した値が123または456で一致したら一致と表示したいのですがどうfor文を回すか分かりません。 ご助力願います_(._.)_ class N { bool hit(const char* a[],const char* b) {   for(int i=0;i<*a[i];i++) if(*a[i]!=b[i]) { return false; } return true ; } public: N() { const char* a[ ]={ "123","456"}; char b[4]; int num; cin>>num; sprintf_s(b, 4, "%03d", num); if(hit(a,b)) cout<<"一致"; else cout<<"不一致"; } };

  • C++ ソートのやり方

    僕が作ったプログラムで、これはバブルソートなのかわからないので教えてください。 また、ほかのソートの仕方も教えてください。 よろしくお願いします。 汎用関数を使っているのでわかりにくいかもしれないですがお願いします。 #include <iostream> using namespace std; template <class X>void Sort(X *data, int size) { X temp; for (int i = 0; i < size; i++){ for (int j = i + 1; j < size; j++){ if (data[i]>data[j]){ temp = data[i]; data[i] = data[j]; data[j] = temp; } } } } int main() { int i[10]{1, 4, 3, 5, 2, 10, 2, 7, 6, 8}; char c[10]{'c', 'b', 'z', 'a', 'x', 'y', 'j', 'n', 'm', 'r'}; Sort(c, 10); Sort(i, 10); for (int j = 0; j < 10; j++){ cout << i[j] << ' '; } cout << endl; for (int j = 0; j < 10; j++){ cout << c[j] << ' '; } cout << endl; getchar(); return 0; }

  • 文字列検索について

    下記のようなC++プログラムにおいて、Good Morning! の「r」以後が、 検索にひっかからないで、-1を返します。 何故なのか、どうぞよろしくお願いします。 -------------------------------------------------------- #include <iostream> #include <cstring> using namespace std; int flag = 0; // 該当文字があったかどうかのフラグ int strch_idx(const char* s, char c){ int temp; cout << strlen(s) << endl; for(int i=0; i<(signed)strlen(s); i++){ if(*s == c){ temp=i+1; // 配列のインデックスは0オリジンだが、インデックスは1からだから1+する flag = 1; break; } s++; } if(flag == 1) return temp; else return -1; } int main(){ const char* s = "Good Morning!"; int idx = strch_idx(s, 'i'); cout << "検索文字のインデックス:" << idx << endl; return 0; }

専門家に質問してみよう