Image-DominantColors

 view release on metacpan or  search on metacpan

lib/Image/DominantColors.pm  view on Meta::CPAN

package Image::DominantColors;

use 5.006;
use strict;
use warnings FATAL => 'all';
use Data::Dumper;
use Imager;
use Imager::Fill;
use Image::ColorCollection;
use POSIX;
 
our $VERSION = '0.02';


sub new {
	my ($class, $params) = @_;
	my $self = undef;
	if($params) {
		$self =  $params;
	} else {
	#carp die. We need a filename...
	}
	bless $self, $class;
	return $self;
}

sub getDominantColors {
	my $class = shift;
	my $img = Imager->new(file => $class->{file});
	my $clusters = 3;
	my $clus = $class->{clusters};
	if($clus)
	{
		$clusters = $clus;
	}
	my $h = $img->getheight() - 1;
	my $w = $img->getwidth() - 1;

	my @colors = ();
	for (my $j = 0; $j < $w; $j++) {
		for (my $k = 0; $k < $h; $k++) {
			my $oth = $img->getpixel(x => $j, y => $k);
			my ($red, $green, $blue, $alpha) = $oth->rgba();
			push (@colors, {
				r => $red,
				g => $green,
				b => $blue,
			});
		}		
	}

	my @centroids = ();
	for (my $i = 1; $i <= $clusters; $i++) {
		my $cc = Image::ColorCollection->new();
		push @centroids, $cc;
	}
	
	my $shft = 100;
	my $it = 0;#track iterations
#	print "TotalCentroid : ".scalar(@centroids);
	while($shft != 0)
	{
		foreach my $col (@colors) {
			my $min = LONG_MAX;
			my $cent = undef;
#				print "TotalCentroidAgainb : ".scalar(@centroids);
			foreach my $c (@centroids) {
				#print Dumper($c);
				my $d = int(euclideanDist($col, $c->getCentroid()));
				if($d < $min)
				{
					$min = $d;
					$cent = $c;					
				}
			}
			$cent->addColor($col);			
		}
		my $localShft = 0;
		foreach my $cnt (@centroids) {
			$localShft += $cnt->updateCentroid();
			$cnt->clear();
		}
		$shft = $localShft;
		$it++;				
#		print "Iteration : $it , shift : $shft\n";
	}
	my @ret = map { $_->getCentroid() } @centroids;
	return \@ret;
}
sub euclideanDist {
	my ($c1, $c2) = @_;
	return sqrt((($c1->{r}-$c2->{r})**2) + (($c1->{g}-$c2->{g})**2) + (($c1->{b}-$c2->{b})**2));
}

1; # End of Image::DominantColors
__END__


=head1 NAME

Image::DominantColors - Find dominant colors in an image with k-means clustering.

=head1 VERSION

Version 0.01

=cut




=head1 SYNOPSIS

This module does just one simple thing. It scans an image and clusters colors with the L<k-means clustering|http://en.wikipedia.org/wiki/K-means_clustering> 
algorithm to give you the most dominant colors in that image.

Here is a live demo : L<http://www.tryperl.com/dominantcolors/>

This is how it works, I would advise leaving the clusters to a default 3 which works best with images.:



( run in 1.207 second using v1.01-cache-2.11-cpan-71847e10f99 )