性格いい人が優勝

ただいま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;

A 回答 (1件)

もう見てないかもしれませんが、



counter:array of array of Integer;

と、動的配列にして、使う前に

SetLength(counter ,THETA_RESOLUTION,RHO_RESOLUTION );

で確保してください。少なくとも私の環境はこれで動作します。まだスタックが足りない場合には大きい配列は全部動的配列に変えてください。

Windowsは静的に巨大な配列は確保できません。ヒープ領域に確保します。
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/01/29 17:57

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!