Page 1 of 1

Intelligent Thumbnails

Posted: Sat Mar 29, 2008 1:31 pm
by onion2k
I was a little sick of doing proper work this afternoon so I decided to spend an hour messing about with GD for the first time in almost a year.

It's faaaaaaaaar from being production code yet, but I've created a script for making "intelligent thumbnails". Basically, it'll take an image and make a thumbnail from the more important part of the picture. This is just a really early version at the moment, but it's a fun thing to play with.

The code:

NOTE: CURRENTLY THE CODE JUST MARKS THE AREA THE THUMBNAIL WOULD USE, IT DOESN'T MAKE THE THUMBNAIL.

Code: Select all

<?php
 
    $source_filename = "3.jpg";
    $sample = 28;
    $thumb_x = 100;
    $thumb_y = 100;
 
// -----------------------------------------------------------------------------
 
    //Open the image
 
    $source = imagecreatefromjpeg($source_filename);
    $source_info = getimagesize($source_filename);
    $source_x = $source_info[0];
    $source_y = $source_info[1];
 
// -----------------------------------------------------------------------------
 
    //Scale to temp_s CAR
 
    if ($source_x < $source_y) { // X>Y
 
        $temp_x = $sample;
        $temp_y = ($sample/$source_x)*$source_y;
 
    } else { // Y>X or Y==X
 
        $temp_x = ($sample/$source_y)*$source_x;
        $temp_y = $sample;
 
    }
 
    $temp = imagecreatetruecolor($temp_x, $temp_y);
    imagecopyresized($temp, $source, 0, 0, 0, 0, $temp_x, $temp_y, $source_x, $source_y);
 
// -----------------------------------------------------------------------------
 
    //Detect edges
 
    $mx = array(array(-1,0,1),
                array(-2,0,2),
                array(-1,0,1)
              );
 
    $my = array(array(1,2,1),
                array(0,0,0),
                array(-1,-2,-1)
              );
 
    $m_elements = count($mx);
    $m_offset = floor($m_elements/2);
 
    for ($y=0;$y<$temp_y;$y++) {
        for ($x=0;$x<$temp_x;$x++) {
            $t1 = imagecolorat($temp,$x,$y);
            $p[$x][$y]['r'] = ($t1 >> 16) & 0xFF;
            $p[$x][$y]['g'] = ($t1 >> 8) & 0xFF;
            $p[$x][$y]['b'] = $t1 & 0xFF;
        }
    }
 
    for($y=0; $y<$temp_y; $y++)  {
        for($x=0; $x<$temp_x; $x++)  {
 
            $sumXr = 0;
            $sumXg = 0;
            $sumXb = 0;
 
            $sumYr = 0;
            $sumYg = 0;
            $sumYb = 0;
 
            for($i=-1; $i<=1; $i++)  {
                for($j=-1; $j<=1; $j++)  {
                    $sumXr = $sumXr + (($p[$x+$i][$y+$j]['r']) * $mx[$i+1][$j+1]);
                    $sumXg = $sumXg + (($p[$x+$i][$y+$j]['g']) * $mx[$i+1][$j+1]);
                    $sumXb = $sumXb + (($p[$x+$i][$y+$j]['b']) * $mx[$i+1][$j+1]);
 
                    $sumYr = $sumYr + (($p[$x+$i][$y+$j]['r']) * $my[$i+1][$j+1]);
                    $sumYg = $sumYg + (($p[$x+$i][$y+$j]['g']) * $my[$i+1][$j+1]);
                    $sumYb = $sumYb + (($p[$x+$i][$y+$j]['b']) * $my[$i+1][$j+1]);
                }
            }
 
            $sumr = abs($sumXr) + abs($sumYr);
            $sumg = abs($sumXg) + abs($sumYg);
            $sumb = abs($sumXb) + abs($sumYb);
 
            if($sumr>255) $sumr=255;
            if($sumg>255) $sumg=255;
            if($sumb>255) $sumb=255;
 
            if($sumr<0) $sumr=0;
            if($sumg<0) $sumg=0;
            if($sumb<0) $sumb=0;
 
            //$color = imagecolorallocate($temp,255-$sumr,255-$sumg,255-$sumb);
            //imagesetpixel($temp,$x,$y,$color);
 
            $e[$x][$y] = (($sumr)+($sumg)+($sumb))/3;
 
        }
 
    }
 
// -----------------------------------------------------------------------------
 
    //Calculate 'interest point'
 
    $line_x = 0;
    $line_y = 0;
 
    $line_xt = 0;
    $line_yt = 0;
 
    for($x=1; $x<($temp_x-2); $x++)  {
 
        $t = 0;
        for($f=0; $f<$temp_x; $f++)  {
            $t += $e[$x][$f];
        }
 
        if ($line_xt < $t) {
            $line_x = $x;
            $line_xt = $t;
        }
 
    }
 
 
    for($y=1; $y<($temp_y-2); $y++)  {
 
        $t = 0;
        for($f=0; $f<$temp_x; $f++)  {
            $t += $e[$f][$y];
        }
 
        if ($line_yt < $t) {
            $line_y = $y;
            $line_yt = $t;
        }
 
    }
 
// -----------------------------------------------------------------------------
 
    //Generate thumbnail
 
    $scale_x = $source_x/$temp_x;
    $scale_y = $source_y/$temp_y;
 
    $red = imagecolorallocate($temp,255,0,0);
    imagerectangle($source,(($line_x*$scale_x)-floor($thumb_x/2)),(($line_y*$scale_y)-floor($thumb_y/2)),(($line_x*$scale_x)+ceil($thumb_x/2)),(($line_y*$scale_y)+ceil($thumb_y/2)),$red);
 
    header("Content-type: image/png");
    imagepng($source);
 
Examples of what it does:

Image

Clearly it's not very intelligent at the moment. Tweaking the sample area size ($sample) produces wildly varying results. This is because it's taking the row and column with the most edge changes in them and using the point they intersect as the origin for the thumbnail area. That can be hugely improved using a rolling average instead of a total, or figuring out which area of the image has the most changes, or figuring out which area has the most contiguous changes, etc. I'm not sure Sobel edge detection is the best option either. There's plenty still to do. Hopefully it won't be another year before I get a chance to revisit it.

Thoughts, comments, code optimisations appreciated.

Re: Intelligent Thumbnails

Posted: Sat Mar 29, 2008 3:03 pm
by s.dot
That is super cool. I would think it could be used (with great enthusiasm!) on graphics designers portfolio pages. Often they take an interesting aspect of the design and make that the clickable thumbnail to the larger full image.

In fact, just yesterday, my friend was complaining to me about having to make thumbnails for this purpose.

Re: Intelligent Thumbnails

Posted: Mon Mar 31, 2008 7:20 am
by georgeoc
This is really nice. It managed to find the face in most of the photos I threw at it - very impressive!

My first comment would be something I'm sure you're aware of already: the thumbnail box quite often goes off the edge of the image. I guess after your calculations you need to bring the box back to the centre just enough so it fits inside the master image. Then it would be very useful!

Re: Intelligent Thumbnails

Posted: Mon Mar 31, 2008 8:00 am
by onion2k
Yeah, I'm aware of that. Fortunately it's an easy thing to fix.