画像の色情報を平均化し、単色にする方法
画像を、単純化して置き換えるような処理をしたかった。
そのために、画像内の色情報を複数プロットし、平均化する処理を書いてみた。
Image::Magick使って、色情報取得
package Package; use strict; use Image::Magick; sub new { my ($pkg, $param) = @_; my $hash = { img => $param->{'img'}, plot => (defined $param->{'plot'} and $param->{'plot'} > 0) ? $param->{'plot'} : 3, }; return bless $hash, $pkg; } sub get_average_color { my ($self) = shift; my $image = Image::Magick->new; $image->Read($self->{'img'}); my($width, $height)= $image->Get('width', 'height'); if ($width < $self->{'plot'} or $height < $self->{'plot'}) { return 0; } my $return_info = {}; my ($one_plot_x,$one_plot_y) = ($width / $self->{'plot'}, $height / $self->{'plot'}); my ($x, $y) = (int ($one_plot_x / 2), int ($one_plot_y / 2)); my $color_info = { r => 0, g => 0, b => 0, count => 0, }; for (my $i = 0; $i < $self->{'plot'}; $i++) { for (my $j = 0; $j < $self->{'plot'}; $j++) { my ($r, $g, $b, $ugh) = split ',', $image->Get("pixel[" . $x . "," . $y . "]"); #画像の一部が透明処理されていた場合、背景色が白という前提で補正。 #背景色が白じゃない場合、もう、そんなことわからん・・。 $r += $ugh if $ugh != 0; $r = 65535 if $r > 65535; $g += $ugh if $ugh != 0; $g = 65535 if $g > 65535; $b += $ugh if $ugh != 0; $b = 65535 if $b > 65535; #RGBそれぞれで色を足していく $color_info->{'r'} += $r; $color_info->{'g'} += $g; $color_info->{'b'} += $b; $color_info->{'count'}++; $x += $one_plot_x; } $x = int ($one_plot_x / 2); $y += $one_plot_y; } #プロットした数で割り、平均を出す $color_info->{'r'} = int($color_info->{'r'} / $color_info->{'count'}); $return_info->{'r'} = $color_info->{'r'}; $color_info->{'g'} = int($color_info->{'g'} / $color_info->{'count'}); $return_info->{'g'} = $color_info->{'g'}; $color_info->{'b'} = int($color_info->{'b'} / $color_info->{'count'}); $return_info->{'b'} = $color_info->{'b'}; #16進数化 $color_info->{'r'} = int($color_info->{'r'} / 256); $color_info->{'g'} = int($color_info->{'g'} / 256); $color_info->{'b'} = int($color_info->{'b'} / 256); $color_info->{'r'} = unpack("H2", pack("C", $color_info->{'r'})); $color_info->{'g'} = unpack("H2", pack("C", $color_info->{'g'})); $color_info->{'b'} = unpack("H2", pack("C", $color_info->{'b'})); #16以下だった場合、先頭に0を付加 $color_info->{'r'} = "0".$color_info->{'r'} if ($color_info->{'r'} =~ /^[0-9a-fA-F]{1}$/); $color_info->{'g'} = "0".$color_info->{'g'} if ($color_info->{'g'} =~ /^[0-9a-fA-F]{1}$/); $color_info->{'b'} = "0".$color_info->{'b'} if ($color_info->{'b'} =~ /^[0-9a-fA-F]{1}$/); $return_info->{'color'} = $color_info->{'r'} . $color_info->{'g'} . $color_info->{'b'}; return $return_info; }
結果
$VAR1 = { 'color' => 'b6d6d8', 'r' => 46680, 'b' => 55465, 'g' => 55019 };
ここ数日やってたやりたいことが、ほぼほぼ完成したよ。
公開環境できたら、公開します。