# アニメ顔切り取りスクリプト use strict; use warnings; use Imager; use Imager::AnimeFace; use File::Spec::Functions; use List::Util qw/min max/; use Storable qw/nstore/; use constant { FACE_THRESHOLD => 0.7, # 顔検出の閾値(0.5~1.0) 高いほど厳しい THUMB_SIZE => 160, # サムネのサイズ MARGIN_SCALE => 1.0 / 32 * 28, # 顔の周りのマージン THUMB_FORMAT => 'png' # 画像フォーマット }; $| = 1; my $input_dir = shift @ARGV; my $output_dir = shift @ARGV; unless ($input_dir && $output_dir) { die "usage: $0 input_dir output_dir\n"; } unless (-d $output_dir) { mkdir($output_dir) || die "$output_dir: $!\n"; } opendir(DIR, $input_dir) || die "$input_dir: $0\n"; my $img = new Imager; my %face_info; foreach my $file (readdir(DIR)) { next unless (-f catfile($input_dir, $file)); next unless ($img->read(file => catfile($input_dir, $file))); print "$file ..\r"; my $results = detect_animeface($img); foreach my $face (@$results) { next if ($face->{likelihood} < FACE_THRESHOLD); my $margin = int($face->{face}->{width} * MARGIN_SCALE); my $thumb_name = sprintf( "face_%d_%d_%s.%s", $face->{face}->{x}, $face->{face}->{y}, (split(/\./, $file))[0], THUMB_FORMAT ); my $thumb_path = catfile($output_dir, $thumb_name); my $thumb = $img->crop( left => max( 0, $face->{face}->{x} - $margin ), right => min( $img->getwidth(), $face->{face}->{x} + $face->{face}->{width} + $margin ), top => max( 0, $face->{face}->{y} - ($margin + int($margin / 2)) ), bottom => min( $img->getheight(), $face->{face}->{y} + $face->{face}->{height} + ($margin - int($margin / 2)) ) ); $thumb = $thumb->scale( scalefactor => THUMB_SIZE / max($thumb->getwidth(), $thumb->getheight()) ); $thumb->write(file => $thumb_path, type => THUMB_FORMAT); $face_info{$thumb_name} = $face; } } closedir(DIR); nstore(\%face_info, catfile($output_dir, "info.bin"));