首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >填充形状边缘中的间隙

填充形状边缘中的间隙
EN

Stack Overflow用户
提问于 2014-10-27 19:03:30
回答 4查看 4.2K关注 0票数 8

有没有一种算法可以很好地像样本图像那样填充空洞?膨胀效果不好,因为在我最终设法连接这些曲线的两端之前,曲线变得非常粗。我不想让线条变粗。谢谢你的帮助。

是的,图像中的任何字母或形状都可以有这样的孔。

EN

回答 4

Stack Overflow用户

发布于 2014-10-28 06:26:11

另一种更简单的方法可能会更好地转换为OpenCV,因为它使用卷积而不是顺序的Perl/C代码。

基本上将所有黑色像素设置为10值,将所有白色像素设置为0值,然后将图像与以下3x3内核进行卷积:

代码语言:javascript
运行
复制
1  1  1
1  10 1
1  1  1

现在,内核中间的黑色像素将得到100 (10x10),而附近的任何其他黑色像素都将得到10 (10x1)。因此,如果我们想要有一个中心黑像素和一个相邻黑像素的点,它的值将是110 (100+10)。因此,让我们用红色对所有值为110的像素进行着色。这给出了这个命令:

代码语言:javascript
运行
复制
convert EsmKh.png -colorspace gray -fill gray\(10\) -opaque black -fill gray\(0\) -opaque white -morphology convolve '3x3: 1,1,1 1,10,1 1,1,1' -fill red -opaque gray\(110\) out.png

生成的图像(您可能需要放大间隙才能看到红色):

如果需要红色像素的列表,请将输出文件名替换为txt:,然后按如下方式进行搜索:

代码语言:javascript
运行
复制
convert EsmKh.png -colorspace gray -fill rgb\(10,10,10\) -opaque black -fill rgb\(0,0,0\) -opaque white -morphology convolve '3x3: 1,1,1 1,10,1 1,1,1' txt: | grep "110,110,110"

这就给出了:

代码语言:javascript
运行
复制
86,55: (110,110,110)  #6E6E6E  grey43
459,55: (110,110,110)  #6E6E6E  grey43
83,56: (110,110,110)  #6E6E6E  grey43
507,59: (110,110,110)  #6E6E6E  grey43
451,64: (110,110,110)  #6E6E6E  grey43
82,65: (110,110,110)  #6E6E6E  grey43
134,68: (110,110,110)  #6E6E6E  grey43
519,75: (110,110,110)  #6E6E6E  grey43
245,81: (110,110,110)  #6E6E6E  grey43
80,83: (110,110,110)  #6E6E6E  grey43
246,83: (110,110,110)  #6E6E6E  grey43
269,84: (110,110,110)  #6E6E6E  grey43
288,85: (110,110,110)  #6E6E6E  grey43
315,87: (110,110,110)  #6E6E6E  grey43
325,87: (110,110,110)  #6E6E6E  grey43
422,104: (110,110,110)  #6E6E6E  grey43
131,116: (110,110,110)  #6E6E6E  grey43
524,116: (110,110,110)  #6E6E6E  grey43
514,117: (110,110,110)  #6E6E6E  grey43
122,118: (110,110,110)  #6E6E6E  grey43
245,122: (110,110,110)  #6E6E6E  grey43
76,125: (110,110,110)  #6E6E6E  grey43
456,128: (110,110,110)  #6E6E6E  grey43
447,129: (110,110,110)  #6E6E6E  grey43
245,131: (110,110,110)  #6E6E6E  grey43
355,135: (110,110,110)  #6E6E6E  grey43
80,146: (110,110,110)  #6E6E6E  grey43
139,151: (110,110,110)  #6E6E6E  grey43
80,156: (110,110,110)  #6E6E6E  grey43
354,157: (110,110,110)  #6E6E6E  grey43
144,160: (110,110,110)  #6E6E6E  grey43
245,173: (110,110,110)  #6E6E6E  grey43
246,183: (110,110,110)  #6E6E6E  grey43
76,191: (110,110,110)  #6E6E6E  grey43
82,197: (110,110,110)  #6E6E6E  grey43
126,200: (110,110,110)  #6E6E6E  grey43
117,201: (110,110,110)  #6E6E6E  grey43
245,204: (110,110,110)  #6E6E6E  grey43
248,206: (110,110,110)  #6E6E6E  grey43
297,209: (110,110,110)  #6E6E6E  grey43
309,210: (110,110,110)  #6E6E6E  grey43

现在,您可以处理红点列表,对于每个红点,找到最近的其他红点并用直线连接它们-或者如果您真的很热衷于曲线拟合,则进行一些曲线拟合。当然,可能会有一些改进工作要做,并且您可能希望设置填充线的最大长度。

票数 7
EN

Stack Overflow用户

发布于 2014-10-28 01:03:03

我对此做了一点尝试。它可能需要一些调整,但它是一个想法。我的算法如下:

找到恰好有1个黑色相邻像素的所有黑色像素,将其着色为红色,并将其放在pixels at ends列表中。

浏览所有红色像素的列表,找到距离最近的其他红色像素,并在两者之间画直线。

顺便说一句,我只实现了第一部分--给读者留下了一些事情要做;-)

代码语言:javascript
运行
复制
#!/usr/bin/perl
use strict;
use warnings;
use Image::Magick;
use Data::Dumper;

my $im=Image::Magick->new();
$im->Read('EsmKh.png');

my ($width,$height)=$im->Get('width','height');
my $out=Image::Magick->new();
$out->Read('EsmKh.png');

my @pixels;
# Iterate over pixels
for my $y (0..($height-1)){
   for my $x (0..($width-1)){
      my (@pixel) = split(/,/, $im->Get("pixel[$x,$y]"));
      $pixels[$x][$y]=$pixel[0];
   }
}

# Find black pixels that have precisely 1 black neighbour
for my $y (1..($height-2)){
   for my $x (1..($width-2)){
      next if $pixels[$x][$y]!=0;
      my $neighbours=0;
      for(my $i=$x-1;$i<=$x+1;$i++){
         for(my $j=$y-1;$j<=$y+1;$j++){
            $neighbours++ if $pixels[$i][$j]==0;
         }
      }
      $neighbours--;    # Uncount ourself !
      if($neighbours==1){
         $out->Set("pixel[$x,$y]"=>'red');
      }
   }
}
$out->Write(filename=>'out.png');

结果

你必须右放大才能看到红色的像素。

缩放图像

票数 4
EN

Stack Overflow用户

发布于 2014-10-29 05:18:45

在你得到加厚的图像后,你可以使用skeletonization恢复你的“瘦”形状。我找到了一个骨架化here的实现。

如果你想避免太多的加厚(因为它扭曲了图像和形状的一部分合并在一起),使用轻度腐蚀和骨架化交替使用,直到你的洞被填满。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26586123

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档