直線検出のハフ変換プログラム(delphi)

このQ&Aのポイント
  • delphiで直線検出のハフ変換のプログラムを書いているが、スタックオーバーフローが発生する。
  • スタックオーバーフローが起こるのは2次元配列のcounterの部分であり、回避方法を知りたい。
  • ハフ変換の実行とハフ逆変換の実行の手順を載せている。
回答を見る
  • ベストアンサー

直線検出のハフ変換プログラム(delphi)

ただいまdelphiで直線検出のハフ変換のプログラムを書いているのですが、コンパイルし、実行しようとするとスタックオーバーフローになってしまいます。 おそらく2次元配列のcounterの部分だと思うのですが、どなたか回避の仕方お分かりになるでしょうか? ご存じの方いらっしゃいましたら教えて下さい。 下記にハフ変換の部分のコードを載せます。 他にも何か気付いた点ありましたらご指摘お願いいたします。 ○直線検出のハフ変換○ var i, j, k, n: Integer; rx, ry: Integer; clr: tcolor; R: longint; counter_max: Integer; THETA_RESOLUTION, RHO_RESOLUTION, LNUMBER_MAX: Integer; pai: Double; theta, rho: Integer; theta_max, rho_max, count: Integer; theta_cut, rho_cut: Integer; counter:array[0..1023,0..1999] of Integer; //直線検出のためのカウンタ sn:array[0..1023] of Double; //sin cs:array[0..1023] of Double; //cos begin THETA_RESOLUTION:=1024; //thetaの範囲は0から1023まで RHO_RESOLUTION:=2000; //rhoの範囲は-1000から999まで LNUMBER_MAX:=15; //検索する電線の数は15まで pai:=PI / THETA_RESOLUTION; //π÷THETA_RESOLUTION for i:=0 to 1023 do //sinとcosのテーブルを用意 begin sn[i]:=Sin(pai*i); cs[i]:=Cos(pai*i); end; //ハフ変換の実行// for rx:=0 to 639 do begin for ry:=0 to 479 do begin clr:=image1.Canvas.Pixels[rx,ry]; R:=colortorgb(clr); if(getrvalue(R)=0)and(getgvalue(R)=0)and(getbvalue(R)=0) then //黒である for theta:=0 to 1023 do begin rho:=Trunc(rx*cs[theta]+ry*sn[theta]+0.5); counter[theta,rho+1000]:=counter[theta,rho+1000]+1; end; end; end; //ハフ逆変換の実行// for n:=0 to 14 do begin //counterが最大になるtheta_maxとrho_maxを求める// counter_max:=0; for theta:=0 to 1023 do begin for rho:=-RHO_RESOLUTION div 2 to RHO_RESOLUTION div 2-1 do begin if(counter[theta,rho+RHO_RESOLUTION div 2] > counter_max) then begin counter_max:=counter[theta,rho+RHO_RESOLUTION div 2]; theta_max:=theta; rho_max:=rho; count:=counter_max; end; end; end; //counter[theta_max,rho_max]の近傍を0にする// for i:=-20 to 20 do begin for j:=-10 to 10 do begin theta_cut:=theta_max+i; rho_cut:=rho_max+j; if(theta_cut < 0) then begin theta_cut:=theta_cut+THETA_RESOLUTION; rho_cut:=-rho_cut; end else if(theta_cut > THETA_RESOLUTION-1) then begin theta_cut:=theta_cut-THETA_RESOLUTION; rho_cut:=-rho_cut; end; counter[theta_cut,rho_cut+RHO_RESOLUTION div 2]:=0; //削除する end; end; //ハフ逆変換した結果の表示// if(theta_max<>0) then //垂線の線を描く begin for rx:=0 to 639 do begin ry:=Trunc((rho_max-rx*cs[theta_max])/sn[theta_max]+0.5); if(ry>=480)or(ry<0) then continue; image1.Canvas.Pixels[rx,ry]:=RGB(255,0,0); end; end; if(theta_max<>THETA_RESOLUTION div 2) then //水平の線を描く begin for ry:=0 to 479 do begin rx:=Trunc((rho_max-ry*sn[theta_max])/cs[theta_max]+0.5); if(rx>=640)or(rx<0) then continue; image1.Canvas.Pixels[rx,ry]:=RGB(255,0,0); end; end; //直線を形成するピクセルが60個未満になったら表示しない// if count<60 then break; end; end;

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

もう見てないかもしれませんが、 counter:array of array of Integer; と、動的配列にして、使う前に SetLength(counter ,THETA_RESOLUTION,RHO_RESOLUTION ); で確保してください。少なくとも私の環境はこれで動作します。まだスタックが足りない場合には大きい配列は全部動的配列に変えてください。 Windowsは静的に巨大な配列は確保できません。ヒープ領域に確保します。

tweety36
質問者

お礼

ありがとうございました。 参考になりました。

関連するQ&A

  • DelphiのプログラムをVB・C#・Javaにかきかえる時の記述

    学校の課題で、 わからないのでおしえてください。 program test; var i,sum:integer; begin sum:0; for i=1 to 100 do if i mod 2 =0 then sum:=sum+i end. というDelphiでのプログラムを、Visual Basic,C#,Java言語で 同じような動作をするように書くにはどのように書いたらいいのか教えてください。

  • Pascalでの選択ソート

    program sort(input, output); const numofdata =100 ; var d: array [1..numofdata] of integer; i,j,k: integer; tmp: integer; begin for i:=1 to numofdata do begin read(d[i]); end; for i:=1 to numofdata-1 do begin j:=i; for k:=i+1 to numofdata do begin if d[j]>d[k] then j:=k; end; tmp:=d[j]; d[j]:=d[i]; d[i]:=tmp; end; for i:=1 to numofdata do begin writeln(d[i]) end end. このプログラムを、データ数(1個から最大10000個まで)を最初に入力できるように変更するには、どうすればよいのでしょうか。教えてください。

  • Pascal言語で小町算

    Pascal言語で、『1~9の順に数字を並べ、+、-を補い式を作り、 値が100になる組み合わせをすべて出力するプログラムを作成せよ(例:12 - 3 - 4 + 5 - 6 + 7 + 89 = 100)。』 という課題が出ました。自分なりに組んでみたのですが、 12個あると聞いたのに、4個しか出力されません><; どこが間違っているのかご教授いただけると幸いですっ ------------------------------------------------------- program KomachiZan(output); var i,s:integer; var sign:array[1..9] of integer; var x,n:longint; begin writeln('< 小町算 -Komachi Zan- >'); for i:=1 to 9 do sign[i]:=-1; repeat x:=0; n:=0; s:=1; for i:=1 to 9 do begin if sign[i]=0 then n:=10*n+1 else begin x:=x+s*n; s:=sign[i]; n:=i; end; end; x:=x+s*n; if x=100 then begin for i:=1 to 9 do begin if sign[i]=1 then write(' + ') else if sign[i]=-1 then write(' - '); write(i); end; writeln(' = 100'); end; i:=9; s:=sign[i]+1; while s>1 do begin sign[i]:=-1; i:=i-1; s:=sign[i]+1; end; sign[i]:=s; until sign[1]>=1; end. -------------------------------------------------------

  • プログラム(tmp)の意味について

    プログラム(tmp)の意味について begin for i:=1 to n-1 do for j:=i+1 to n do if a[i]>a[j] then begin tmp:=a[i] ; a[i]:=a[j] ; a[j]:=tmp end というプログラムがあるのですが、tmpがどういう役割を持っているのかよくわかりません。 このプログラムでtmpの辺りのプログラムがどのような意味を持っているか教えてもらえませんか?

  • 最大公約数を再帰で求める(pascal)

    入力した整数値の最大公約数を出力するプログラムを再帰呼び出しの形式で作れ、という課題が出ました。 再帰でない形式は下のように作れたのですが、再帰形式がどうしてもできません。どなたかご教授ください。 function gcd(a,b:integer):integer; {関数部} var tmp:integer; begin if a<b then begin tmp:=b; b:=a; a:=tmp end; repeat tmp:=b; b:=a mod b; a:=tmp until b=0; gcd:=a end; repeat {計算部、i=n=入力した個数、max=入力できる最大数} i:=i+1; n:=n+1; data[i]:=x; writeln('値:'); readln(x); until (x=0) or (i=max); if i>=2 then begin p:=gcd(data[1],data[2]); if i>=3 then begin for i:= 3 to n do begin p:=gcd(p,data[i]) end; writeln('最大公約数:',p) end else begin writeln('最大公約数:',p) end;

  • Delphiに関して  「このプログラム解読できません!」

    こんにちは。このプログラムが解読不可です。StringGridの1列目と2列目の各セルの内容を右寄せにする ということで、実行させると確かにそうなるのですが、どういう構造かいまいち分かりません。特に 'Rect.Top:=Rect.Top+2;' のところなんて"なんで+2なの~?"ってホントに謎です。gdFixedとかFillRectとかヘルプに書いてあることとなんか違う気がして....DT_RIGHTもわかりません。 このプログラムの解説お願いします! procedure TForm1.StringGrid1DrawCell(Sender:TObject;ACol,ARow:Integer;Rect: TRect; State: TGridDrawState); begin If Not (gdFixed In State) And (ACol In [1,2]) Then Begin StringGrid1.Canvas.FillRect(Rect); Rect.Top := Rect.Top + 2; If (ACol = 1)or(ACol = 2) Then DrawText(StringGrid1.Canvas.Handle, PChar(StringGrid1.Cells                 [ACol,ARow]),Lengthend(StringGrid1.Cells                [ACol,ARow]),Rect,DT_RIGHT) end; end;

  • [Delphi] StrToInt64がしたい

    16バイトの文字列を8バイトのint64型に変換したいです 下記コードのようにやってみたのですが上手く動きません 何か間違っている、他に方法などがありましたら教えてください。 function HexToInt64(const S: string): Int64; const hexstr : string = '0123456789abcdefABCDEF'; var I,L,h,m: Integer; j: Int64; p: PByteArray; test: string; begin result:=-1; p := @j; L:=Length(s); test:= ''; if L <> 16 then Exit; for i:=1 to L do if Pos(s[i], hexstr)<=0 then Exit; h:= strtoint('$' + Copy(S,0,8)); CopyMemory(@p[0], @h, 8); m:= strtoint('$' + Copy(S,9,8)); CopyMemory(@p[8], @m, 8); CopyMemory(@j, @p, 16); result:=j; end;

  • Delphi6 ループ中にキー入力

    Delphi 6 です。 for next などのループの中で、stringgridのセルをEnterキーで選択させたい時、選択されるまで(キーが押されるまで)処理を進めたくない方法は、どうするんでしょうか? flg:=false; for i:=1 to 100 do begin ~諸々の処理で flg:=true; ~ if flg=true then x[i]:= stringgridの選択されたRow番号(はじめからフォーカスされている番号でなく) ~諸々の処理で flg:=false; ~ end;

  • Delphi の文字列型stringについて

     以下のコードで string は AnsiString、Char は AnsiChar です。  buf: array[1..16] of Char; を  buf :string[16]; と宣言しては意図通りに動きません。なぜでしょう?  TPerson = record   Age : Integer;   Name: string[30];  end;  TPersonArray = array of TPerson; procedure TForm1.Nantoka; var  i,j: Integer;  buf: array[1..16] of Char; //buf :string[16]; ではダメ!  Fs : TFileStream;  R : TPersonArray; begin  SetLength(R, 100); //配列のサイズを決定  for i := 0 to 99 do //動的配列の添え字は常に0から始まる  begin   R[i].Age := Random(100);   for j := 1 to 16 do buf[j] := Chr( Random(26)+97 );   //buf :string[16]; では buf[j] が'文字'にならない!   R[i].Name := 'Stream '+buf;  end; end;

  • Delphi for文

    これって、Delphiのバグですか?特性ですか? procedure TForm1.Button1Click(Sender: TObject); begin test(); end; //-------------------------- procedure TForm1.test(); var k,x:integer; begin paintbox1.Canvas.pen.Color:=clBlack ; x:=0; for k:=1 to 3 do begin paintbox1.Canvas.moveto(x,0); paintbox1.Canvas.lineto(x,paintbox1.Height); x:=x+2; end; end; forループ内にブレークポイントを付けて「k」の値の変化を見ると、3,2,1と逆順になります。 「x:=x+2」を「x:=x+k」に変更すると、1,2,3と普通の順になります。 なぜ、こうなるのか? 対処法はありますか? Delphi Ver6・ターボDelphi どちらも同じ状況です。

専門家に質問してみよう