perl中的图像细化算法?

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=();
  }
}

hob*_*bbs 6

你在实现算法时犯了几个错误:

  1. 您无法$ra就地修改.如果这样做,那么当您擦除一个像素时,您将更改其后处理的像素的条件,这会导致错误向下和向右蠕动.

  2. $cond1$cond2条件不应该在同一个循环中检查.相反,必须使用$cond1条件处理整个图像,然后根据$cond2条件处理整个图像,并根据需要重复.

  3. 当你计算连通性时,你错过了$p9"unmark"并且$p2是"mark"的条件 - 你忘了绕着圆圈走.

纠正所有这些错误后,看起来事情正在发挥作用.

还有一些建议:

  1. 您不应该使用eq数字 - 使用==运算符进行数字比较.
  2. 而不是使用$cond1$cond2变量,使用&&and逻辑运算符 - 它们将使您的代码更容易阅读,并避免不必要的工作.
  3. 而不是for ($x = lower; $x <= $upper; $x++)你可以写for $x (lower .. upper).
  4. 如果你改变*#输出输入到0和1,然后再回来,你可以通过更换使很多逻辑的更容易阅读if ($pixel eq $mark)if ($pixel)
  5. 使用数组而不是像$p1through 这样的一系列编号变量$p9.如果$p1被调用$pixel$p2通过$p9一个被调用的数组@neighbors,你可以重写十八行来计算$np1$sp1分成三行.
  6. 一般来说,更好的变量名称是个不错的主意:)