とりあえずHSVでフィニッシュ
ん〜。やっぱりHSVでの判定ですかね・・・?
ということで、先日のヤツを部分的に手直しした物をベベっと貼っておこう。
ソースさん(一部)
#!perl (省略) # どっかで &pickup_image_colors(ファイル名)みたいに呼ぶ。 # 戻り値は、成功1/失敗0, 一つ目の色, 二つ目の色 で返ってきます。 sub pickup_image_colors { my($file, $width, $height, $hantei) = @_; if(! $file) {return(0);} # Miss if(! $width) {$width = 100;} if(! $height) {$height = $width;} if(! $hantei) {$hantei = 432;} my $rate_sum = 0; my @color = ( ['blacK' , 0, 0], ['Blue' , 1, 0], ['Green' , 2, 0], ['Cyan' , 3, 0], ['Red' , 4, 0], ['Purple', 5, 0], ['Yellow', 6, 0], ['White' , 7, 0], ); GD::Image->trueColor(1); my $srcimage = GD::Image->new($file); if(! $srcimage) {return(0);} # Miss my($src_width, $src_height) = $srcimage->getBounds(); # サイズを変更して処理する my $image = GD::Image->new($width, $height); if(! $image) {return(0);} # Miss $image->copyResampled($srcimage, 0,0, 0,0, $width,$height, $src_width,$src_height); if(! $image) {return(0);} # Miss for(my $y = 0; $y < $height; $y++) { for(my $x = 0; $x < $width; $x++) { # get pixel color my($h, $s, $v) = &rgb_to_hsv($image->rgb($image->getPixel($x, $y))); # rate setting my $rate = 1; $rate_sum += $rate; # HSV if(($hantei - ($s * 8) > $v) || ($hantei - ($v * 8) > $s)) { if($v < 121) {$color[0][2] += $rate;} # blacK else {$color[7][2] += $rate;} # White } else { if ($h < 40) {$color[4][2] += $rate;} # Red elsif($h < 75) {$color[6][2] += $rate;} # Yellow elsif($h < 150) {$color[2][2] += $rate;} # Green elsif($h < 210) {$color[3][2] += $rate;} # Cyan elsif($h < 270) {$color[1][2] += $rate;} # Blue elsif($h < 330) {$color[5][2] += $rate;} # Purple else {$color[4][2] += $rate;} # Red } } } # Res @color = sort {@$b[2] <=> @$a[2]} @color; if(($color[0][2] / $rate_sum) > 0.9) { $color[1][0] = $color[0][0]; $color[1][1] = $color[0][1]; } return(1, $color[0][0], $color[1][0]); } sub rgb_to_hsv { my($r, $g, $b) = @_; my($h, $s, $v); my($min, $max); if($r < $g) {$min = $r; $max = $g;} else {$min = $g; $max = $r;} if ($max < $b) {$max = $b;} elsif($min > $b) {$min = $b;} $v = $max; if($v == 0 || $max == $min) {$h = 0; $s = 0;} else { $s = 255 * ($max - $min) / $max; my $cal_r = ($max - $r) / ($max - $min); my $cal_g = ($max - $g) / ($max - $min); my $cal_b = ($max - $b) / ($max - $min); $h = $max == $r ? 60 * ( $cal_b - $cal_g): $max == $g ? 60 * (2 + $cal_r - $cal_b): 60 * (4 + $cal_g - $cal_r); if($h >= 360) {$h -= 360;} elsif($h < 0) {$h += 360;} } return(int($h), int($s), int($v)); }
こんな感じでどーでしょ。
相変わらず力技ですが・・・。
グレーの扱い
この方法でも、やっぱり白黒の扱いが微妙ですね。
黒白は一色たんにして評価して、ランキングに入ったら、黒白の平均値で黒か白かを決定する方がいいかもしれないですねー。てかLabとかの方がいいかもしれないけどアレ計算がちょいと重くないですか。
まあ、そんなにこだわらなくてもいいかなー。こういうのPerlでやるのが間違ってる?w