Imagerで画像を回転させる
回転させるだけならrotate
で出来るんだけど、
小ネギを直立させつつ、重なっている小ネギの判定も行う。
やることは、ラベリングした画像の回転と範囲の取得を繰り返して、
幅が最小になる角度を取得する。
重なりがあると、幅と高さの比がしきい値を下回らないので、
その範囲に存在する小ネギは無視する。
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 = Imager->new( file => $ARGV[0] ) or die Imager->errstr(); my $cur_angle = .0; my $cur_value = calc_evaluation_value( $img, $cur_angle ); my $step = 32.0; while ( 0.1 < abs($step) ) { my $new_angle = $cur_angle + $step; my $new_value = calc_evaluation_value( $img, $new_angle ); printf( "Current %5.1f: %3d, New %5.1f: %3d\n", $cur_angle, $cur_value, $new_angle, $new_value ); if ( $new_value < $cur_value ) { $cur_value = $new_value; $cur_angle = $new_angle; } else { $step *= -0.5; } } $img->rotate( degrees => $cur_angle, back => 'black' )->write( file => $0 . '.png' ); sub calc_evaluation_value { my ( $img, $rot_angle ) = @_; my $img_tmp = $img->rotate( degrees => $rot_angle, back => 'black' ); my $xmin = int( $img_tmp->getwidth() / 2 ); my $xmax = int( $img_tmp->getwidth() / 2 ); my $iy = $img_tmp->getheight(); while ( 0 < $iy-- ) { my $tmp = $img_tmp->getsamples( y => $iy, channels => [0] ); my @pixels = unpack( 'C*', $tmp ); if ( grep { $_ == 255 } @pixels ) { my $st = 0; $st++ while $pixels[$st] != 255; my $en = scalar(@pixels) - 1; $en-- while $pixels[$en] != 255; $xmin = $st if $st < $xmin; $xmax = $en if $xmax < $en; } } return $xmax - $xmin + 1; }
あんまし、うまく書けた感じはしないけど、
前回に切り抜いて出力した画像を入力すると、ちゃんと直立する。
後者は重なっているので、幅と高さの比を見て重なり判定ができる。
もちろん、その前に余白を除いた画像を作り直す必要はあるけど。
おしまい。
Leave a Comment