我从网上阅读张舜的细化算法,并编写perl代码来细化图像。但是当代码运行时,代码会导致区域的过度侵蚀。下面的ascii图片就是例子。有人会告诉我代码有什么问题。非常感谢。
Before thinning ********** ********** ********** ********** ********** ********** ********** ********** ***###*#** **##**###* *##****### *#******#* *##****##* *##****##* **######** ***####*** **##*###** *##****##* *#******## ##******## ##*****### *##****##* **######** ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** After thinning ********** ********** ********** ********** ********** ********** ********** ********** ***###**** **#***##** *#*****### ********** ********** *******#** ******#*** ***###**** **#**###** *#*****##* ********## #*******## ##*******# *##****##* **#####*** ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** **********
代码如下。
##image array length: 0-37,image array width: $div[$idx]->{'R'}和$div[$idx]->{'L'}
##image array: $div[$idx]->{'A'}
while($flag eq 'Y'){
my $diff= $div[$idx]->{'R'} - $div[$idx]->{'L'};
my $ra= $div[$idx]->{'A'};
$flag= 'N';
for($y=1; $y<= 36; $y++){
for($x=1; $x<= $diff-1; $x++){
my $np1=0;
my $sp1=0;
my $cond1= 0;
my $cond2= 0;
my $p1= $ra->[$y][$x];
my $p2= $ra->[$y-1][$x];
my $p3= $ra->[$y-1][$x+1];
my $p4= $ra->[$y][$x+1];
my $p5= $ra->[$y+1][$x+1];
my $p6= $ra->[$y+1][$x];
my $p7= $ra->[$y+1][$x-1];
my $p8= $ra->[$y][$x-1];
my $p9= $ra->[$y-1][$x-1];
if($p1 ne $mark){next;}
if($p2 eq $mark){$np1++;}
if($p3 eq $mark){$np1++;}
if($p4 eq $mark){$np1++;}
if($p5 eq $mark){$np1++;}
if($p6 eq $mark){$np1++;}
if($p7 eq $mark){$np1++;}
if($p8 eq $mark){$np1++;}
if($p9 eq $mark){$np1++;}
if(($p2 eq $unmark)&&($p3 eq $mark)){$sp1++;}
if(($p3 eq $unmark)&&($p4 eq $mark)){$sp1++;}
if(($p4 eq $unmark)&&($p5 eq $mark)){$sp1++;}
if(($p5 eq $unmark)&&($p6 eq $mark)){$sp1++;}
if(($p6 eq $unmark)&&($p7 eq $mark)){$sp1++;}
if(($p7 eq $unmark)&&($p8 eq $mark)){$sp1++;}
if(($p8 eq $unmark)&&($p9 eq $mark)){$sp1++;}
if(($np1 >= 2)&&($np1 <= 6)){$cond1++; $cond2++;}
if($sp1 eq 1){$cond1++; $cond2++;}
if(($p2 eq $unmark)||($p4 eq $unmark)||($p6 eq $unmark)){$cond1++;}
if(($p4 eq $unmark)||($p6 eq $unmark)||($p8 eq $unmark)){$cond1++;}
if(($p2 eq $unmark)||($p4 eq $unmark)||($p8 eq $unmark)){$cond2++;}
if(($p2 eq $unmark)||($p6 eq $unmark)||($p8 eq $unmark)){$cond2++;}
if($cond1 eq 4){
$div[$idx]->{'A'}->[$y][$x]= $unmark;
$flag= 'Y';
}
if($cond2 eq 4){
$div[$idx]->{'A'}->[$y][$x]= $unmark;
$flag= 'Y';
}
}
}
}
更新 我修改了我的代码。它似乎工作。但我不知道它是否正常工作。 任何建议。非常感谢。
sub thinning{ my $idx= shift; my $flag= 'Y'; my @unmarklist; my $aheight= 37; ##0..37 my $awidth= $div[$idx]->{'R'} - $div[$idx]->{'L'}; while($flag eq 'Y'){ $flag= 'N'; my $ra= $div[$idx]->{'A'}; for $y(1..$aheight-1){ for $x(1..$awidth-1){ my $np1=0; my $sp1=0; my @neighbors; my $pixel= $ra->[$y][$x]; $neighbors[2]= $ra->[$y-1][$x]; $neighbors[3]= $ra->[$y-1][$x+1]; $neighbors[4]= $ra->[$y][$x+1]; $neighbors[5]= $ra->[$y+1][$x+1]; $neighbors[6]= $ra->[$y+1][$x]; $neighbors[7]= $ra->[$y+1][$x-1]; $neighbors[8]= $ra->[$y][$x-1]; $neighbors[9]= $ra->[$y-1][$x-1]; if($pixel ne $mark){next;} for $i(2..9){if($neighbors[$i] eq $mark){$np1++;}} if(($np1 >= 2)&&($np1 <= 6)){ for $i(2..8){if(($neighbors[$i] eq $unmark)&&($neighbors[$i+1] eq $mark)){$sp1++;}} if(($neighbors[9] eq $unmark)&&($neighbors[2] eq $mark)){$sp1++;} if($sp1 == 1){ if((($neighbors[2] eq $unmark)||($neighbors[4] eq $unmark)||($neighbors[6] eq $unmark))&& (($neighbors[4] eq $unmark)||($neighbors[6] eq $unmark)||($neighbors[8] eq $unmark))){ push(@unmarklist, [$y, $x]); $flag= 'Y'; } } } } } for $i(0..$#unmarklist){ my $y= $unmarklist[$i]->[0]; my $x= $unmarklist[$i]->[1]; $div[$idx]->{'A'}->[$y][$x]= $unmark; } @unmarklist=(); my $ra= $div[$idx]->{'A'}; for $y(1..$aheight-1){ for $x(1..$awidth-1){ my $np1=0; my $sp1=0; my @neighbors; my $pixel= $ra->[$y][$x]; $neighbors[2]= $ra->[$y-1][$x]; $neighbors[3]= $ra->[$y-1][$x+1]; $neighbors[4]= $ra->[$y][$x+1]; $neighbors[5]= $ra->[$y+1][$x+1]; $neighbors[6]= $ra->[$y+1][$x]; $neighbors[7]= $ra->[$y+1][$x-1]; $neighbors[8]= $ra->[$y][$x-1]; $neighbors[9]= $ra->[$y-1][$x-1]; if($pixel ne $mark){next;} for $i(2..9){if($neighbors[$i] eq $mark){$np1++;}} if(($np1 >= 2)&&($np1 <= 6)){ for $i(2..8){if(($neighbors[$i] eq $unmark)&&($neighbors[$i+1] eq $mark)){$sp1++;}} if(($neighbors[9] eq $unmark)&&($neighbors[2] eq $mark)){$sp1++;} if($sp1 == 1){ if((($neighbors[2] eq $unmark)||($neighbors[4] eq $unmark)||($neighbors[8] eq $unmark))&& (($neighbors[2] eq $unmark)||($neighbors[6] eq $unmark)||($neighbors[8] eq $unmark))){ push(@unmarklist, [$y, $x]); $flag= 'Y'; } } } } } for $i(0..$#unmarklist){ my $y= $unmarklist[$i]->[0]; my $x= $unmarklist[$i]->[1]; $div[$idx]->{'A'}->[$y][$x]= $unmark; } @unmarklist=(); } }
答案 0 :(得分:6)
您在实施算法时犯了几个错误:
您无法修改$ra
。如果这样做,那么当您擦除一个像素时,您将更改其后处理的像素的条件,这会导致错误向下和向右蔓延。
不应在同一循环中检查您的$cond1
和$cond2
条件。相反,必须使用$cond1
条件处理整个图像,然后使用$cond2
条件处理整个图像,并根据需要重复。
当您计算连通性时,您错过了$p9
为“取消标记”并且$p2
为“标记”的情况 - 您忘记绕圈子走了一圈。
在纠正所有这些错误后,看起来事情正在发挥作用。
还有一些建议:
eq
用于数字 - 请使用==
运算符进行数字比较。$cond1
和$cond2
变量,而是使用&&
或and
逻辑运算符 - 它们将使您的代码更易于阅读,并避免不必要的工作for ($x = lower; $x <= $upper; $x++)
。for $x (lower .. upper)
*
和#
更改为0和1,然后在输出中再次返回,则可以通过将if ($pixel eq $mark)
替换为if ($pixel)
来使更多逻辑更容易阅读$p1
等等。$p9
到$p1
等一系列编号变量。如果调用$pixel
$p2
且$p9
到@neighbors
是一个名为$np1
的数组,则可以重写十八行以计算$sp1
和{ {1}}分为三行。