二值图分割问题(300分)

  • 主题发起人 主题发起人 qdyoung
  • 开始时间 开始时间
Q

qdyoung

Unregistered / Unconfirmed
GUEST, unregistred user!
一个二维数组 A[m,n] 保存一个二值图像,值为1代表有象素,值为0代表没有象素,
其中有值为1的连续区域,比如
00001110001111000
00111110011100000
00001100001110000
就有两块连续的区域,要想把这些1的连续区域识别出来,并通过区域加点的链表或其它
数据结构表达出来,请问有没有现成的优化算法?
我有一个算法,但是很慢,600x400的要算10秒左右。
 
用四点或八点边缘跟踪算法
http://www.delphibbs.com/delphibbs/dispq.asp?lid=407206
http://www.delphibbs.com/delphibbs/dispq.asp?lid=075670
>>600x400的要算10秒左右
好像是太慢了...
 
我的好像就是上下左右搜索的
不知道哪儿有具体的例子
 
如果不长的话(< 2k),可以考虑把你的核心代码贴出来,大家帮你优化一下。(注意,只要
核心代码就可以了)
 
PDot = ^TDot;
//点指针
TDot = record //点类型
No: Integer;
//序号
Next: PDot;
//下一点指针
X: Integer;
Y: Integer;
RGBColor: TRGBColor;
KLColor: TKLColor;
IsSeperate: Boolean;
end;
PArea = ^TArea;
//区域指针
TArea = record //区域类型
No: Integer;
//区域序号 1-----
Description: string;
//描述
do
tNumber: Integer;
//点数
Next: PArea;
//下一区域指针
do
t: PDot;
//指向第一个点
end;
MyArray: array[1..txcl_object_width,1..txcl_object_high] of integer;
//目标真值图
var
i, j, k, k1, k2, k3, kk2, num: Integer;
//i列 j行
t, t1, t2, t3, tt2, newarea, pdtj: Boolean;//新区域
//找到新区域后找新区域的所有点
//本过程从第一行开始扫描,从左到右
label here1,here2;
begin
if not(FImageLoaded and FModelLoaded) then
exit;
Refresh;
//清除标记
do
Analyse(False);
ClearArea;
highlight_area:=nil;
Refresh ;
num:=0;
//ProgressBar.Position:=0;
//newarea:=True;
for j:=3 to txcl_object_highdo
begin
ProgressBar.Position:=j+200;
for i := 1 to txcl_object_widthdo
begin
newarea:=False;
if (i=154) and (j=167) then
begin
//showmessage('here')
end;
if (i=354) and (j=167) then
begin
//showmessage('here')
end;
if myarray[i,j]=1 then
//equal to 1 may be new area
begin
if j > 3 then
//不是第一行
begin
if i=1 then
pdtj:=(myarray[i,j-1]=1)
else
pdtj:= ((myarray[i-1,j]=1) or (myarray[i,j-1]=1));
if (not pdtj) then
//前面的点和上面的点不是区域点,则有可能是新区域点
begin
//found new area
if i = txcl_object_width then
newarea := True
else
begin
//可能是区域点,判断
t := True;
k := j - 1;
//行记数 先向上移一行
if k > 398 then
//last lin point
begin
newarea := True;
t := False;
end;
here2: ;
while tdo
//not last line point
begin
k:=k+1;
//行加1 向下移动
if (k > txcl_object_high) or (myarray[i,k]=0) then
//avoid over in loop
begin
newarea:=True;
//下面的行不是区域点,判定结束,出口
t := False;
//是新区域,返回
goto here2;
end
else
begin
// else
1
t3 := True;
t1 := True;
k1 := i;
//右移指针
k3 := i;
//左移指针
while t1do
begin
k1 := k1 + 1;
//向右移动
if (myarray[k1,k]=0) or (k1>599) then
//右移到头
begin
t1:=False;
//出右移循环
end
else
begin
//再向上查找
t2:=True;
k2:=k;
while t2do
begin
k2:=k2-1;
if (k2<3) or (myarray[k1,k2]=0) then
t2 := False
end;
if k2 < j-1 then
//not new area
begin
newarea := False;
//t2 := False;
t1 := False;
t3 := False;
t := False;
end
else
begin
//t2 := False;
end;
end;
//再向上查找
end;
//while t1
while t3do
begin
k3 := k3-1;
//向左移动
if (myarray[k3,k]=0) or (k3<1) then
//左移到头
begin
t3:=False;
//出左移循环
end
else
begin
//再向上查找
tt2:=True;
kk2:=k;
while tt2do
begin
kk2:=kk2-1;
if (kk2<3) or (myarray[k3,kk2]=0) then
tt2 := False;
end;
if kk2<j then
//not new area
begin
newarea := False;
//tt2 := False;
t3 := False;
//t1 := False;
t := False;
end
else
begin
//tt2 := False;
end;
end;
//再向上查找
end;
//while t3
end;
//else
1
end;
//not last line point
end;
//可能是区域点,判断
end;
//前面的点和上面的点不是区域点,则有可能是新区域点
end //不是第一行
else
//first line to process
begin
newarea := False;
if i = 1 then
newarea := True
else
if myarray[i-1,j]<>1 then
//前面一个不是
begin
k := j;
//k是行
t := True;
while tdo
begin
k := k+1;
//向下移
if (myarray[i,k]=0) or (k>599) then
begin
newarea:=True;
t:=False;
end
else
begin
//else
2
t1:=True;
//左循环
k1:=i;
//k1是列
while t1do
begin
k1:=k1-1;
//向左移
if (k1<1) or (myarray[k1,k]=0) then
begin
t1:=False;
end
else
begin
//再向上
k2:=k;
//行
t2:=True;
while t2do
begin
k2:=k2-1;
if (k2<j) or (myarray[k1,k2]=0) then
t2:=False;
end;
if k2<j then
//not new area
begin
newarea:=False;
//t2 := False;
t1 := False;
t := False;
end
else
begin
//t2 := False;
end;
end;
//再向上
end;
//while t1
end;
//else
2
end;
//while t
end;
//前面一个不是
end;
//=1 if
end;
////first line to process end of if myarray[i,j]=1
if newarea then
begin
// showmessage('found new area');
//DrawDot(i,j,clred);
//DrawDot(i,j-1,clred);
//DrawDot(i,j+1,clred);
//DrawDot(i-1,j,clred);
//DrawDot(i+1,j,clred);
AddArea(i,j);
num:=num+1;
end;
end;
//j loop
end;
//i loop
 
天!一个过程搞定所有功能,没有内部分工(我认为Pascal函数、过程的可嵌套性太可爱了,
比C好用多了)。看起来太费力,得,我还是从头写吧。
 
多人接受答案了。
 
后退
顶部