• 締切済み

円のHough変換をC言語で

つくってみたのですが、ループが多すぎて実行時間が30分以上はかかりそうです。 ループをどうやって減らせばよいか、アドバイスお願いします。 円は(x-a)^2+(y-b)^2=400です。 以下、現在のプログラムの手順 1.b[x][y][a]を初期化(x,y,aでループ) 2.画素値が0のとき、b[x][y][a]=(円の式をb=~~の形にしたときの右辺)を行う(x,y,aでループ) 3.b[x][y][a]の頻度をカウントする。(カウントするbの値,x,y,aでループ。ここが時間かかる。) 4.逆変換する。まだ試してないけどxでしかループしないので時間はかからないはず。

みんなの回答

  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.3

下記サイトのプログラムと見比べてみると、 > 2. b[x][y][a]=(円の式をb=~~の形にしたときの右辺)を行う の表現法がムダっぽいような。 x,y,r(半径)で計算してみては。 「Visual C++ 2010 Express を用いた易しい画像認識(2)」 http://homepage3.nifty.com/ishidate/vcpp10_r2/vcpp10_r2.htm 170x60くらいなら、C++で書いたプログラムで、1秒かからなかった。 スクリプト言語の中でもとくに遅いといわれる)rubyでも、1秒かからないですね。 # 640x480x(半径)40のデータでも10秒ほど。

参考URL:
http://ideone.com/13V2Y3
全文を見る
すると、全ての回答が全文表示されます。
回答No.2

コンパイラは何を使用されていますか? ダミー変数を憶測で用意してコンパイルしてみましたがVS2010では通りませんでした。 また、色々細工をして「こうだろう」で動かした結果、定義や内容が分からない変数(rやb)がネックで、どうもうまく動作しませんでした。 できれば全てのソースコードと実行結果の一例が欲しいのですが、無理そうでしたら今回はお力になれそうにありません。 一応性能改善のアドバイスとしては、 ・bh配列の初期化 → memset関数で初期化することで高速化可能 ・Hough変換部分 → 変数iは加算なのでsqrt部を事前計算後、iを加算しながらループすることで高コストの計算回数を抑えられます(但しiのループを内側に持ってくる必要あり)。このループが変数rとの兼ね合いがある場合は難しいです。 ・カウント部分 → 少なくとも「カウントするbの値,x,y,aでループ」から「カウントするbの値」を排除するようにプログラムを構成する必要があります。例えば「x,y,aでループ」の中でうまいこと数えてやるようなイメージです。

pgmbgn
質問者

補足

わざわざ試行錯誤までありがとうございます・・・。 cygwinのgccです。 全コードは字数オーバーになるので・・・ rは画素値を入れるポインタです。 bhはbの値です。bがもともと前の部分で使われていたので・・・ カウント部分の改善を試みているのですが、うまいこと数えられません・・・。

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

ソースコードは公開できませんか? アルゴリズムを知らないので的確なアドバイスはできませんが、論理の最適化であればできます。 ちなみに30分っていう時間はどうやって推測したのでしょう? 250 * 1000 * 1000の配列で、 No2(初期化)、No3(条件分岐と演算)を擬似的にやってみましたが、5秒程で終わりました。 (勿論高コストな計算が入るならそれだけかかっても不思議じゃないですが)

pgmbgn
質問者

補足

該当部分(1,2,3,4)を抜き出しました。 時間推測は、カウントの部分で、printf("debug\n");(今はかいてない)をループさせ、その表示間隔からしました。間隔からして50分ぐらいかかりそうでしたが、出力しない場合は早まると思って、30分ぐらいかな、と。 以下がソースコードです。よろしくお願いします・・・。 /*初期化*/ int a,pic[170][60]; int (*bh)[170][60][11200]=malloc(sizeof(*bh)); for(i=0 ; i<pPic->y ; i++){ for(j=0 ; j<pPic->x ; j++){ for(a=0;a<size;a++){ (*bh)[j][i][a]=0; } } } // printf("debug\n"); for(i=0 ; i<pPic->y ; i++){ for(j=0 ; j<pPic->x ; j++){ if(*r==0){ for(a=0;a<size;a++){ (*bh)[j][i][a]=(int)(-sqrt(400-pow((j-a),2))+i);//Hough変換 } r++; } } } //printf("debug\n"); int b_atai,B_MAX=0,A_MAX=0,COUNT_MAX=0; /*カウント*/ int count[size],ah[size]; for(b_atai=0;b_atai<=size;b++){ for(i=0 ; i<pPic->y ; i++){ for(j=0 ; j<pPic->x ; j++){ for(a=0;a<size;a++){ if(b_atai==(*bh)[j][i][a]){ count[b_atai]++; ah[b_atai]=a; } } } } if(count[b_atai]>=COUNT_MAX){ COUNT_MAX=count[b_atai]; B_MAX=b_atai; A_MAX=ah[b_atai]; } } // printf("debug\n"); /*Hough逆変換*/ int y=0; for(j=0;j<pPic->x;j++){ y=(int)(sqrt(400-pow((j-A_MAX),2))+B_MAX); printf("%d %d\n",j,y); }

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 円のハフ変換をC言語で

    r^2=(x-a)^2+(y-b)^2 を変形して b=√(r^2-(x-a)^2)+y にしました。課題ではr=10と指定されていて、 b=√(100-(x-a)^2)+y となります。これをa,b平面にプロットすればいいのですが、 画像平面のxとyというのがいまさら分かりません。 画素値をどう入力すればいいのでしょうか。 例えば1行1列目の画素値をwとしたとき、 x[1]=w、y[1]=w とすればいいのでしょうか。 ご回答お願いします。

  • 対数変換について

    この公式を対数変換して、右辺をxの一次式にすることはできるのでしょうか。 Y=1-(1-e^(-x/a))^b しばらくにらめっこしていましたが、解けそうもないので、どなたか教えてください。

  • C言語教えてください。

    (1)二次方程式y=a*x*x+b*x+cについて、a=1.0,b=2.0,c=3.0として、x=1.1,2.2,3.3,4.4のときのyをもとめる計算を行い、式と係数値とxと対応するyの値を表示するプログラムを作成せよ。 (2)xを与えて、xの2乗、3乗を計算し、xと対応する結果を表示するプログラムを作成せよ。なお、x=3,5,7,9とする。

  • C言語のポインタの考え方について

    ポインタについて理解ができていないのでお聞きしたいのですが 値を交換する関数のプログラミングでこの場合ポインタ で以下にしないといけないと思います。 #include<stdio.h> void swap(int *a int *b){ int c; c=*a; *a=*b; *b=c; } main(){ int x,y; x=123; y=456; swap(&x,&y); printf("x = %d, y = %d\n", x, y); } またポインタを使用せず以下のプログラムではなぜダメのでしょうか。 よろしくお願い致します。 #include<stdio.h> void swap(int a int b){ int c; c=a; a=b; b=c; } main(){ int x,y; x=123; y=456; swap(x,y); printf("x = %d, y = %d\n", x, y); }

  • 一次変換 線形変換

    行列 A= 1 -4    4 1 で表される線形変換がありその変換で 円 x^2+y^2=1はどのような図形に写されるか求める問題で、 (x')=(1 -4 )(cost) (y')=(4  1 )(sint) より (x')^2+(y')^2=17 よって x^2+y^2=17と解答ではそうなっています。 costやsintはどこから来たのでしょうか? Aが直交行列だからなのですか? もうひとつ B=1 -2   -2 4 の場合の答えを教えてください。 Aのようには解けないので困ってます。

  • 「解きながら学ぶC言語」という本の問題8-3

    2つの値の大きい方の値を返すマクロを以下のように定義! #define max(x, y) ((x) > (y) ? (x) : (y)) このマクロを利用してmax(max(max(a, b), c), d)を展開すると ((((((a) > (b) ? (a) : (b))) > (c) ? (((a) > (b) ? (a) : (b))) : (c))) > (d) ? (((((a) > (b) ? (a) : (b))) > (c) ? (((a) > (b) ? (a) : (b))) : (c))) > (d)) このようになる。 そこで質問ですが、展開後の最後の部分、 (c))) > (d))は、不等号(>)ではなくコンマ(:)ですよね? これは参考書のミスということでよろしいんでしょうか? 少々腑に落ちないので質問させていただきました。 長々と長文申し訳ございません。 ご回答宜しくお願いします!

  • c言語の問題です。解説と解答をお願いします

    (1) doube a[3][4]で宣言された2次元配列の要素a[y][x]に割り当てられるメモリのアドレス&a[y][x]を数式で表せ。x∈{0,1,2,3},y∈{0,1,2}である。 (2) 下記の宣言文によって複数個の配列要素に初期値を代入した。各配列要素に代入される値を説明しなさい。 char b[]={‘X’,’Y’,’Z’}; char c[]=“xyz”; char *d[]={“ONE”,”TWO”,”THREE”}; int e[3][2]={1,3,5,7,9,11}; お願いします。

  • 楕円を円に変換する問題です。

    1次変換 A=(1      -α) (β   √3・γ) によって楕円3x^2+9y^2=1を原点を中心とする半径1の円になるとき α,β,γを求めよ。ただしα、β、γは正の実数とする。 という問題です。 (X,Y)を変換後の座標としますと、X^2+Y^2=1・・(1)が成り立ちます。 又、楕円は(1/√3 , 0) (0 , 1/3)を通りますので (X,Y)=(1/√3 , 1/√3・β)   ・・(2) (X,Y)=(α/3 ,√3・γ/3)    ・・(3) が成り立ちます。 (2)を(1)に代入しβ=√2を導出することはできたのですが、(3)を(1)に代入したところで詰まってしまいました。 ご回答よろしくお願いします。

  • 円の交点

    2円x^2+y^2=25,(x-a)^2+(y-2)^2=9が、2点A、Bで交わっている時、ABの長さが最大になる時のaの値を求めよ。 ご教示、宜しくお願い致します。

  • 配列のプログラム(C言語)

    実数yの値をキーボードから入力し、数列an=n+1(n=0.1.2.・・・.8.9)を係数にもつ多項式 f(y) = a9yの9乗 + a8yの8乗 +・・・+ a1y + a0 の値を計算して画面に表示するプログラムをforのループを使って教えてください。