PHP Developers Network

A community of PHP developers offering assistance, advice, discussion, and friendship.
 
Loading
It is currently Thu Nov 27, 2014 7:51 am

All times are UTC - 5 hours




Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Mon Oct 17, 2005 11:02 am 
Offline
Admin
User avatar

Joined: Wed Aug 13, 2003 7:02 am
Posts: 4522
Location: York, UK
Hi,

I currently have a plan to build a stock photo library that is going to be an addon to our internal intranet.

One feature i would like to have is...when the image is uploaded...the image is somehow analyzed, and the dominant color is somehow determined and stored in the database.

Then, users can search for "bluey" images or "yellowy" images etc.

I have seen this done on a stock photo site, but i have no idea if this is possible with PHP and GD, and even how to go about it.

Any help appreciated.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 17, 2005 12:07 pm 
Offline
Forum Regular
User avatar

Joined: Sat Mar 12, 2005 8:13 pm
Posts: 685
Location: US
Ok, set up variables as a point system. Something like..
$blue = 0;
$red = 0;
$green = 0;
...
Then analyze each pixel in the image. Only including red, blue and green, you'd just see which has the highest value, then give the appropriate value a 'point.' To check for light/dark, you'd just add the three up and see if it's above/below a certain number.

As long as you can look at individual pixels and see their color value, it's possible.

Seems a lot to do, though. You sure the site you're looking at doesn't just use keywords?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 17, 2005 2:16 pm 
Offline
Jedi Mod
User avatar

Joined: Tue Dec 21, 2004 6:03 pm
Posts: 5263
Location: usrlab.com
First thing you'll need to do is analyse the colours in the image. I do this by creating 3 integers (one each for r, g and b), and aggregating the total value of each channel.

Syntax: [ Download ] [ Hide ]
$i = imagecreatefromjpeg("image.jpg");

for ($x=0;$x<imagesx($i);$x++) {

                for ($y=0;$y<imagesy($i);$y++) {



                        $rgb = imagecolorat($i,$x,$y);

                        $r   = ($rgb >> 16) & 0xFF;

                        $g   = ($rgb >>  & 0xFF;

                        $b   = $rgb & 0xFF;



                        $rTotal += $r;

                        $gTotal += $g;

                        $bTotal += $b;

                        $total++;



                }

        }


If you want to know the average colour of the overall image..

Syntax: [ Download ] [ Hide ]
$rAverage = round($rTotal/$total);

$gAverage = round($gTotal/$total);

$bAverage = round($bTotal/$total);


This will give you the 3 r, g and b values you need to make a colour. At this point I would store these 3 values in the database. Then, if you need to find an image that's closest to a particular colour you can use some simple SQL to find it. Imagine that the r g b colour values have been stored in 3 int columns in the database called rVal, gVal, and bVal, and you've got your colour that you're looking for in 3 seperate components ($r, $g, $b):

Syntax: [ Download ] [ Hide ]
select * from image_table order by ABS(".$r."-rVal)+ABS(".$g."-gVal)+ABS(".$b."-bVal);


This is the technique I used in my image mosaic generator at http://www.ooer.com/mosaic/ .. The code goes through each pixel of the image you upload and selects a similarly coloured image from the database. As you can see .. it's not that slow, and it's pretty cool fun.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 17, 2005 3:19 pm 
Offline
Admin
User avatar

Joined: Wed Aug 13, 2003 7:02 am
Posts: 4522
Location: York, UK
Mate, your a legend! Image

Thanks, looks like just what i need!!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 17, 2005 6:04 pm 
Offline
Jedi Mod
User avatar

Joined: Tue Dec 21, 2004 6:03 pm
Posts: 5263
Location: usrlab.com
Pimptastic wrote:
Mate, your a legend! Image

Thanks, looks like just what i need!!

Yes .. yes I am. ;)

I was in York a little while ago .. cocktails in the Living Room .. drinking on the balcony over the river .. very civilised. I like York.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 17, 2005 6:46 pm 
Offline
Neighborhood Spidermoddy
User avatar

Joined: Mon Mar 29, 2004 4:24 pm
Posts: 31559
Location: Bothell, Washington, USA
grrrraphics. ;)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 17, 2005 7:28 pm 
Offline
Breakbeat Nuttzer
User avatar

Joined: Wed Mar 24, 2004 8:57 am
Posts: 13098
Location: Melbourne, Australia
onion2k wrote:
I was in York a little while ago .. cocktails in the Living Room .. drinking on the balcony over the river .. very civilised. I like York.


Me too... I used to visit York lots in the summer but I havent been for over a year now. Used to be a lot of Peacocks in the park but apparently not anymore :(


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 18, 2005 3:48 am 
Offline
Admin
User avatar

Joined: Wed Aug 13, 2003 7:02 am
Posts: 4522
Location: York, UK
feyd wrote:
grrrraphics. ;)


I'd say it was more PHP than graphics Image

onion2k wrote:
I was in York a little while ago .. cocktails in the Living Room .. drinking on the balcony over the river .. very civilised. I like York.


Ah, one of my many jaunts! Stumbled out of there a few times. Image

When were you there?

If anyone is ever in York, gimme a shout!


Top
 Profile  
 
PostPosted: Sat Apr 19, 2008 5:52 am 
Offline
Forum Newbie

Joined: Wed Jun 15, 2005 9:47 am
Posts: 2
I haven't been to York for ages....

Back on topic. This is almost what I'm looking for. I found this class: http://www.phpclasses.org/browse/package/3370.html, which extracts the colours from an image as hex values, in descending order of frequency.

What I want to do is this;
- find the most dominant colours in an image
- maintain a finite list of colours in the database, that people can search against (probably around 15)

So as I see it, there are several things I need to do;

(I hope the following is relatively coherent - I'm just writing down what's going on in my head!!)

1. from the list extracted, work out which ones are dominant / frequent enough to warrant being stored against the image
2. given a search colour from a limited set, work out which ones are close enough to provide a match

Now presumably, from the number of pixels in the image and the frequency of a particular colour, I can work out a percentage, then skim off the most dominant colours accordingly. Question is, what on earth should the cut-off point be? Should it be a pre-determined threshold (e.g. 25%)? Should I simply take the x (e.g. 3,4) most frequent colours?

Then of course, I need to either:
- only store the colours that provide a reasonable match to one of my searchable colours, or
- only flag a match when a colour stored against an image is close enough to the colour being searched for

It's starting to sound like I need to come up with some pre-determined, hard-coded values; e.g., a colour is relevant if it comprises more than 25% of an image, and a colour is a match if ABS(".$r."-rVal)+ABS(".$g."-gVal)+ABS(".$b."-bVal) is less than delta.

Anyone got any thoughts as to how I do this, or indeed how I go about choosing these values?


Top
 Profile  
 
PostPosted: Sat Apr 19, 2008 6:36 am 
Offline
Jedi Mod
User avatar

Joined: Tue Dec 21, 2004 6:03 pm
Posts: 5263
Location: usrlab.com
You shouldn't really bump a three year old thread..

What you've suggested there is the right approach anyway.


Top
 Profile  
 
PostPosted: Thu Jan 13, 2011 8:57 pm 
Offline
Forum Newbie

Joined: Thu Jan 13, 2011 8:55 pm
Posts: 1
I hate to re-bump a thread that is yet again over 2 years old since the last comment but Im looking for this solution as well.

Did you come up with the solution? If so, would you mind posting it so others (like me) can see how its done?

Thanks,
S


Top
 Profile  
 
PostPosted: Tue Jan 17, 2012 2:57 am 
Offline
Forum Newbie

Joined: Tue Jan 17, 2012 2:54 am
Posts: 1
I tried the above code, but I do get an error message:
Parse error: syntax error, unexpected '&' in /home/webrage/public_html/foto/test/out.php on line 8

Removing the line, the script works perfect. What is wrong with the section:
Syntax: [ Download ] [ Hide ]
$g   = ($rgb >>  & 0xFF;


Thanks


Top
 Profile  
 
PostPosted: Tue Jan 17, 2012 3:07 am 
Offline
Admin
User avatar

Joined: Wed Aug 13, 2003 7:02 am
Posts: 4522
Location: York, UK
rmfloris wrote:
I tried the above code, but I do get an error message:
Parse error: syntax error, unexpected '&' in /home/webrage/public_html/foto/test/out.php on line 8

Removing the line, the script works perfect. What is wrong with the section:
Syntax: [ Download ] [ Hide ]
$g   = ($rgb >>  & 0xFF;


Thanks


There is a number and a bracket missing, but over the years of forum upgrades, it syntax has been messed up.

I cant remember what the code should look like.


Top
 Profile  
 
PostPosted: Tue Jan 17, 2012 3:41 pm 
Offline
Forum Newbie

Joined: Tue Jan 17, 2012 3:26 pm
Posts: 1
I posted this response to this snippet posted on http://www.catswhocode.com/blog/ regarding the missing 8) and also bad programming:
Quote:
It gives an error if run as is, and it uses way to much memory. This mostly because of the imagesx and imagesy functions are run on EVERY iteration of the pixles. This means that if the image is 100x100 pixles the imagesx will run 101 times and the imagesy will run 10100 times (and this increases with the resolution). Not only is this bad programming but it also slows the snippet down mayor. Since we do no modifications to the $i variable there is no need to recalculate the size of that image on every iteration.

Syntax: [ Download ] [ Hide ]
// How it looks now
for ($x = 0; $x < imagesx($i); $x++) {
    for ($y = 0; $y < imagesy($i); $y++) {


Syntax: [ Download ] [ Hide ]
// Example 1
for ($x = 0, $iX = imagesx($i), $iY = imagesy($i); $x < $iX; $x++) {
    for ($y = 0; $y < $iY; $y++) {


Syntax: [ Download ] [ Hide ]
// Example 2
$iX = imagesx($i);
$iY = imagesy($i);
for ($x = 0; $x < $iX; $x++) {
    for ($y = 0; $y < $iY; $y++) {


My favorite is example 2 since I feel it increases readability, there is no speed difference between example 1 and 2. Both examples only run imagesx one time and imagesy one time, the way it should be.

I also threw a modified version of the snippet on pastie.org: http://pastie.org/3203289
Take note of that I have not modified the core parts of the snippet and the snippet might perform even better if that modification is also made, maybe another day.


The error the original snippet created was that the smiley 8) had been removed. Since the RGB part is taken from the PHP Manual it was easy to find the problem part.
http://php.net/manual/en/function.imagecolorat.php#refsect1-function.imagecolorat-examples

On the PHP Manual page http://php.net/manual/en/control-structures.for.php you can also read:
"This code can be slow because it has to calculate the size of the array on each iteration. Since the size never change, it can be optimized easily using an intermediate variable to store the size and use in the loop instead of..."
Great point for any PHP programmer to check the manual from time to time as you can find great examples even for the most basic functions.


Top
 Profile  
 
 Post subject: Re:
PostPosted: Wed Jan 09, 2013 2:15 am 
Offline
Forum Newbie

Joined: Wed Jan 09, 2013 2:06 am
Posts: 1
onion2k wrote:
First thing you'll need to do is analyse the colours in the image. I do this by creating 3 integers (one each for r, g and b), and aggregating the total value of each channel.

Syntax: [ Download ] [ Hide ]
$i = imagecreatefromjpeg("image.jpg");
for ($x=0;$x<imagesx($i);$x++) {
                for ($y=0;$y<imagesy($i);$y++) {

                        $rgb = imagecolorat($i,$x,$y);
                        $r   = ($rgb >> 16) & 0xFF;
                        $g   = ($rgb >>  & 0xFF;
                        $b   = $rgb & 0xFF;

                        $rTotal += $r;
                        $gTotal += $g;
                        $bTotal += $b;
                        $total++;

                }
        }


If you want to know the average colour of the overall image..

Syntax: [ Download ] [ Hide ]
$rAverage = round($rTotal/$total);
$gAverage = round($gTotal/$total);
$bAverage = round($bTotal/$total);


This will give you the 3 r, g and b values you need to make a colour. At this point I would store these 3 values in the database. Then, if you need to find an image that's closest to a particular colour you can use some simple SQL to find it. Imagine that the r g b colour values have been stored in 3 int columns in the database called rVal, gVal, and bVal, and you've got your colour that you're looking for in 3 seperate components ($r, $g, $b):

Syntax: [ Download ] [ Hide ]
select * from image_table order by ABS(".$r."-rVal)+ABS(".$g."-gVal)+ABS(".$b."-bVal);


This is the technique I used in my image mosaic generator at http://www.ooer.com/mosaic/ .. The code goes through each pixel of the image you upload and selects a similarly coloured image from the database. As you can see .. it's not that slow, and it's pretty cool fun.


This is the main thing that is what i am looking for .ome time ago i was facing this type of problem but after long stugle i found the solution here....thanks dude...you are my super hero .....Thanks one again.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
Powered by phpBB® Forum Software © phpBB Group