Blurring an image - Advanced convolution [56kb warning]
Posted: Mon Nov 14, 2005 2:39 pm
Note to mods: Don't move this to code snippets coz it's unoptimized and not useable yet. It'll undergo improvements.
Note: Updated the convolution code .. approx 8 times faster now. Still slow though.
I've been working on a new and improved image convolution script .. so far so good so I thought I'd share some results:

What's going on in the image there then?
By taking a 7*7 convolution matrix as follows and multipling all the pixels in the image against it you can calculate the values of new pixels as an "average" of the pixels around it .. hence the blur effect.
The Matrix:
The convolution script:
Note: Updated the convolution code .. approx 8 times faster now. Still slow though.
I've been working on a new and improved image convolution script .. so far so good so I thought I'd share some results:

What's going on in the image there then?
By taking a 7*7 convolution matrix as follows and multipling all the pixels in the image against it you can calculate the values of new pixels as an "average" of the pixels around it .. hence the blur effect.
The Matrix:
Code: Select all
$m = array( array(1,0,0,0,0,0,1),
array(0,2,0,0,0,2,0),
array(0,0,2,4,2,0,0),
array(0,0,4,8,4,0,0),
array(0,0,2,4,2,0,0),
array(0,2,0,0,0,2,0),
array(1,0,0,0,0,0,1)
);Code: Select all
$time_start = microtime_float();
// Blur
$m = array( array(1,0,0,0,0,0,1),
array(0,2,0,0,0,2,0),
array(0,0,2,4,2,0,0),
array(0,0,4,8,4,0,0),
array(0,0,2,4,2,0,0),
array(0,2,0,0,0,2,0),
array(1,0,0,0,0,0,1)
);
$f = array_sum_multi($m);
$c = 0;
$m_elements = count($m);
$m_offset = floor($m_elements/2);
for ($m_y=0;$m_y<$m_elements;$m_y++) {
for ($m_x=0;$m_x<$m_elements;$m_x++) {
$mx[$m[$m_x][$m_y]][] = array($m_x-$m_offset,$m_y-$m_offset);
}
}
$original = imagecreatefromjpeg("xxx.jpg");
$source = imagecreatetruecolor(imagesx($original)+($m_offset*2),imagesy($original)+($m_offset*2));
$red = imagecolorallocate($source,255,0,0);
imagecopy($source, $original, $m_offset, $m_offset, 0, 0, imagesx($original),imagesy($original));
imagecopyresampled($source, $original, 0, 0, 0, 0, imagesx($original)+($m_offset*2), $m_offset, imagesx($original), $m_offset);
imagecopyresampled($source, $original, 0, imagesy($original)+$m_offset, 0, imagesy($original)-$m_offset, imagesx($original)+($m_offset*2), $m_offset, imagesx($original), $m_offset);
imagecopy($source, $original, 0, $m_offset, 0, 0, $m_offset, imagesy($original));
imagecopy($source, $original, imagesx($original)+$m_offset, $m_offset, imagesx($original)-$m_offset, 0, $m_offset, imagesy($original));
$image = imagecreatetruecolor(imagesx($original),imagesy($original));
for ($y=0;$y<imagesy($source);$y++) {
for ($x=0;$x<imagesx($source);$x++) {
$t1 = imagecolorat($source,$x,$y);
$p[$x][$y]['r'] = ($t1 >> 16) & 0xFF;
$p[$x][$y]['g'] = ($t1 >> & 0xFF;
$p[$x][$y]['b'] = $t1 & 0xFF;
}
}
for ($y=$m_offset;$y<imagesy($original)+$m_offset;$y++) {
for ($x=$m_offset;$x<imagesx($original)+$m_offset;$x++) {
$pixel_r = 0;
$pixel_g = 0;
$pixel_b = 0;
// Slooooooooooooooooooooow
// for ($m_y=0;$m_y<$m_elements;$m_y++) {
// for ($m_x=0;$m_x<$m_elements;$m_x++) {
// $pixel_r += ($p[$x+($m_x-$m_offset)][$y+($m_y-$m_offset)]['r']*$m[$m_x][$m_y]);
// $pixel_g += ($p[$x+($m_x-$m_offset)][$y+($m_y-$m_offset)]['g']*$m[$m_x][$m_y]);
// $pixel_b += ($p[$x+($m_x-$m_offset)][$y+($m_y-$m_offset)]['b']*$m[$m_x][$m_y]);
// }
// }
// Bit quicker
foreach ($mx as $m => $a) {
if ($m != 0) {
$pixel_r_temp = 0;
$pixel_g_temp = 0;
$pixel_b_temp = 0;
foreach ($a as $avals) {
$xt = $x+$avals[0];
$yt = $y+$avals[1];
$pixel_r_temp += ($p[$xt][$yt]['r']);
$pixel_g_temp += ($p[$xt][$yt]['g']);
$pixel_b_temp += ($p[$xt][$yt]['b']);
}
$pixel_r += $pixel_r_temp*$m;
$pixel_g += $pixel_g_temp*$m;
$pixel_b += $pixel_b_temp*$m;
}
}
$pixel_r = ($pixel_r/$f)+$c;
$pixel_g = ($pixel_g/$f)+$c;
$pixel_b = ($pixel_b/$f)+$c;
$col = imagecolorallocate($image,$pixel_r,$pixel_g,$pixel_b);
imagesetpixel($image,$x-$m_offset,$y-$m_offset,$col);
}
}
$black = imagecolorallocate($image,0,0,0);
$time_end = microtime_float();
$time = $time_end - $time_start;
imagestring($image, 3, 5, 5, $time, $black);
header("Content-Type: image/jpeg");
imageJPEG($image,"",100);
function array_sum_multi($a) {
if(!is_array($a)) return $a;
foreach($a as $key=>$value) {
$total += array_sum_multi($value);
}
return $total;
}
function microtime_float() {
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}