Imagerで画像をモノクロにする

最近、ちょっとコードが長過ぎる気がしたので、
今日は短めのコードを載せようと思う。

まずは長ったらしい方から。

use v5.14;
use strict;
use warnings;
use Imager;

if ( (not @ARGV) or (not -e $ARGV[0]) ) {
    say "Usage:
    perl $0 file_path";
    exit( 0 );
}

my $img_src = Imager->new( file => $ARGV[0] )
    or die Imager->errstr();

# Y = (0.299 * red) + (0.587 * green) + (0.114 * blue)
my $img_dst = Imager::transform2( {
    channels => 1,
    constants => {
        fr => 0.299,
        fg => 0.587,
        fb => 1.0 - 0.299 - 0.587
    },
    rpnexpr => 'x y getp1 !pix @pix red fr * @pix green fg * + @pix blue fb * + int !yy @yy @yy @yy rgb'
}, $img_src );

$img_dst or die $Imager::ERRSTR;

$img_dst->write( file => $0 . '.jpg', jpegquality => 90 );

ありがちな係数で輝度を算出して、それをR,G,Bに格納してる。

でも、こんな異常な努力は必要なくて、
R,G,Bに任意の係数を掛けるだけなら、こう書ける。

use v5.14;
use strict;
use warnings;
use Imager;

if ( (not @ARGV) or (not -e $ARGV[0]) ) {
    say "Usage:
    perl $0 file_path";
    exit( 0 );
}

my $img_src = Imager->new( file => $ARGV[0] )
    or die Imager->errstr();

my $img_dst = $img_src->convert(
    matrix => [ [ 0.299, 0.587, (1.0 - 0.299 - 0.587) ] ]
);

$img_dst->write( file => $0 . '.jpg', jpegquality => 90 );

ところで、ありがちな係数で輝度を求めてもいんだけど、
個人的には画像にあった係数を掛けるべきだと思う。
たとえば、今回の例だとピンク色だし、
せっかく露出補正で明るい方に振ったので、
モノクロに変換した後も明るめになって欲しい。

という訳で、適当に係数を変えて変換してみる。

use v5.14;
use strict;
use warnings;
use Imager;

if ( (not @ARGV) or (not -e $ARGV[0]) ) {
    say "Usage:
    perl $0 file_path";
    exit( 0 );
}

my $img_src = Imager->new( file => $ARGV[0] )
    or die Imager->errstr();

my $img_dst = $img_src->convert(
    matrix => [ [ .4, .4, .2 ] ]
);

$img_dst->write( file => $0 . '.jpg', jpegquality => 90 );

ほんとに適当なんだけど、
こんな感じにすると、花のところが少し明るくなる。

という訳で、元画像。

20140803-1

ありがちな係数と、適当な係数で変換した画像。

20140803-2  20140803-3

convertの詳しい使い方は、Imager::Transformationsをどうぞ。

おしまい。

Leave a Comment