phpimagepixelstencils

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


I am working on a project at a company that cuts designs using a laser cutter. The company recently developed a website that allows customers to upload any image of their choice. In order to cut the design printed on the image, the design has to be a stencil. So, I have to write a software that can analyze an image to find where it is non-stencilized. If the design turns out to be non-stencilized the system should output a message such as “Design not a stencil”. I imagine this would work by understanding where a group of white pixels are enclosed by a group of black pixels. If a white pixel is completely enclosed by black pixels, then the design is not a stencil. I am not quite sure how I can write a software that can check if a white pixel is completely enclosed by black pixels. Since all the previous code for the website is written in PHP, I would prefer to use PHP. Thanks in advance

This is an example of a valid and invalid stencil


Solution

  • In a nutshell, I think your question comes down to whether or not your image can be "flood-filled" - see Wikipedia.

    So, if I just use ImageMagick at the command line to demonstrate, and flood-fill with magenta so you can see it:

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

    enter image description here

    And if I do the same with the invalid stencil image:

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

    enter image description here

    So, the solution is to flood-fill and see if there are any white pixels left afterwards. In the actual code, I will fill with black rather than magenta because, that way, I have only to find if the brightest pixel after filling is black or not to know the answer:

    So, again with ImageMagick. Flood-fill with black and see if brightest pixel after filling is black (0) or white (255 or 65535):

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

    and now the invalid stencil:

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

    There is one little wrinkle - if the top-left pixel is not white, or the black parts touch the edge of the picture and stop the flood-fill flowing around the edges of the picture. And there is a simple solution to both, just add a 1-pixel wide white border all around the image before you start to ensure the top-left pixel is white and that the "paint" can flow all the way around the edges of image:

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

    PHP Version

    PHP is not my native programming language so there may be other, better ways of doing things but this seems to work ok...

    <?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");
    ?>