Determine dominant image color

Need help with Photoshop, the GIMP, Illustrator, or others? Want to show off your work? Looking for advice on your newest Flash stuff?

Moderator: General Moderators

Determine dominant image color

Postby JayBird » Mon Oct 17, 2005 11:02 am

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.
User avatar
JayBird
Admin
 
Posts: 4522
Joined: Wed Aug 13, 2003 7:02 am
Location: York, UK

Postby Skara » Mon Oct 17, 2005 12:07 pm

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?
User avatar
Skara
Forum Regular
 
Posts: 684
Joined: Sat Mar 12, 2005 8:13 pm
Location: US

Postby onion2k » Mon Oct 17, 2005 2:16 pm

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.
User avatar
onion2k
Jedi Mod
 
Posts: 5263
Joined: Tue Dec 21, 2004 6:03 pm
Location: usrlab.com

Postby JayBird » Mon Oct 17, 2005 3:19 pm

Mate, your a legend! Image

Thanks, looks like just what i need!!
User avatar
JayBird
Admin
 
Posts: 4522
Joined: Wed Aug 13, 2003 7:02 am
Location: York, UK

Postby onion2k » Mon Oct 17, 2005 6:04 pm

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.
User avatar
onion2k
Jedi Mod
 
Posts: 5263
Joined: Tue Dec 21, 2004 6:03 pm
Location: usrlab.com

Postby feyd » Mon Oct 17, 2005 6:46 pm

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

Postby Chris Corbyn » Mon Oct 17, 2005 7:28 pm

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 :(
User avatar
Chris Corbyn
Breakbeat Nuttzer
 
Posts: 13098
Joined: Wed Mar 24, 2004 8:57 am
Location: Melbourne, Australia

Postby JayBird » Tue Oct 18, 2005 3:48 am

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!
User avatar
JayBird
Admin
 
Posts: 4522
Joined: Wed Aug 13, 2003 7:02 am
Location: York, UK

Re: Determine dominant image color

Postby hukkas » Sat Apr 19, 2008 5:52 am

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?
hukkas
Forum Newbie
 
Posts: 2
Joined: Wed Jun 15, 2005 9:47 am

Re: Determine dominant image color

Postby onion2k » Sat Apr 19, 2008 6:36 am

You shouldn't really bump a three year old thread..

What you've suggested there is the right approach anyway.
User avatar
onion2k
Jedi Mod
 
Posts: 5263
Joined: Tue Dec 21, 2004 6:03 pm
Location: usrlab.com

Re: Determine dominant image color

Postby midwest22 » Thu Jan 13, 2011 8:57 pm

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
midwest22
Forum Newbie
 
Posts: 1
Joined: Thu Jan 13, 2011 8:55 pm

Re: Determine dominant image color

Postby rmfloris » Tue Jan 17, 2012 2:57 am

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
rmfloris
Forum Newbie
 
Posts: 1
Joined: Tue Jan 17, 2012 2:54 am

Re: Determine dominant image color

Postby JayBird » Tue Jan 17, 2012 3:07 am

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.
User avatar
JayBird
Admin
 
Posts: 4522
Joined: Wed Aug 13, 2003 7:02 am
Location: York, UK

Re: Determine dominant image color

Postby XeroXer » Tue Jan 17, 2012 3:41 pm

I posted this response to this snippet posted on http://www.catswhocode.com/blog/ regarding the missing 8) and also bad programming:
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.
XeroXer
Forum Newbie
 
Posts: 1
Joined: Tue Jan 17, 2012 3:26 pm

Re:

Postby simonclark » Wed Jan 09, 2013 2:15 am

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.
simonclark
Forum Newbie
 
Posts: 1
Joined: Wed Jan 09, 2013 2:06 am

Next

Return to Graphics

Who is online

Users browsing this forum: No registered users and 1 guest