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

508

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

868

Answer

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

People are also looking for solutions to the problem: PHP Try/Catch block halting code execution

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.