如何编写可以分析图像以查找未进行模板化处理的代码?

How to write code that can analyse an image to find where it is non-stencilized?

我正在一家使用激光切割机切割设计的公司从事一个项目。该公司最近开发了一个网站,允许客户上传他们选择的任何图像。为了切割打印在图像上的设计,设计必须是模板。因此,我必须编写一个软件来分析图像以找出未进行模板化处理的位置。如果设计结果是非模板化的,系统应该输出一条消息,例如“Design not a stencil”。我想这可以通过了解一组白色像素被一组黑色像素包围的位置来实现。如果白色像素完全被黑色像素包围,则设计不是模板。我不太确定如何编写一个软件来检查白色像素是否完全被黑色像素包围。由于该网站以前的所有代码都是用 PHP 编写的,所以我更愿意使用 PHP。 提前致谢

This is an example of a valid and invalid stencil

简而言之,我认为您的问题归结为您的图像是否可以 "flood-filled" - 请参阅 Wikipedia.

因此,如果我只是在命令行中使用 ImageMagick 进行演示,并用洋红色填充以便您可以看到它:

convert valid.png -threshold 50% -fill magenta -draw 'color 0,0 floodfill' result.png

如果我对无效模板图像执行相同操作:

convert invalid.png -threshold 50% -fill magenta -draw 'color 0,0 floodfill' result.png

所以,解决办法就是先flood-fill,然后看看有没有留下白色像素。在实际代码中,我会用黑色而不是洋红色来填充,因为那样的话,我只需要看看填充后最亮的像素点是不是黑色就可以知道答案了:

因此,再次使用 ImageMagick。用黑色填充并查看填充后最亮的像素是黑色(0)还是白色(255 或 65535):

convert valid.png -threshold 50% -fill black -draw 'color 0,0 floodfill' -format "%[max]" info:
0

现在是无效模板:

convert invalid.png -threshold 50% -fill black -draw 'color 0,0 floodfill' -format "%[max]" info:
65535

有一个小皱纹 - 如果左上角的像素不是白色,或者黑色部分接触到图片的边缘并停止在图片的边缘周围流动。两者都有一个简单的解决方案,只需在图像周围添加一个 1 像素宽的白色边框,然后再开始确保左上角像素为白色并且 "paint" 可以一直围绕图像的边缘流动:

convert input.png -bordercolor white -border 1 .... <as before> ...

PHP版本

PHP 不是我的母语编程语言,所以可能还有其他更好的方法,但这似乎工作正常...

<?php
   # Load the input image and get its size
   $name="invalid.png";
   $image=imagecreatefrompng($name);
   $size=getimagesize($name);

   # Threshold the image to only contain pure black and pure white
   imagefilter($image,IMG_FILTER_GRAYSCALE);
   imagefilter($image,IMG_FILTER_CONTRAST,-1000);

   # Flood fill white areas with black
   $black = imagecolorallocate($image,0,0,0);
   imagefilltoborder($image,0,0,$black,$black);

   $allblack=1;
   # Scan the image and see if there are any non-black pixels
   for($i=0;$i<$size[0];$i++){
      for($j=0;$j<$size[1];$j++){
         $thisColor = imagecolorat($image,$i,$j);
         if($thisColor!=0){
            $allblack=0;
            break;
         }
      }
   }

   printf("%s: %d\n",$name,$allblack);

   # Write output image
   imagepng($image,"result.png");
?>