0 perl image-manipulation image image-processing
我从网上读了张舜的细化算法并编写了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';
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
更新: 我修改了我的代码.它似乎工作.但我不知道它是否正常工作.任何建议.非常感谢.
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=();
}
}
你在实现算法时犯了几个错误:
您无法$ra就地修改.如果这样做,那么当您擦除一个像素时,您将更改其后处理的像素的条件,这会导致错误向下和向右蠕动.
您$cond1和$cond2条件不应该在同一个循环中检查.相反,必须使用$cond1条件处理整个图像,然后根据$cond2条件处理整个图像,并根据需要重复.
当你计算连通性时,你错过了$p9"unmark"并且$p2是"mark"的条件 - 你忘了绕着圆圈走.
纠正所有这些错误后,看起来事情正在发挥作用.
还有一些建议:
eq数字 - 使用==运算符进行数字比较.$cond1和$cond2变量,使用&&或and逻辑运算符 - 它们将使您的代码更容易阅读,并避免不必要的工作.for ($x = lower; $x <= $upper; $x++)你可以写for $x (lower .. upper).*和#输出输入到0和1,然后再回来,你可以通过更换使很多逻辑的更容易阅读if ($pixel eq $mark)与if ($pixel)等$p1through 这样的一系列编号变量$p9.如果$p1被调用$pixel并$p2通过$p9一个被调用的数组@neighbors,你可以重写十八行来计算$np1并$sp1分成三行.| 归档时间: |
|
| 查看次数: |
643 次 |
| 最近记录: |