直線検出のハフ変換プログラム(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;
お礼
やっぱりだめでした。 別の方法も探してみます。
補足
回答ありがとうございます。 >・・・エンコードしたファイル名の文字列をそのまま渡しているの・・・ 結果を見るとそのようになっているようです。 この書き方を紹介しているHPでは「Create とした後に、再度、ファイル名を指定」とありましたが、Sampleでは上記書き方になっていました。 ということは、「再度、ファイル名を指定」しているつもりがCreateと同時にエンコードしているようですね。 とういことで、先ほどから「再度、ファイル名を指定」をやろうとしているのですが、まだうまくいきません。