Image edge detection algorithm – php version

One of the most used image effects is the edge detection. Have you ever wondered how does it work?

The following is a tutorial to achieve an edge detection effect on an image without using any built-in functions, such as imagefilter with IMG_FILTER_EDGEDETECT filter type.

It will be very useful to learn something about image filters.

Before we begin, let me copy/paste some basic information from Wikipedia :)

Edge detection is a fundamental tool in image processing and computer vision, particularly in the areas of feature detection and feature extraction, which aim at identifying points in a digital image at which the image brightness changes sharply or more formally has discontinuities (source).

Now we know we are looking for sharp image brightness changes.

To quickly get the image brigthness, we have to convert it to a grayscale representation of its luminance.

To convert any color to a grayscale representation of its luminance, first one must obtain the values of its red, green, and blue (RGB) primaries in linear intensity encoding, by gamma expansion. Then, add together 30% of the red value, 59% of the green value, and 11% of the blue value. The resultant number is the desired linear luminance value (source).

Once we have our luminance map, we can use the Sobel operator to detect edges.

The Sobel operator calculates the directional change of the image intensity at each point, giving the direction of the largest possible increase from light to dark and the rate of change in that direction, using uses a pair of 3×3 convolution masks, one estimating the directional change in the x-direction and the other estimating the directional change in the y-direction.

This is the convolution mask:

Where A is the source image.

Once you have Gx and Gy values, combine them this way:

to get the directional change and consequently the gray representation of the edge.

Time to code something:

I tried the script on this image:

This is the Photoshop CS4 Find Edges filter on the desaturated image:

This is the result of the script:

This is the result of the same script using Manhattan Distance rather than Euclidean distance, changing line 33 with:

And this is the result of the same script applying the Manhattan Distance and a gaussian blur this way:

Hope you can use this concept in some of your works. I already have one use in mind… stay tuned.

  • dario

    It’s not working for me. I don’t get image at all. :(

  • // adjusting distance if it’s greater than 255 or less than zero (out of color range)
    if($gray > 255){
    $gray = 255;
    }
    if($gray < 0){
    $gray = 0;
    }

    Is the same as :

    $gray = min( 255, $gray );
    $gray = max( 0, $gray );

    /I did not test it./

  • Emanuele Feronato

    yes, but using “if” is quicker :)

    (should I do a speed test?)

  • I think IF has proved to be much faster in your Manhattan article.

    Speaking of wich …

    The difference between the first image and the Manhattan one comes from line 33 :
    $gray = sqrt($conv_x*$conv_x+$conv_y + $conv_y);
    I think it should be :
    $gray = sqrt($conv_x*$conv_x+$conv_y * $conv_y);

    Thank you for this great article !

  • The sobel operator is separable, so you can transform Gx and Gy from a 3×3 operator into a 3×1 and a 1×3 operator, which will probably make the filter faster (less image lookups)

  • Try

    for($x = 1; $x < $im_data[0]-1; $x++){
    for($y = 1; $y < $im_data[1]-1; $y++){
    ...
    }
    }

    o prevent imagecolorat() out of bounds errors

  • Excellent article. Is there anyway I can reserve the original image color while tracing out the edges?

  • Sastha

    Good article, This method leads to timeout when tried on larger images. anyways to improve performance?

  • Well I tried it with diferents images and get not image at all!!! But using the same image as in this page, the code break with an error of out of boundaries!!!

  • To SLIMTUGO: Yes you can, only “plot” the gray dots of the edge over the original image instead of the gray-converted one..

  • To getorund the timeout try set_time_limit(52); Or Upgrade de CPU!!!

  • What could be any further applications of this?
    any clues,,

    for example,
    one may want to use this to create filters
    to detect selected features in an image

    or extend it for sound ???

    Regards.

  • Suman

    i want to add a lightbox where,the content of lihtbox will be fetch from database and after selecting the content,the content will display in a html page.

  • Shanmuganathan

    First of this tutorial is very useful.

    But the above code is throwing this error please help me to fix this

    Notice: imagecolorat() [function.imagecolorat]: 0,-1 is out of bounds in F:\xampp\htdocs\projects\ipix\sketch.php on line 19

    Notice: imagecolorat() [function.imagecolorat]: -1,0 is out of bounds in F:\xampp\htdocs\projects\ipix\sketch.php on line 21

    Notice: imagecolorat() [function.imagecolorat]: -1,-1 is out of bounds in F:\xampp\htdocs\projects\ipix\sketch.php on line 23

    Notice: imagecolorat() [function.imagecolorat]: 1,-1 is out of bounds in F:\xampp\htdocs\projects\ipix\sketch.php on line 24

    Notice: imagecolorat() [function.imagecolorat]: -1,1 is out of bounds in F:\xampp\htdocs\projects\ipix\sketch.php on line 25

    • Sameer Akela

      put this line at the starting of your script…
      error_reporting(0);

  • priyanka

    can we find the text image by this sobel operator?

  • Mukesh Kumar

    how I get the variable:
    $source_image = “http://farm5.static.flickr.com/4109/4964650020_5d0f00298b.jpg”;
    in my computer please help me………………..

  • Mukesh Kumar

    when we are executing all code then we have got the output doesn’t any image it was seems like symbol of image only. what we have to do such that we will got sobel image.

  • magaroo

    Thanks for the great article. Matt West is right…you NEED to change this at the top of the start of the for loops:

    for($x = 1; $x < $im_data[0]-1; $x++){
    for($y = 1; $y < $im_data[1]-1; $y++){

    }
    }

    I adjusted the code a little bit over here and I am using:
    $w = imagesx($img);
    $h = imagesy($img);

    // this will be the final image, same width and height of the original
    $final = imagecreatetruecolor($w,$h);

    // looping through ALL pixels!!
    for ($x = 1; $x < $w-1; $x++) {
    for ($y = 1; $y < $h-1; $y++) {

    //////////////

    On my local version of XAMPP, I have gotten it to work. You can use this as a SEQUENTIAL way to modify an image called $img. You can just paste this below too, and at the end of these steps, you will still have $img, only it will now have the filter our great friend coded. Here's my modified version, with line 33 changed too:

    $w = imagesx($img);
    $h = imagesy($img);

    // this will be the final image, same width and height of the original
    $final = imagecreatetruecolor($w,$h);

    // looping through ALL pixels!!
    for ($x = 1; $x < $w-1; $x++) {
    for ($y = 1; $y 255) {
    $gray = 255;
    }
    if ($gray < 0) {
    $gray = 0;
    }

    // creation of the new gray
    $new_gray = imagecolorallocate($final, $gray, $gray, $gray);

    // adding the gray pixel to the new image
    imagesetpixel($final, $x, $y, $new_gray);
    }
    }

    $img = $final;

  • DulP

    Can I use this to compare similarity between 2 images? If so, how I can I use this? Thanks in advance.

  • Thanks, This tutorial is very helpfull