Cytat(Mephistofeles @ 13.12.2010, 09:57:44 )

Określić "odległość" koloru od środka zakresu kolorów, a potem posortować i wziąć najmniejszą?
Moglbys dokladniej opisac metode znalezienia podobnych?
Zauwaz ze biorac odleglosc od srodka uwzgledniasz chyba tylko zmiane jasnosci ale nie juz odcienia wiec rozowy tym sposobem nie bedzie podobny do czerwonego, hmmmmm
EDIT:
Napisałem taką klasę:
<?php
class avgColor {
var $pixProbX = 10; //Eg. if img is 120x120 script probe for pixel #0, 10, 20 etc
var $pixProbY = 10; //See above
private $imgRes; //Loaded GD2 resource image
private $imgResY; //Img height [axis Y]
private $imgResX; //Img width [axis X]
private $colorMap; //Table of color in image
private $totalProbPix; //Total probbed pixels - used for % calculation
function __construct($imgPath) {
return false;
}
$this->imgResY = $imgInfo[1];
$this->imgResX = $imgInfo[0];
switch($imgInfo["mime"]) {
case "image/jpeg": $this->imgRes = imagecreatefromjpeg($imgPath); break;
case "image/png": $this->imgRes = imagecreatefrompng($imgPath); break;
case "image/gif": $this->imgRes = imagecreatefromgif($imgPath); break;
case "image/jpeg": $this->imgRes = imagecreatefromjpeg($imgPath); break;
}
}
function trcArr(&$arr, $elements=10) {
$i=1;
foreach($arr as $key=>$val) {
if($i<=$elements) $ret[$key] = $val;
$i++;
}
$arr=$ret;
}
function mapColors($el=10) { //Make colors map in image with counter.
if($this->imgResY < $this->pixProbY) $this->pixProbY = $this->imgResY; //If Y axis is smaller than defined probing use maximum value
if($this->imgResX < $this->pixProbX) $this->pixProbX = $this->imgResX; //Same as above for X axis
$loopsY = (int)($this->imgResY/$this->pixProbY); //Number of samples, cutted to int, Y axis
$loopsX = (int)($this->imgResX/$this->pixProbX); //Same as above for X axis
if($loopsY==0
|| $loopsX==0
) { trigger_error("Cannot make colormap for $imgPath - loops for X/Y axis == 0", E_USER_ERROR
); return; } //Check psblt. $this->totalProbPix = $loopsY+$loopsX;
//echo "Y=".$this->imgResY." | X=".$this->imgResX." | prbY=".$this->pixProbY." | prbX=".$this->pixProbX."\n\n";
//if($loopsX > $loopsY) { //If image contain more "rows" than "columns" typed to parsing parse by columns
for($y=0;$y<$loopsY;$y++) { //Loop for columns
for($x=0;$x<$loopsX;$x++) { //Loop for pixels in column
$rgb = imagecolorat($this->imgRes, ($x*$this->pixProbX), ($y*$this->pixProbY));
@$this->colorMap[(($rgb >> 16) & 0xFF).".".(($rgb >> 8) & 0xFF).".".($rgb & 0xFF)]++;
}
}
//} else { //...or if image contain more "cols" than "rows" typed to parsing parse row-by-row and then probe every pixel in row
//}
arsort($this->colorMap); //Sort arr $this->trcArr($this->colorMap, $el); //Strip array
return $this->colorMap;
}
function mostUsedColor(&$map) {
$muc["key"] = explode(".", $muc["key"]); $ret["color"] = dechex($muc["key"][0
]).dechex($muc["key"][1
]).dechex($muc["key"][2
]); //Make hex notation of color $ret["percent"] = round((($muc["value"]/$this->totalProbPix)*100
),2
); //Calculate percen value
return $ret;
}
}
?>
Przykład użycia:
<?php
require_once("sim.class.php");
$_sim = new avgColor("imgs/647636.jpg");
var_dump($_sim->mostUsedColor($_sim->mapColors())); ?>
Klasa ładnie wygciąga najczęściej występujący kolor ale dla tapety 1280x1024 jest dość wolna gdy analizuje się każdy pixel ($pixProbX oraz $pixProbY na 1), jeśli natomiast zmniejszy się dokładność o 10x to działa szybko no ale.... (IMG:
style_emoticons/default/smile.gif)
Ma ktoś inny pomysł? Dodatkowo pozostaje kwestia porównania.
EDIT2:
Wracam z nowym kodem (IMG:
style_emoticons/default/smile.gif) Dodałem metodę avgColor która jest o 2-2.5x szybsza ale ciągle dla 4k x 3k trwa to blisko 20sekund (IMG:
style_emoticons/default/smile.gif)
<?php
class avgColor {
var $pixProbX = 1; //Eg. if img is 120x120 script probe for pixel #0, 10, 20 etc
var $pixProbY = 1; //See above
private $imgRes; //Loaded GD2 resource image
private $imgResY; //Img height [axis Y]
private $imgResX; //Img width [axis X]
private $colorMap; //Table of color in image
private $totalProbPix; //Total probbed pixels - used for % calculation | value for most used color
private $totalPixAvg; //Similar to above but for avg color calculation
function __construct($imgPath) {
return false;
}
$this->imgResY = $imgInfo[1];
$this->imgResX = $imgInfo[0];
switch($imgInfo["mime"]) {
case "image/jpeg": $this->imgRes = imagecreatefromjpeg($imgPath); break;
case "image/png": $this->imgRes = imagecreatefrompng($imgPath); break;
case "image/gif": $this->imgRes = imagecreatefromgif($imgPath); break;
case "image/jpeg": $this->imgRes = imagecreatefromjpeg($imgPath); break;
}
}
function trcArr(&$arr, $elements=10) {
$i=1;
foreach($arr as $key=>$val) {
if($i<=$elements) $ret[$key] = $val;
$i++;
}
$arr=$ret;
}
private function mapColors($el=10) { //Make colors map in image with counter.
if($this->imgResY < $this->pixProbY) $this->pixProbY = $this->imgResY; //If Y axis is smaller than defined probing use maximum value
if($this->imgResX < $this->pixProbX) $this->pixProbX = $this->imgResX; //Same as above for X axis
$loopsY = (int)($this->imgResY/$this->pixProbY); //Number of samples, cutted to int, Y axis
$loopsX = (int)($this->imgResX/$this->pixProbX); //Same as above for X axis
if($loopsY==0
|| $loopsX==0
) { trigger_error("Cannot make colormap for $imgPath - loops for X/Y axis == 0", E_USER_ERROR
); return; } //Check psblt. $this->totalProbPix = $loopsY+$loopsX;
//echo "Y=".$this->imgResY." | X=".$this->imgResX." | prbY=".$this->pixProbY." | prbX=".$this->pixProbX."\n\n";
//if($loopsX > $loopsY) { //If image contain more "rows" than "columns" typed to parsing parse by columns
for($y=0;$y<$loopsY;$y++) { //Loop for columns
for($x=0;$x<$loopsX;$x++) { //Loop for pixels in column
$rgb = imagecolorat($this->imgRes, ($x*$this->pixProbX), ($y*$this->pixProbY));
@$this->colorMap[(($rgb >> 16) & 0xFF).".".(($rgb >> 8) & 0xFF).".".($rgb & 0xFF)]++;
}
}
//} else { //...or if image contain more "cols" than "rows" typed to parsing parse row-by-row and then probe every pixel in row
//}
arsort($this->colorMap); //Sort arr $this->trcArr($this->colorMap, $el); //Strip array
return $this->colorMap;
}
function mostUsedColor() {
$this->mapColors(1); //Make color map
$muc = each($this->colorMap); $muc["key"] = explode(".", $muc["key"]); $ret["color"] = dechex($muc["key"][0
]).dechex($muc["key"][1
]).dechex($muc["key"][2
]); //Make hex notation of color $ret["percent"] = round((($muc["value"]/$this->totalProbPix)*100
),2
); //Calculate percen value
return $ret;
}
function avgColor() { //Analyze every pixel and return avg color
$this->totalPixAvg=0;
$color=array("r"=>0,"g"=>0,"b"=>0,"rgb"=>"fff"); for ($x=0;$x<imagesx($this->imgRes);$x++) {
for ($y=0;$y<imagesy($this->imgRes);$y++) {
$rgb = imagecolorat($this->imgRes, $x, $y);
$color["r"] += (($rgb >> 16) & 0xFF);
$color["g"] += (($rgb >> 8) & 0xFF);
$color["b"] += $rgb & 0xFF;
$this->totalPixAvg++;
}
}
$color["r"] = round($color["r"]/$this->totalPixAvg); $color["g"] = round($color["g"]/$this->totalPixAvg); $color["b"] = round($color["b"]/$this->totalPixAvg);
return $color;
}
}
?>
<?php
/********************************************************************************
*/
function _st() {
return $mtime[1] + $mtime[0];
}
function _et($_st) {
$execT = (($mtime[1] + $mtime[0]) - $_st);
echo "\n\n".str_repeat("-", 40)."\nExec time: ".(($execT<1
)?
($execT*1000)."ms":$execT."s")."\n\n"; }
/********************************************************************************
*/
require_once("sim.class.php");
$_sim = new avgColor("imgs/647596.jpg");
$_st=_st();
//var_dump($_sim->mostUsedColor());
_et($_st);
?>
Ten post edytował kiler129 14.12.2010, 09:48:13