Edge detection with PHP


We do some example with this image : http://static.asiawebdirect.com/m/bangkok/portals/vietnam/homepage/hanoi/pagePropertiesImage/hanoi-guide.jpg

Method 1:

<?php

function detect_edge($input)
{
    $in_im = imagecreatefromjpeg($input);
    $gx = array(array(-1, 0, 1), array(-2, 0, 2), array(-1, 0, 1));
    $gy = array(array(-1, -2, -1), array(0, 0, 0), array(1, 2, 1));
    $x = imagesx($in_im);
    $y = imagesy($in_im);
    $out_im = imagecreatetruecolor($x, $y);
    $colors = array(255 => imagecolorallocate($out_im, 255, 255, 255));
    for ($row = 1; $row < $x; $row++)
    {
        for ($col = 1; $col < $y; $col++)
        {
            $eyedropper = imagecolorat($in_im, $x, $y);
            $color = imagecolorsforindex($in_im, $eyedropper);
            $pxval = ($color['red'] + $color['green'] + $color['blue']) / 3;
            $pixel_gx = $pixel_gy = 0;
            for ($i = -1; $i < 2; $i++)
            {
                for ($j = -1; $j < 2; $j++)
                {
                    $eyedropper = imagecolorat($in_im, $row + $i, $col + $j);
                    $color = imagecolorsforindex($in_im, $eyedropper);
                    $val = ($color['red'] + $color['green'] + $color['blue']) / 3;
                    $pixel_gx += $gx[$i + 1][$j + 1] * $val;
                    $pixel_gy += $gy[$i + 1][$j + 1] * $val;
                }
            }
            $pixel = sqrt($pixel_gx * $pixel_gx + $pixel_gy * $pixel_gy);
            $pixel = abs(255 - (int)$pixel);
            if (!isset($colors[$pixel]))
                $colors[$pixel] = imagecolorallocate($out_im, $pixel, $pixel, $pixel);
            imagesetpixel($out_im, $row, $col, $colors[$pixel]);
        }
    }
    imagejpeg($out_im);
    imagedestroy($in_im);
    imagedestroy($out_im);
}

header('Content-type: image/jpg');
detect_edge('hanoi-guide.jpg');

?>

Online demo:

Method 2:

Use imagefilter:

<?php
$im = imagecreatefromjpeg('hanoi-guide.jpg');

imagefilter($im, IMG_FILTER_EDGEDETECT);

header('Content-type: image/jpg');    
imagejpeg($im);

imagedestroy($im);
?>

Online demo:

Method 3:

<?php
// input: r,g,b in range 0..255
function RGBtoHSV($r, $g, $b) {
	$r = $r/255; // convert to range 0..1
	$g = $g/255;
	$b = $b/255;
	$cols = array("r" => $r, "g" => $g, "b" => $b);
	asort($cols, SORT_NUMERIC);
	$min = key(array_slice($cols, 1)); // "r", "g" or "b"
	$max = key(array_slice($cols, -1)); // "r", "g" or "b"
	// hue
	if($cols[$min] == $cols[$max]) {
		$h = 0;
	} else {
		if($max == "r") {
			$h = 60 * ( 0 + ( ($cols["g"]-$cols["b"]) / ($cols[$max]-$cols[$min]) ) );
		} elseif ($max == "g") {
			$h = 60 * ( 2 + ( ($cols["b"]-$cols["r"]) / ($cols[$max]-$cols[$min]) ) );
		} elseif ($max == "b") {
			$h = 60 * ( 4 + ( ($cols["r"]-$cols["g"]) / ($cols[$max]-$cols[$min]) ) );
		}
		if($h < 0) {
			$h += 360;
		}
	}
	// saturation
	if($cols[$max] == 0) {
		$s = 0;
	} else {
		$s = ( ($cols[$max]-$cols[$min])/$cols[$max] );
		$s = $s * 255;
	}
	// lightness
	$v = $cols[$max];
	$v = $v * 255;
	return(array($h, $s, $v));
}
$filename = "hanoi-guide.jpg";
$dimensions = getimagesize($filename);
$w = $dimensions[0]; // width
$h = $dimensions[1]; // height
$im = imagecreatefromjpeg($filename);
for($hi=0; $hi < $h; $hi++) {
	for($wi=0; $wi < $w; $wi++) {
		$rgb = imagecolorat($im, $wi, $hi);
		$r = ($rgb >> 16) & 0xFF;
		$g = ($rgb >> 8) & 0xFF;
		$b = $rgb & 0xFF;
		$hsv = RGBtoHSV($r, $g, $b);
		if($hi < $h-1) {
			// compare pixel below with current pixel
			$brgb = imagecolorat($im, $wi, $hi+1);
			$br = ($brgb >> 16) & 0xFF;
			$bg = ($brgb >> 8) & 0xFF;
			$bb = $brgb & 0xFF;
			$bhsv = RGBtoHSV($br, $bg, $bb);
			// if difference in hue is bigger than 20, make this pixel white (edge), otherwise black
			if($bhsv[2]-$hsv[2] > 20) {
				imagesetpixel($im, $wi, $hi, imagecolorallocate($im, 255, 255, 255));
			} else {
				imagesetpixel($im, $wi, $hi, imagecolorallocate($im, 0, 0, 0));
			}
			
		}
	}
}
header('Content-Type: image/jpeg');
imagejpeg($im);
imagedestroy($im);
?>

Online demo:

Method 4: use imageconvolution

<?php

$filename = "hanoi-guide.jpg";
$im = imagecreatefromjpeg($filename);

$matrix = array(array(0.0, 1.0, 0.0), array(1.0, -4.0, 1.0), array(0.0, 1.0, 0.0));
//$matrix = array(array(-1, -1, -1), array(-1, 8, -1), array(-1, -1, -1));

imageconvolution($im, $matrix , array_sum(array_map('array_sum', $matrix)), 0);

header('Content-Type: image/jpeg');
imagejpeg($im);
imagedestroy($im);

?>

Online demo:

Please comment the mothod you prefer.

Leave a Reply