• 締切済み

ラベリング処理プログラム

画像のラベリング処理プログラムを作っているんですが どうもうまく実行できません。よければ教えていただけないでしょうか。 #include<stdio.h> #include<stdlib.h> int column, row; unsigned char val[4] = {0,0,0,0}; unsigned char tmp[255]; int pos_y[4] = {-1, 0, 1, 0}; int pos_x[4] = {0, 1, 0, -1}; int i, j, x, y, label, level, label1; int label_count = 1; unsigned char *in, *out; void labeling_main(); void labeling_search(); void labeling_main() { for(i = 0; i < y; i++){ for(j = 0; j < x; j++){ printf("aaa\n"); if(out[i * x + j] == 255){ printf("bbb\n"); fflush(stdout); out[i * x + j] = label_count; labeling_search(label_count, i, j); label_count++; } } } } void labeling_search(int label_count, int x, int y) { for(i = 0; i < 4; i++){ if(out[(pos_y[i] + y) * x + (pos_x[i] + x)] == 255){ out[(pos_y[i] + y) * x + (pos_x[i] + x)] = label_count; labeling_search(label_count,(pos_y[i]+y),(pos_x[i]+x)); } } printf("ccc\n"); } int main(int argc, char *argv[]) { int result; int head, Magic; unsigned char *image, *in, *out, *res, *ros; FILE *fin, *fout; if(argc!=3){ printf("Usage : %s input output\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); 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); out = (unsigned char *)malloc(sizeof(unsigned char) *x*y); //2値画像 for (i = 0; i < y; i++) { for (j = 0; j < x; j++){ if(in[i * x + j] > 120){ out[i * x + j] = 0; }else if(in[i * x + j] <= 120){ out[i * x + j] = 255; } } } labeling_main(); printf("Max label number:%d\n",label_count); free(in); free(out); fclose(fin); fclose(fout); } コンパイルは通るのですが実行するとlabeling_mainの if文でセグメンテーションが出てしまいます。

みんなの回答

noname#208507
noname#208507
回答No.4

labeling_search()の引数のxとyも間違えていますね. 他のグローバル変数の意見等を反映したものが下のコード. ただし再帰はループに変えないと,小さい画像でもすぐスタックがあふれるでしょう. エラー処理もさぼってます. あとはご自分で. #include<stdio.h> #include<stdlib.h> #include<limits.h> #define GRAY_MAP 5 typedef struct PGM { int magic; int width; int height; int level; unsigned char *image; } PGM; typedef enum Result { ERROR, SUCCESS } Result; enum { BACK = 0, FORE = UCHAR_MAX }; #define is_in_image(pgm, x, y) \ (((x) >= 0) && ((y) >= 0) && ((x) < (pgm)->width) && ((y) < (pgm)->height)) static void labeling_search(PGM *pgm, int label_count, int x, int y) { int pos_y[4] = { -1, 0, 1, 0 }; int pos_x[4] = { 0, 1, 0, -1 }; int pos[4] = { pgm->width * pos_y[0] + pos_x[0], pgm->width * pos_y[1] + pos_x[1], pgm->width * pos_y[2] + pos_x[2], pgm->width * pos_y[3] + pos_x[3] }; unsigned char *p = pgm->image + (pgm->width * y) + x; int i; for (i = 0; i < 4; i++) { if (is_in_image(pgm, x, y) && (p[pos[i]] == FORE)) { p[pos[i]] = label_count; labeling_search(pgm, label_count, x + pos_x[i], y + pos_y[i]); } } return; } static int labeling_main(PGM *pgm) { int label_count = 1; unsigned char *p; int x, y; p = pgm->image; for (y = 0; y < pgm->height; y++) { for (x = 0; x < pgm->width; x++) { if (*p == FORE) { *p = label_count; labeling_search(pgm, label_count, x, y); label_count++; } p++; } } return label_count; } static Result pgm_read(PGM *pgm, char *filename) { const int TMP_SIZE = 255; size_t size; char tmp[TMP_SIZE]; FILE *fin; fin = fopen(filename, "rb"); if (fin == NULL) { return ERROR; } fgets(tmp, TMP_SIZE, fin); if (tmp[0] != 'P') { fclose(fin); return ERROR; } sscanf(tmp,"P%d", &(pgm->magic)); if (pgm->magic != GRAY_MAP) { fclose(fin); return ERROR; } while (fgets(tmp, TMP_SIZE, fin) != NULL) { if (tmp[0] != '#') { break; } } sscanf(tmp,"%d %d", &(pgm->width), &(pgm->height)); if ((pgm->width < 1) || (pgm->height < 1)) { fclose(fin); return ERROR; } fgets(tmp, TMP_SIZE, fin); sscanf(tmp, "%d", &(pgm->level)); size = pgm->width * pgm->height; pgm->image = malloc(sizeof(unsigned char) * size); if (pgm->image == NULL) { fclose(fin); return ERROR; } fread(pgm->image, sizeof(unsigned char), size, fin); fclose(fin); return SUCCESS; } static Result pgm_write(PGM *pgm, char *filename) { FILE *fout; fout = fopen(filename, "wb"); if (fout == NULL) { return ERROR; } fprintf(fout, "P%d\n", pgm->magic); fprintf(fout, "# My new PGM\n"); fprintf(fout, "%d %d\n", pgm->width, pgm->height); fprintf(fout, "%d\n", pgm->level); fwrite(pgm->image, sizeof(unsigned char), pgm->width * pgm->height, fout); fclose(fout); return SUCCESS; } static void pgm_binarize(PGM *pgm, int thresh) { unsigned char *p; int x, y; p = pgm->image; for (y = 0; y < pgm->height; y++) { for (x = 0; x < pgm->width; x++) { *p = (*p > thresh) ? BACK : FORE; p++; } } return; } int main(int argc, char *argv[]) { const int THRESH = 120; int label_count; Result r; PGM pgm; if (argc != 3) { printf("Usage : %s input output\n",argv[0]); exit(1); } r = pgm_read(&pgm, argv[1]); if (r == ERROR) { printf("error\n"); exit(1); } pgm_binarize(&pgm, THRESH); label_count = labeling_main(&pgm); printf("Max label number:%d\n",label_count); r = pgm_write(&pgm, argv[2]); if (r == ERROR) { printf("error\n"); exit(1); } free(pgm.image); return EXIT_SUCCESS; }

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

◯「グローバル変数の間違った使い方」の見本みたいなプログラムになっています i=10,j=15でlabeling_searchを実行したらどうなると思います? ◯0,0に対象があったとしたらlabeling_search(1,0,0)で実行することになるかと思います このとき (pos_y[i] + y) * x + (pos_x[i] + x) はいくつになると思います? ◯グローバル変数x,yで画像の幅、高さにしているようですが、labeling_search関数では、仮引数x,yで座標を表しています out[(pos_y[i] + y) * x + (pos_x[i] + x)] xは画像幅にはなってません labeling_mainで問題を起こしそうなにのは上のような点 他にも PGMのバイナリ8ビットしか対応してないのに、P1等でも読み込もうとする 間違いじゃないけど、doに{}が無いのが気持ち悪い 等

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.2

>コンパイルは通るのですが実行するとlabeling_mainの >if文でセグメンテーションが出てしまいます。 本当にその場所…ですか? ちゃんと追ってはいませんが、 labeling_search()の >if(out[(pos_y[i] + y) * x + (pos_x[i] + x)] == 255){ >out[(pos_y[i] + y) * x + (pos_x[i] + x)] = label_count; 辺りが範囲外に行きそうな気が……。 あとは……labeling_main()からlabeling_search()をコールして戻って来た時点で、y座標を走査しているカウンタ変数のiが期待外の値(具体的には3)になっていることが「保証されて」ます。 グローバル変数は便利ですよね? # 意図しない箇所で書き換えできますから…ね。 # 書き換えたくなくてももれなく書き換え可能ですから。 >fwrite(out, sizeof(unsigned char),x*y, fout); >out = (unsigned char *)malloc(sizeof(unsigned char) *x*y); ここのfwrite()でセグメンテーション違反になるギャンブルも楽しめるようです。 # fwrite()の時点ではポインタ変数outが挿している箇所は「不定」です。 # malloc()の後なら不定値ではないかも知れませんが、「メモリの内容」不定値です。

tharaaay
質問者

お礼

ありがとうございます。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

メモリくらい割当ててあげようよ.

関連するQ&A