ショッピングモール  Earth-Based Religions ( Shintoism )  Earth-Based Religions ( Wicca )


掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板1

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧

No.5052

hough変換
投稿者---tana(2005/12/07 22:40:32)


今画像処理でhough変換のプログラムを作ったのですが、
うまく動作しなくて困ってます。まずhough変換というのは、
(あるサイトの文章ですが)
 広義には、直線や各種2次関数曲線などパラメータで表現できる図形のパラメータ空間への写像をさす。しかし、図形を記述するパラメータの数が多くなると、変換は困難となるために、通常は直線を対象とした写像をさす。
 xy平面において、原点からある直線1への垂線を考え、その垂線と直線1との交点の極座標値を(θi,ρi)とする。このとき、直線1は次式を満足する(x,y)の集合として表される。
 x cosθi+y sinθi=ρi (1)
したがって、直線1は(θ,ρ)空間の点(θi,ρi)に写像される。
 この逆変換は、(θ,ρ)空間で(x,y)をパラメータと考えて、次式で示される正弦曲線を(x,y)空間の点(xi,yi)に写像する操作として定義される。
 ρ=xi cosθ+yi sinθ
  =(xi2+yi2) sin(θ+α) (2)
 ただし、α=tan-1(xi/yi)
 もし画像において濃淡レベルfk以上の点が直線上の点であるならば、 fk以上の点をそれぞれ式(2)により(θ,ρ)空間の正弦曲線群に変換すると、それらの正弦曲線はある一点で交差する。

以上がhough変換の概要です。
ちなみに自分が作っているのは円検出プログラムです。
次に作ったプログラムを載せておきます。



この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:hough変換 5063 tana 2005/12/07 23:04:42


No.5063

Re:hough変換
投稿者---tana(2005/12/07 23:04:42)




このプログラムでは、あらかじめ配列を確保しておき、
つぎにカラー画像を配列に読み込んで(関数inputdata1)、
モノクロ画像へ変換して二値化します(関数nichi)。
その二値化したデータをhough変換を実行する関数へ
与えて最適な画像座標と半径rを探します(関数Hough_transform)。
そして最後にHOUGH逆変換というのを行い画像上に円を描写します(invHough_Transformおよびwritefile3_double)。
ちなみにchange_colorは、二値化したデータの白い部分の
階調を落として、Hough変換して描画する円をわかりやすくするための
関数です。いかがプログラムです。

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include<math.h>

/*a[0]はx(横) a[1]はy(縦)の値が入っている*/

#define RGB 3
#define KAICYOU 256        /*基本階調値*/
#define MAX_KAICYOU 255
#define PIK 0.003067962      /* 円周率 3.1415926/1024(ラジアン) */
#define MAX_THETA  1024         /* 最大θ */
#define MAX_NIJYOU  320         /* 用意する二乗テーブルの個数 */   
#define MAX_L       1          /* 抽出する円の数 */

void file_imformation(FILE *infile0,int argc,char *argv[],int *);
void inputdata1(FILE *, char *argv[], int a[],double*** N);
void getmemory2_double(int a[],double*** N);
void getmemory3_double(int a[],double**** N);
void getmemory3_int(int a[],int**** N);
void getmemory_sp(int a[],int**** N,int MAX_R);
void leftmemory2_double(int a[],double** N);
void leftmemory3_double(int a[],double*** N);
void table(double sn[],double cs[],double sq[]);
void change_color(int a[],double** O,double*** P);
void Hough_transform(int a[],double** P,double sq[],int*** intens,int MAX_R);
void invHough_transform(int a[],int MAX_R,
            int*** intens,double*** P,double cs[],double sn[]);
int calc_MAX_R(int a[],int MAX_R);
void writefile3_double(FILE *,char *argv[],int num,int a[],double*** N);
void leftmemory3_int(int a[],int*** N);
void nichi(int a[],double*** L,double** O);
void writefile2_double(FILE *,char *argv[],int num,int a[],double** N);



この投稿にコメントする

削除パスワード

No.5064

Re:hough変換
投稿者---tana(2005/12/07 23:05:46)


//-------main----------
int main(int argc,char *argv[]){
  double*** data;
  double** nichi_data;
  double*** hough_data; 
  int*** intens;
  int i,j,k,a[2],MAX_R=0;//a[]はx、yの値
  double  sn[MAX_THETA]={0.0},cs[MAX_THETA]={0.0},sq[MAX_NIJYOU]={0.0};
  FILE *infile0,*infile1, *infile2, *outfile1,*outfile2,*outfile3,*outfile4;
  
  file_imformation(infile0,argc,argv,a);  
  getmemory2_double(a,&nichi_data);  
  getmemory3_double(a,&hough_data);
  getmemory3_double(a,&data);  

  table(sn,cs,sq);
  MAX_R = calc_MAX_R(a,MAX_R);  
  getmemory_sp(a,&intens,MAX_R);
  
  inputdata1(infile1,argv,a,data);

  nichi(a,data,nichi_data);
  writefile2_double(outfile1,argv,2,a,nichi_data);
  change_color(a,nichi_data,hough_data);

  Hough_transform(a,nichi_data,sq,intens,MAX_R);
  invHough_transform(a,MAX_R,intens,hough_data,cs,sn);
   writefile3_double(outfile2,argv,3,a,hough_data);  
  
  leftmemory2_double(a,nichi_data);  
  leftmemory3_double(a,hough_data);
  leftmemory3_int(a,intens);
  leftmemory3_double(a,data);
  return 0;
}


void nichi(int a[],double*** L,double** O){
  int i1,j,h;
  double  hist[KAICYOU]={0};
  int x,y,i,k,saiteki_k=0;
  double N=0.0,N1=0.0,N2=0.0;
  double ave=0.0,ave1=0.0,ave2=0.0,total=0.0;
  double bun_b=0.0,bun_max=0.0,bun1,bun2,bun_w=0.0;
  
  
  for(i1=0;i1<a[0];i1++){
    for(j=0;j<a[1];j++){
      O[i1][j]=0.299*L[i1][j][0]+0.587*L[i1][j][1]+0.114*L[i1][j][2];  
    }
  }
  for(i=0;i<a[0];i++)               /* データ入力 + ヒストグラムを描く。 */
    for(j=0;j<a[1];j++)
      hist[(int)O[i][j]]++;

  for(i=0;i<KAICYOU;i++) 
    N += hist[i];                   /* 全画素数 N の計算。 */
 
  for(i=0;i<KAICYOU;i++){
    hist[i] = hist[i] / N;          /* 輝度の正規化ヒストグラムに直す。  */
    ave += ((i+1)*hist[i]);         /* 画像の平均輝度 ave の計算。 */
}

 
    printf("画像の平均輝度(ave):%.0lf\n",ave);
  
  for(k=0;k<KAICYOU;k++){
    N1 = 0.0;   N2 = 0.0;
    ave1 = 0.0; ave2 = 0.0;
  bun1 = 0.0; bun2 = 0.0;
    total = 0.0;
    
    for(i=0;i<k;i++){
      N1 += hist[i];                  /* 生起確立 N1 の計算。 */
      total += ((i+1)*hist[i]);
    }
    //    printf("%d\n",k);
    // printf("%lf\n",N1);
    // printf("%lf\n",total);

    if(N1!=0){
      ave1 = total / N1;              /* クラス1の平均輝度 ave1 の計算。 */
    }
      for(i=0;i<k;i++){
      bun1 += (((i+1)-ave1)*((i+1)-ave1)*hist[i]);
    }
    if(N1!=0){
      bun1 = bun1 / N1;               /* クラス1の分散 bun1 の計算。 */ 
    } 
    total = 0.0;
    for(i=k;i<KAICYOU;i++){
      N2 += hist[i];                 /* 生起確立 N2 の計算。 */
      total += ((i+1)*hist[i]);
    }
    if(N2!=0){
      ave2 = total / N2;             /* クラス2の平均輝度 ave2 の計算。 */
    }
     for(i=k;i<KAICYOU;i++){
      bun2 += (((i+1)-ave2)*((i+1)-ave2)*hist[i]);
    }
    if(N2!=0){
      bun2 = bun2 / N2;              /* クラス2の分散 bun2 の計算。 */
    } 
    bun_b = N1*N2*(ave1-ave2)*(ave1-ave2);  /* クラス間分散 bun_b の計算。 */
    
    if(bun_b>bun_max){                /*クラス間分散が最大となるときの最適しきい値の計算*/
      bun_max = bun_b;
      saiteki_k = k;
    }
    //    printf("%lf\n",bun_max);
    // printf("%lf\n",saiteki_k);
  }
  
  printf("最適しきい値(saiteki_k):%d\n",saiteki_k);
  
  for(i=0;i<a[0];i++){              /* モノクロ画像から2値画像へ。 */
    for(j=0;j<a[1];j++)
      {
    if(O[i][j]<=saiteki_k)  O[i][j]=0;
    else                         O[i][j]=255;
      }
  }
  printf("モノクロ画像から2値画像に変換しました。\n"); 
  
}



この投稿にコメントする

削除パスワード

No.5065

Re:hough変換
投稿者---tana(2005/12/07 23:06:47)


void Hough_transform(int a[],double** O,double sq[],int*** intens,int MAX_R)
{
int x,y,c,b,r=0,Dist_x=0,Dist_y=0;

printf("Hough変換を実行中。\n"); /* Hough変換処理の実行。 */

for(y=0;y<a[1];y++)
for(x=0;x<a[0];x++)
if(O[x][y] == (double)MAX_KAICYOU){ /* そのピクセルが白なら。 */
for(c=0;c<a[0];c++)
for(b=0;b<a[1];b++){
if((x-c)>0) Dist_x = (x-c);
else if((x-c)==0) Dist_x = 0;
else Dist_x = (c-x);
if((y-b)>0) Dist_y = (y-b);
else if((y-b)==0) Dist_y = 0;
else Dist_y = (b-y);

r = sqrt( sq[Dist_x] + sq[Dist_y] );
if(r>=0 && r<MAX_R) intens[c][b][r]++; /* intens[a][b][r]に頻度を累積する。*/
}
}

// printf("intens[167][152][116]=%d",intens[167][152][116]);
printf("Hough変換実行完了\n");
}


void invHough_transform(int a[],int MAX_R,int*** intens,double*** P,double cs[],double sn[])
{
int l,c,b,r,x,y,theta,i,j,k;
int MAX_INTENS=0,MAX_A=0,MAX_B=0,MAX_r=0;

printf("Hough逆変換を実行します\n");

for(l=0;l<MAX_L;l++){
MAX_INTENS=0;


for(c=0;c<a[0];c++)
for(b=0;b<a[1];b++)
for(r=0;r<MAX_R;r++)

if(intens[c][b][r]>MAX_INTENS){
MAX_INTENS = intens[c][b][r];
MAX_A = c;
MAX_B = b;
MAX_r = r;
}

printf("intens[%d][%d][%d]=%d\n",MAX_A,MAX_B,MAX_r,MAX_INTENS);


for(theta=0;theta<MAX_THETA;theta++){

x=MAX_A+MAX_r*cs[theta];
if(x>a[0]-1||x<0) continue;
y=MAX_B+MAX_r*sn[theta];
if(y<a[1]-1&&y>0){
if(l==0){
P[x][y][0]=255;
P[x][y][1]=0;
P[x][y][2]=0;
}
else if(l==1){
P[x][y][0]=0;
P[x][y][1]=255;
P[x][y][2]=0;
}
else{
P[x][y][0]=0;
P[x][y][1]=0;
P[x][y][2]=255;
}
}
}
for(theta=0;theta<MAX_THETA;theta++){
x=MAX_A+MAX_r*cs[theta];
if(x>a[0]-1||x<0) continue;
y=MAX_B-MAX_r*sn[theta];
if(y<a[1]-1&&y>0){

if(l==0){
P[x][y][0]=255;
P[x][y][1]=0;
P[x][y][2]=0;
}
else if(l==1){
P[x][y][0]=0;
P[x][y][1]=255;
P[x][y][2]=0;
}
else{
P[x][y][0]=0;
P[x][y][1]=0;
P[x][y][2]=255;
}
}
}

for(i=-1;i<=1;i++)
for(j=-1;j<=1;j++)
for(k=-1;k<=1;k++){
if(MAX_A+i<0||MAX_A+i>a[0]-1) continue;
if(MAX_B+j<0||MAX_B+j>a[1]-1) continue;
if(MAX_r+k<0||MAX_r+k>MAX_R-1) continue;
intens[MAX_A+i][MAX_B+j][MAX_r+k] = 0;
}
}
printf("Hough逆変換を実行完了。\n");
}



void change_color(int a[],double** O,double*** P){
int i,j;
for(i=0;i<a[0];i++){
for(j=0;j<a[1];j++){
if(O[i][j]==0){
P[i][j][0]=0.0;
P[i][j][1]=0.0;
P[i][j][2]=0.0;
}
else {
P[i][j][0]=80.0;
P[i][j][1]=80.0;
P[i][j][2]=80.0;
// printf("P[%d][%d][%d]=%lf\n",i,j,0,P[i][j][0]);
}

}
}
}


この投稿にコメントする

削除パスワード

No.5066

Re:hough変換
投稿者---tana(2005/12/07 23:07:37)


void writefile3_double(FILE *outfile,char *argv[],int num,int a[],double*** N){
  int i,j,k;
  
  outfile = fopen(argv[num],"w");
  fprintf(outfile, "P3\n"); 
  fprintf(outfile, "%d %d\n",a[0],a[1]); 
  fprintf(outfile, "255\n"); 
  for(i=0;i<a[0];i++){
    for(j=0;j<a[1];j++){
      for(k=0;k<RGB;k++){
    fprintf(outfile,"%d ",(int)N[i][j][k]);
      }
    }
  }
  fclose(outfile);
}  

int calc_MAX_R(int a[],int MAX_R){
  if(a[0]==a[1])      MAX_R = a[0] / 2;    
  else if(a[0]>a[1])  MAX_R = a[1] / 2;
  else                MAX_R = a[0] / 2;
  return MAX_R;
}


void table (double sn[],double cs[],double sq[]){
  int i;
  for(i=0;i<MAX_THETA;i++){               
    sn[i] =sin(PIK*i);
    cs[i] =cos(PIK*i);
    //   printf("i=%d ,sn[%d]=%lf",i,i,sn[i]);

  }
  for(i=0;i<MAX_NIJYOU;i++)           
    sq[i] =i*i;
  //   printf("sq[%d]=%lf",i,sq[i]);
  printf("テーブル用意完了。\n");
}


void file_imformation(FILE *infile0,int argc,char *argv[],int a[]){
  int h=0,i,j,k,data;
  char A[4][100],unnec[100];
  
  printf("(プログラム名以外の)引数の総個数=%d\n",argc-1);
  for(i=1;i<argc;i++){
    printf("%d番目の引数=%s\n",i,argv[i]);
  }
  
  infile0 = fopen(argv[1],"r");
  if(NULL==fopen(argv[1], "r")){
    printf("ファイルが存在しません1\n");
    exit(1);
  }
  for(;;){
    fscanf(infile0,"%s",A[h]);
    if(strcmp(A[h],"#")==0)
      {
    fgets(unnec,100,infile0);
      }
    else{
      h++;
    }
    if(h==4){
      break;
    }
  }
  sscanf(A[1],"%d",&a[0]);
  sscanf(A[2],"%d",&a[1]);
  fclose(infile0);
}


void inputdata1(FILE *infile1 , char *argv[] , int a[],double*** M){
  int i,j,k,c=0,line=0;
  printf("\n画像間の差分をとります。\n");
  printf("画像1のファイル名を入力してください。\n");
  printf("(%s)\n",argv[1]); 
  infile1 = fopen(argv[1], "r");
  if(NULL==fopen(argv[1], "r")){
    printf("ファイルが存在しません1\n");
    exit(1);
  }
  
  

 for(i=0;i<3;i++){ 
     fscanf(infile1, "%*[\t\n]");
     fscanf(infile1,"%*[^\n]");
   }
                          
  for(i=0; i<a[0]; i++){
    for(j=0; j<a[1]; j++){
      for(k=0;k<RGB;k++){
    fscanf(infile1,"%lf",&M[i][j][k]);
      }
    }
  } 
}


void getmemory_sp(int a[],int**** N,int MAX_R){
  
  int i,j,k;
  *N = (int***)malloc(sizeof(int**)*a[0]);
  if(*N==NULL){
    perror("メモリの確保に失敗しました。\n");
    exit(1);
  }
  printf("メモリ確保開始\n");
  for(i=0 ; i < a[0] ;i++){
    (*N)[i] = (int**)malloc(sizeof(int*)*a[1]);
    if((*N)[i]==NULL) {
      perror("メモリの確保に失敗しました。\n");
      exit(1);}
    for(j=0 ; j < a[1] ; j++){
      (*N)[i][j] = (int*)malloc(sizeof(int)*MAX_R);
      if((*N)[i][j]==NULL)exit(1);
    }
  }
  printf("メモリ確保終了\n");
  for(i=0; i<a[0]; i++){
    for(j=0; j<a[1]; j++){
      for(k=0;k<MAX_R;k++){
    (*N)[i][j][k]=0;
      }
    }
  }
}

void getmemory2_double(int a[],double*** N){
  int i,j;
  *N = (double**)malloc(sizeof(double*)*a[0]);
  if(*N==NULL){
    perror("メモリの確保に失敗しました。\n");
    exit(1);
  }
  printf("メモリ確保開始\n");
  for(i=0 ; i < a[0] ;i++){
    (*N)[i] = (double*)malloc(sizeof(double)*a[1]);
    if((*N)[i]==NULL) {
      perror("メモリの確保に失敗しました。\n");
      exit(1);
    }
  }
  printf("メモリ確保終了\n");
 for(i=0; i<a[0]; i++){
    for(j=0; j<a[1]; j++){
      (*N)[i][j]=0;
    }
 }
}




この投稿にコメントする

削除パスワード

No.5067

Re:hough変換
投稿者---tana(2005/12/07 23:11:38)


void getmemory3_double(int a[],double**** N){
  int i,j,k;
  *N = (double***)malloc(sizeof(double**)*a[0]);
  if(*N==NULL){
    perror("メモリの確保に失敗しました。\n");
    exit(1);
  }
  printf("メモリ確保開始\n");
  for(i=0 ; i < a[0] ;i++){
    (*N)[i] = (double**)malloc(sizeof(double*)*a[1]);
    if((*N)[i]==NULL) {
      perror("メモリの確保に失敗しました。\n");
      exit(1);}
    for(j=0 ; j < a[1] ; j++){
      (*N)[i][j] = (double*)malloc(sizeof(double)*RGB);
      if((*N)[i][j]==NULL)exit(1);
    }
  }
  printf("メモリ確保終了\n");
  for(i=0; i<a[0]; i++){
    for(j=0; j<a[1]; j++){
      for(k=0;k<RGB;k++){  
    (*N)[i][j][k]=0;
      }
    }
  }
}




void leftmemory3_int(int a[],int*** N){
  int i,j;
  printf("メモリ開放開始\n");
  for(i=0 ; i < a[0] ; i++){
    for(j=0 ; j < a[1] ; j++){
      free(N[i][j]);
    }
    free(N[i]);
  }
  free(N);
  printf("メモリ開放終了\n");
}



void leftmemory2_double(int a[],double** N){
  int i;
  printf("メモリ開放開始\n");
  for(i=0 ; i < a[0] ; i++){
    free(N[i]);
  }
  free(N);
  printf("メモリ開放終了\n");
}


void leftmemory3_double(int a[],double*** N){
  int i,j;
  printf("メモリ開放開始\n");
  for(i=0 ; i < a[0] ; i++){
    for(j=0 ; j < a[1] ; j++){
      free(N[i][j]);
    }
    free(N[i]);
  }
  free(N);
  printf("メモリ開放終了\n");
}


void getmemory3_int(int a[],int**** N){
  int i,j;
  *N = (int***)malloc(sizeof(int**)*a[0]);
  if(*N==NULL){
    perror("メモリの確保に失敗しました。\n");
    exit(1);
  }
  printf("メモリ確保開始\n");
  for(i=0 ; i < a[0] ;i++){
    (*N)[i] = (int**)malloc(sizeof(int*)*a[1]);
    if((*N)[i]==NULL) {
      perror("メモリの確保に失敗しました。\n");
      exit(1);}
    for(j=0 ; j < a[1] ; j++){
      (*N)[i][j] = (int*)malloc(sizeof(int)*RGB);
      if((*N)[i][j]==NULL)exit(1);
    }
  }
  printf("メモリ確保終了\n");
}

void writefile2_double(FILE *outfile,char *argv[],int num,int a[],double** N){
  int i,j;
  
  outfile = fopen(argv[num],"w");
  fprintf(outfile, "P2\n"); 
  fprintf(outfile, "%d %d\n",a[0],a[1]); 
  fprintf(outfile, "255\n"); 
  for(i=0;i<a[0];i++){
    for(j=0;j<a[1];j++){
      fprintf(outfile,"%d ",(int)N[i][j]);
    }
    fprintf(outfile,"\n");
  }
  fclose(outfile);
}  



以上がプログラムです。二値化はうまく動作するのですが、
hough変換(Hough_TransformとinvHough_Transform)がうまく
動作してくれません。見苦しいプログラムだと思いますがどこが悪いのかアドバイスをいただけないでしょうか?


この投稿にコメントする

削除パスワード

No.5069

Re:hough変換
投稿者---RAPT(2005/12/07 23:14:49)


> うまく動作しなくて
あなたが投入した値と、あなたの想定した動きと、実際の動きを明記してください。
それから、開発環境(コンパイラ・OS等)も明記してください。



この投稿にコメントする

削除パスワード

No.5072

Re:hough変換
投稿者---tana(2005/12/07 23:47:31)


><pre>> うまく動作しなくて
あなたが投入した値と、あなたの想定した動きと、実際の動きを明記してください。
それから、開発環境(コンパイラ・OS等)も明記してください。</pre>
そうですね。環境はwindowsxpのコンパイラはborlandc++ 5.1.1 for win32を使っています。

実行結果についてですが、
例えば352*240画像で実際に実行してみると、
<pre>C:\Documents and Settings\Owner\sokken&gt;hough4 1.pgm 4.pgm 5.pgm
(プログラム名以外の)引数の総個数=3
1番目の引数=1.pgm
2番目の引数=4.pgm
3番目の引数=5.pgm
メモリ確保開始
メモリ確保終了
メモリ確保開始
メモリ確保終了
メモリ確保開始
メモリ確保終了
テーブル用意完了。
メモリ確保開始
メモリ確保終了

画像間の差分をとります。
画像1のファイル名を入力してください。
(1.pgm)
画像の平均輝度(ave):2
最適しきい値(saiteki_k):38
モノクロ画像から2値画像に変換しました。
Hough変換を実行中。
Hough変換実行完了
Hough逆変換を実行します
intens[167][152][116]=53
Hough逆変換を実行完了。
メモリ開放開始
メモリ開放終了
メモリ開放開始
メモリ開放終了
メモリ開放開始
メモリ開放終了
メモリ開放開始
メモリ開放終了
</pre>

という出力がでます。一見よさそうですが、実際は
(自分が想定した値は)intens[75][56][26]程度で
このプログラムの出力結果intens[167][152][116]と大きな開き
があります。この自分が想定した値というのは、画像より
読取った適当な値ですが、実際そのあたりにしか円が描けよう
がない画像なのです(実際画像がのせられないので苦しいですが)。
しかも半径rに相当する116という値で円が描けていれば
良いのですが円さえもかけてないのです。
 このほかの画像でも実験しましたが、ペイントで適当な丸を描いた
画像ではうまく動作(円描画成功)しましたが、それ以外では
うまく動作しませんでした。




この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧




掲示板提供:Real Integrity