• 締切済み

画像のラベリング

画像処理について勉強しています。 画像のラベリングを行うプログラムを書いていたのですが、意図した結果になりません。 以下の関数で実現しようとしましたが、上手くいきませんでした。何か、決定的に間違っている点などがありましたら、教えてください。 また、参考になるWebページなどがありましたら、教えていただけると幸いです。 image2[][]には、レナ画像の512x512を判別分析法を使用して2値化した画像データが格納されています。 また、label[]は全て-1で初期化しました。(initialize()) void labeling(){ int x,y; int up_label,left_label; int label_num=1; //初期ラベル int label_add=1; //ラベルの増分 int max; int i; initialize(); for(y=0; y<y_size1; y++){ for(x=0; x<x_size1; x++){ if(image2[y][x]==0 && label[y][x]==-1){ up_label=left_label=500; if(y-1>=0) up_label=label[y-1][x]; if(x-1>=0) left_label=label[y][x-1]; if(up_label==500 && left_label==500){//(0,0)の地点の処理 label[y][x]=label_num; }else if(up_label==left_label){//上と左が等しい場合の処理 //上と左のラベルが無い場合はラベルを作る if(up_label < 0) label_num += label_add; //ラベルを付与 label[y][x]=label_num; }else{//それ以外の処理 //上と左で小さいほうのラベルを付与する if(up_label<0) label[y][x]=left_label; else if(left_label<0) label[y][x]=up_label; else label[y][x]= (up_label < left_label)? up_label:left_label; } } } } }

みんなの回答

  • mutchio
  • ベストアンサー率0% (0/0)
回答No.1

私もラベリングのアルゴリズムを考えているものです。 まだ考え途中なのですが、とりあえず訂正すべき箇所はわかりましたので、書き込ませていただきます。 上と左を調べて小さいほうのラベルを付与したあと、上と左で大きい方のラベルに小さいラベルを振りなおす必要があります。 自分で書いてても意味がわからなくなってしまったので、図で。    333 555□□□ 555□□□ 555□□□ この画像を処理すると    333 555333 555333 555333 こうなってしまうと思います。 そこで5の部分に3を入れなおさなければいけません。    333 333333 333333 333333 この処理をエレガントに行うのが割りと難しくて私も苦労しています。 もっと詳しい方の回答をお待ちしていますw

関連するQ&A

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

    画像のラベリング処理プログラムを作っているんですが どうもうまく実行できません。よければ教えていただけないでしょうか。 #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文でセグメンテーションが出てしまいます。

  • ラベリング方法の工夫をしたいのですが・・・

    はじめまして!大学で画像処理について学び始めたものですが、 ラベリング処理でわからないことがあり、質問させていただきました! 二値化はなんとかできたのですが・・・ 下記のようにラベルをつけるにはどうしたらよろしいでしょうか?? 画素数 ○⇒255 ●⇒0 一○○○○○○○○○ 行○○○○●○○○○⇒左から順に●に1、2、3、とつけたい 目○●○○○○○●○  ○○○○○○○○○  ○○○○○○○○○  ○○○○○○○○○ 二○○○○○○○●○ 行○●○○●○○○○⇒左から順に●に11、12、13とつけたい 目○○○○○○○○○  ○○○○○○○○○  ○○○○○○○○○ ※●は横一列ですが上記のように一番右の●の座標が上だったりするなど縦にずれていてラベリングがうまく走査できません。。。この図だと縦に一列ですが、実際は横にも画素がずれています。。。。 最終的には、このようにラベリングして 一○○○○○○○○○ 行○○○○2○○○○ 目○1○○○○○3○  ○○○○○○○○○  ○○○○○○○○○  ○○○○○○○○○ 二○○○○○○○13○ 行○11○○12○○○○ 目○○○○○○○○○  ○○○○○○○○○  ○○○○○○○○○ 1と11 2と12 3と13の距離を測りたいと思っています・・・なのですが、この際ラベリングを走査すると 一行目の「1」とつけたい画素に「2」がついてしまったり、 二行目の「3」とつけたい画素に「1」がついてしまいます。。 そこでラベリングを、コンビニのスキャナーのように 4つの画素分ぐらいで横に走査できるようにできないか、 と考えたのですが、参考書などを調べたのですが そのようなラベリングは見つからず、 うずまきラベリングや 4近傍ラベリングは見つけたのですが、 うまくラベルをつけることができませんでした。 うずまきラベリングは一行目の横画素に到達するまえに 上下の画素に触れてしまいラベリングできませんでした。 4近傍ラベリングは通常のラベリングと同じような結果になってしまいました。 もしどなたか、このようなラベリング方法を知っている方など いましたらご教授お願いします!! 説明不足、意味がよくわからないところなどありましたらご指摘お願いします よろしくお願いします(><)

  • らべリnグについての質問です

    数字が書かれた画像を2値化し、ラベリングして数字だけを抜き出して出力したいのですが、どうも上手くいきません。 色々試しても見たのですが、数字だけを取り出すことはできませんでした。 以下のプログラムのどこを直せば、ラベリングされた画像を抜き出すことができるのでしょうか? 一週間やってもできませんでした… 何方か教えて下さると大変助かります #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define Y_SIZE 512 //縦の最大画素数 #define X_SIZE 512 //横の最大画素数 #define HIGH 255 //最大階調値 #define LOW 0 //最小階調値 #define Level 256 #define FileName 256 #define MaxBufferSize 640 #define L_BASE 100 #define Black 1 #define White 2 unsigned char image[Y_SIZE][X_SIZE]; //入力画像用配列 unsigned char label_image[Y_SIZE][X_SIZE]; unsigned char image_h[Y_SIZE][X_SIZE]; int x_size, y_size; int Label=200; long hist[256]; void set(unsigned char image[Y_SIZE][X_SIZE], int xs, int ys, int label); void save(unsigned char output_img[Y_SIZE][X_SIZE],int output_ysize,int output_xsize); void load(void) { 入力画像 } void hist1(unsigned char image_in[Y_SIZE][X_SIZE], int x, int y, long hist[256]) { ヒストグラム処理 } void hist2(long hist[256], unsigned char image_h[Y_SIZE][X_SIZE]) { ヒストグラムを画像化 } void thr(unsigned char image_in[Y_SIZE][X_SIZE], unsigned char image_out[Y_SIZE][X_SIZE], int thresh, int type) { 閾値処理 閾値180 タイプ白 } 画像のラベリング処理 int labeling(unsigned char image_in[Y_SIZE][X_SIZE], unsigned char image_label[Y_SIZE][X_SIZE]) { int i, j, label; for (i = 0; i < Y_SIZE; i++) for (j = 0; j < X_SIZE; j++) image_label[i][j] = image_in[i][j]; label = L_BASE; for (i = 0; i < Y_SIZE; i++) for (j = 0; j < X_SIZE; j++) { if (image_label[i][j] == HIGH) { if (label >= HIGH) return -1; set(image_label, j, i, label); label++; }} return label - L_BASE; } 連結している画素すべてにラベル付け void set(unsigned char image[Y_SIZE][X_SIZE], int xs, int ys, int label) { int i, j, cnt, im, ip, jm, jp; image[ys][xs] = label; while(1) { cnt = 0; for (i = 0; i < Y_SIZE; i++) for (j = 0; j < X_SIZE; j++) if (image[i][j] == label) { im = i-1; ip = i+1; jm = j-1; jp = j+1; if (im < 0) im = 0; if (ip >= Y_SIZE) ip = Y_SIZE-1; if (jm < 0) jm = 0; if (jp >= X_SIZE) jp = X_SIZE-1; if (image[i ][jp] == HIGH) { image[i ][jp] = label; cnt++; } if (image[im][jp] == HIGH) { image[im][jp] = label; cnt++; } if (image[im][j ] == HIGH) { image[im][j ] = label; cnt++; } if (image[im][jm] == HIGH) { image[im][jm] = label; cnt++; } if (image[i ][jm] == HIGH) { image[i ][jm] = label; cnt++; } if (image[ip][jm] == HIGH) { image[ip][jm] = label; cnt++; } if (image[ip][j ] == HIGH) { image[ip][j ] = label; cnt++; } if (image[ip][jp] == HIGH) { image[ip][jp] = label; cnt++; } } if (cnt == 0) break; } save(image,ys,xs); } //ラベリング画像の出力 void save(unsigned char output_img[Y_SIZE][X_SIZE],int output_ysize,int output_xsize) { char f_name[FileName]; FILE *fp; int i, j,n; printf("Output File (*.pgm) : "); scanf("%s",f_name); fp = fopen(f_name, "wb"); fputs( "P5\n", fp ); fputs( "# Created by Image Processing\n", fp ); fprintf( fp, "%d %d\n", output_xsize, output_ysize ); fprintf( fp, "%d\n", HIGH); 画像データの出力 for (i=0; i<output_ysize; i++) for (j=0; j<output_xsize; j++) fputc(output_img[i][j], fp); fclose(fp); } int main(void){ int thresh=180, type=White; 入力画像 load(); ヒストグラム処理 hist1(image, x_size, y_size, hist); ヒストグラム画像化 hist2(hist,image_h); 閾値処理 thr(image, image_h, thresh, type); labeling(image_h, label_image); return 0; }

  • ラベリング処理

    はじめまして。最近、画像処理を勉強し始めたものです。 ラベリング処理で質問したいことがあり、書き込みさせていただきました。 2値化処理した画像を作成したとします。 例えば以下のような0(黒)と255(白)の画像です。 ここで、連結し合う255の画素を同じ番号でラベル付けして、異なるラベル番号の255の島(塊)の数を数えたいと思ってます。 以下の例では、連結し合う同一ラベルの255の島の数は「3つ」となります。 さらに最下2行のように、画素数が3つというような小さな島は除去するという条件もつけられたらなと思ってます。 自分ではなかなかうまくいかず・・・ 是非、どういうプログラムを組んでいけば良いか、ご指導をいただけないでしょうか。 何卒よろしくお願いいたします。 0 0 255 255 0 0 0 0 255 255 255 255 0 0 0 0 255 255 255 255 0 0 0 0 255 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 0 0 0 255 255 255 255 0 0 0 0 255 255 255 255 0 0 0 255 255 255 0 0 0 0 255 255 255 0 0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 255 255 0 0 0

  • 画像処理のプログラムについて

    初めまして、こんにちは C言語で画像処理のプログラミングについてご解答をお願いします 現在二値化した白黒バーコードに対して、ビット数埋め込みというものを行っています この画像に埋め込んだビットを、検出するプログラムを作成したいのですがどうしたらいいでしょうか? ソースコードは以下です int x,y,i,j; double Th = 128.0; /*2値化の際のしきい値 */ int x_StartPos, y_StartPos,x_EndPos,y_EndPos; /*バーコードが描画されている領域の座標 */ int num; y=0; while (y<biHeight){ x=0; while(x<biWidth){ if (Y[y][x]<Th) break; x++; } if (x < biWidth){ x_StartPos = x; y_StartPos = y; break; } y++; } if ((x_StartPos==0) && (y_StartPos==0)) { printf("画像中に黒領域が見つかりませんでした"); exit(-1); } x_EndPos=0; while (x<biWidth){ /*画面右までスキャンして、一番右端の黒のx座標を求める*/ if (Y[y][x] < Th)/* 黒い点であったら */ x_EndPos=x; x++; } if (x_EndPos==0) { printf(" バーコード右端が検出できませんでした\n"); exit(-1); } /*バーコード一番上のラインにおける、黒の画素の数を数える*/ x=y_StartPos; y=y_StartPos; num=0; //これまでに検出した黒画素の数 while(x<=x_EndPos){ if (Y[y][x] < Th) // 黒い点であったら num++; //黒画素数を +1 する x++; } *start_x= x_StartPos; *start_y= y_StartPos; *end_x = x_EndPos; *num_of_blackpixels =num; } void Embed_watermark(double Y[Y_SIZE][X_SIZE],double Y_out[Y_SIZE][X_SIZE], int sukasi[], int Length, int x_StartPos, int y_StartPos, int x_EndPos) { int x,y; int bitnum; double Th = 128.0; /*2値化の際のしきい値 */ for(y=0;y<biHeight;y++) //出力データに元データをコピー for(x=0;x<biWidth;x++) Y_out[y][x]=Y[y][x]; bitnum=0; //現在何番目のbitが埋め込み対象になっているのか x=x_StartPos; y=y_StartPos; //埋め込み開始 while(x<=x_EndPos){ if (Y_out[y][x]<Th){ //もし注目点が黒画素なら透かし埋め込み処理を行う printf("found! x=%d bitnum=%d\n",x,bitnum); if (sukasi[bitnum]==0){ // 「0」を埋め込むなら、該当画素を白くする Y_out[y][x]=255; } bitnum++; //埋め込み対象を次のビットにする } if (bitnum==Length) // もし全てのビットの埋め込み処理が終了したら break; x++; } printf("埋め込みが完了しました.埋め込み終了x座標=%d\n",x); } void main(void) { int Length = 20; // 埋め込む透かしのビット長 int suuchi[]={1,1,1,1,0,0,0,0,1,1,1,0,0,0,1,1,0,0,1,0}; //埋め込む透かしビット char *input="bar.bmp"; char *output="out.bmp"; /* 画像中のバーコードが書かれている左上端の座標 */ int x_StartPos; int y_StartPos; int x_EndPos;//バーコードx座標の終端 int Num_of_Blacks; //バーコードの横方向の黒画素数(=埋め込めるビット数の上限)

  • 画像に対してn/2ずつずらしてnメッシュをつくり、

    画像に対してn/2ずつずらしてnメッシュをつくり、 nのメッシュにそれぞれ処理をしていくための プログラムを組もうとしています。 ですが、以下のプログラムを組んだ際に "ハンドルされていない例外が発生しました: 0xC0000005: 場所 0x02def000 を読み込み中にアクセス違反が発生しました" というエラー文がでます。 この理由を教えていただけると助かります。 よろしくお願いいたします。 以下のプログラムは1920x1080の画像に対して 縦横120メッシュの処理を行おうとしています。 int a=0,b=0; int x,y; while(1) { for(y = a; y < y + 120 ; y++) { for( x = b; x < x + 120 ; x++) { //画像の読み込み } } //上記のメッシュに対して処理 if(a + 60 == 1920) //xの端までいったとき { a = 0; //x=0に戻る if( b + 60 == 1080) //yの端までいったとき { b =+ 60; //y方向に60ずらす } else { break; } } else { a =+ 60; //x方向に60ずらす } }

  • C++でオセロのCPUの処理を考えたのですが、40手目あたりからうまく

    C++でオセロのCPUの処理を考えたのですが、40手目あたりからうまくいきません。ReverseOthello関数の石を探して裏返す処理がおかしいと思われます。一番裏返せる石が多い位置を裏返すという処理をしています。プログラミング経験が豊富な方よろしくお願いします。 #include "stdafx.h" bool Othello(int (*pBoard)[8] ){ int i; int j; int ans; int k = 0; int num[3] = {0,0,0}; int sum[28][3]; i = 0; while(i < 28){ j = 0; while(j < 3){ sum[i][j] = 0; j++; } i++; } i = 0; while(i < 8){ j= 0; while(j < 8){ if(pBoard[i][j] == 0){ ans = SeachStone(i,j,pBoard); if(ans != 0){ sum[k][0] = i; sum[k][1] = j; sum[k][2] = ans; k++; } } j++; } i++; } i = 0; while(i < 28){ if(num[2] < sum[i][2]){ num[0] = sum[i][0]; num[1] = sum[i][1]; num[2] = sum[i][2]; } i++; } if(num[2] == 0){ return false; } ReverseStone(num[0],num[1],pBoard); return true; } void ReverseStone(int y1,int x1,int (*pBoard)[8]){ int cnt = 0; int y2; int x2; int i; int j; int k; if(y1 == 0){ i = 0; } else { i = y1-1; } while(i < y1 + 2){ if(x1 == 0){ j = 0; } else { j = x1-1; } while(j < x1 + 2){ y2 = i; x2 = j; cnt = 0; while(pBoard[y2][x2] == -1){ y2 = y2 + (i - y1); x2 = x2 + (j - x1); cnt++; } if(pBoard[y2][x2] == 1&& cnt != 0){ k = 0; while(k < cnt + 1){ y2 = y2 + (y1 - i); x2 = x2 + (x1 - j); pBoard[y2][x2] = 1; printf("%d\n",pBoard[y2][x2]); k++; } } j++; } i++; } } int SeachStone(int y1,int x1,int (*pBoard)[8]){ int cnt = 0; int sumCnt = 0; int y2; int x2; int i; int j; if(y1 == 0){ i = 0; } else { i = y1-1; } while(i < y1 + 2){ if(x1 == 0){ j = 0; } else { j = x1-1; } while(j < x1 + 2){ y2 = i; x2 = j; cnt = 0; while(pBoard[y2][x2] == -1){ y2 = y2 + (i - y1); x2 = x2 + (j - x1); cnt++; } if(pBoard[y2][x2] == 1&& cnt != 0){ sumCnt = sumCnt + cnt; } j++; } i++; } return sumCnt; }

  • インライン関数の使い道と理屈

    #include <iostream> using namespace std; //max関数の定義 inline int max(int x, int y){if(x>y) return x; else return y;} int main(){ int num1, num2, ans; cout << "1番目の整数を入力して下さい。\n"; cin >> num1; cout <<"2番目の整数を入力して下さい。\n"; cin >> num2; ans = max(num1, num2); cout << "最大値は" << ans << "です。\n"; return 0; } インライン関数の処理は呼び出し部分に埋め込まれるので、プログラムの処理速度が 向上することがありますとあるんですが、 どのような時にインライン関数は使用するのでしょうか? 理由もしくみもご教示お願いします。

  • 併合処理ソートについて

    いつも大変お世話になっておりますm(_ _)m アルゴリズム初心者なのですが、併合処理ソートをC言語で自作しています。しかし途中で行き詰ってしまい困っております。 私が作成したコードは以下になります。 void merge(int D[], int left, int mid, int right) { int x, y, i, M[50000]; x=left; y=mid+1; for(i=0; i<=right-left; i=i+1){ if((x != mid+1)&&(y != right+1)) { if (D[x]<D[y]){ M[i]=D[x]; x=x+1; } else if (D[x]=D[y]){ M[i]=D[x]; x=x+1; i=i+1; M[i]=D[y]; y=y+1; } else { M[i]=D[y]; y=y+1; } } if(x == mid+1){ M[i]=D[y]; y=y+1; } if(y == right+1){ M[i]=D[x]; x=x+1; } } for(i=left; i<=right-left; i=i+1){ D[i]=M[i]; } } void mergesort(int D[], int left, int right) { int mid; if(left != right){ mid=(left+right)/2; if(left < mid) mergesort(D,left,mid); if(right > mid+1) mergesort(D,mid+1,right); merge(D,left,mid,right); } } 入力は五桁程度の正の整数の昇順並び替えで、↑のコードの中には 入力と出力に関するコードは含んでいません。入力出力部分に誤りはないと思われます。 出力しても正しく昇順に並んでくれません。。。 どなたかご教授ご指導お願い致しますm(_ _)m

  • マージソート内の再帰処理にすいて

    #include<stdio.h> #define MAX 4 int temp[MAX]; void marge(int num[],int left,int right) { int i,j,mid,k   if(left>=right)return; mid=(left+right)/2; marge(num,left,mid);//(1) maege(num,mid+1,right);//(2) for(i=left;i<=mid;i++) temp[i]=num[i]; for(i=mid+1,j=right;i<=right;i++,j--) temp[i]=num]j]; i=left; j=right; for(k=left;k<=right;k++) if(temp[i]<=temp[j]) num[k]=temp[i++]; else num[k]=temp[j--] } マージソート内はこういった関数を記述してエラーもでないのですが、(1)と(2)の処理がよくわかりません。 (1)は再帰的に処理していってif(left>=right)return;の条件を満たした場合に(2)の処理に入っていきますよね? その場合、(2)の処理を行う際に(1)が(2)の再帰より前に記述されているので(1)がまた処理されるのでしょうか? 一連の流れを(1)、(2)を使って表してほしいです。

専門家に質問してみよう