PerlとImageMagickを使ってモザイク画像を作る

単純なPerlスクリプトを使って、画像操作やテキスト作成、モザイク画像の合成などを自動化しましょう。ここではImageMagickやGD、The Gimpなどの使い方を学びながら、静止表示や動的コンテンツに適した、独自のモザイク画像を作ります。また、ImageMagickやオープンソースのグラフィカル編集ツールの機能についても解説します。

Nathan Harrington, Programmer, EMC

Nathan Harrington は IBM のプログラマーで、現在 Linux とリソース特定技術に従事しています。


developerWorks 貢献著者レベル

2006年 1月 24日

モザイク画像は視覚的に訴える力があることや、技術的に進んだ印象を与えるため、今日の印刷メディアやビデオ・メディアで、よく使用されています。この記事では、テキストやグラフィック・コンテンツを使って、皆さん独自の、単純なモザイク画像を作るための方法を説明します。この記事で解説する手法は、静的な、あるいは動的なコンテンツ作成に応用することができます。一例としてIBMの従業員は、この記事の元となっているツールを使って、自分たちの上司の名前を、その上司の下で働く従業員のモザイク画像で構成することができるのです。

そのためにはPerlを使って画像にアクセスし、またその画像を「タイル状」のモザイクに修正した後、Perlスクリプトの中にあるGDモジュールを使って画像を処理します。GDは、Perlの中でテキスト・オーバーレイを作るためにも使われています。最終的な結果を合成するためには、ImageMagickツール・スイートを使います。またThe Gimp画像操作ツールを使って、Linux®のマスコットであるペンギン、「タックス(Tux the penguin)」に少し手を加え、Linuxテーマのモザイク画像を作ります。

必要なシステム

ハードウェア

画像の操作や合成処理は、メモリーやCPUへの負荷が非常に高い作業です。この記事で使用したシステムは、500-MHzのPentium® IIIに512 MBのRAMを積んでいます。もっと遅いシステムでも動作するはずですが、少なくとも256 MBのRAMを推奨します(作成する画像ファイルのサイズは約6メガピクセルです)。

ソフトウェア

PerlとGD、The Gimp、そしてImageMagickが必要です。これらはどれも、ほとんどのLinuxディストリビューションで、デフォルトでインストールされています。これらのツールを見つけるための情報については、参考文献を見てください。『feh』は、画像を見るための素晴らしいプログラムであり、モザイク・タイルの処理に大いに役立ちます。


モザイク・タイル画像

画像の取得

IBMの内部リソースには、従業員の写真のリポジトリーがあり、各自の業務責任とリンクされています。私はこの業務責任フィールドを検索し、developerWorksに責任を持つ従業員すべての写真を取り出しました。Webからの画像を使ってライブラリーを構成するための素晴らしいツールは数多くありますが、これらの中にはモザイク画像作成に適したものも幾つもあります。この記事用のソースコード・パッケージの中には、幾つかの画像も入れておきました(ダウンロードのセクションを見てください)。

タイルの処理

画像のソースが何であれ、ほとんどの場合はモザイクに使用するために何らかの処理が必要です。私が手にした一連の写真はサイズが様々であり、またモザイクに使用するには望ましくない、「デフォルト」画像から構成されているものもありました。必要のない画像は、fehビューアーを使って削除します。

  1. 画像ディレクトリーの内容の概要を把握するために、feh -t images/ というコマンドを使います。各画像がサムネイル状で得られ、また各画像の下にファイル名が付けられます。
図 1.  Fehのサムネイル・モード
Fehのサムネイル・モード
  1. fehのコマンド、feh -F -d -A "rm %f" images/ を使って、必要のない画像を削除します。これによって、フルスクリーン・モードで各画像を順次見られるようになります。スペース・バーを押すと次の画像に進み、削除すべき画像の所に来たらEnterキーを押すと、「-A "rm %f"」オプションによって、その画像が削除されます。この例では、青と白のデフォルト画像はすべて削除しています。
  2. これで必要な画像だけが集まったので、すべての画像が同じサイズになるようにします。このデモでは、25 x 25のピクセルが適当です。このサイズであれば、内容を確認するには充分な大きさであり、最終的な画像の視覚要素として使うには充分に小さいのです。ImageMagickのコマンド、mogrify -geometry 25 x 25 images/* を使うと、すべての画像を同じサイズにすることができます。このコマンドは、画像の大きさを25 x 25に制限する一方、縦横比は同じに保つことに注意してください。

テキスト・オーバーレイ・モザイク

モザイク用のテキスト内容としては、「developerWorks」を使います。また白いテキストを持った透明画像を作成する必要があります(このテキストの中に、後でタイルを合成します)。これは、以下の手順で行います。

  1. overlaysというディレクトリーを作成します。
  2. 次のコードを使って、build_text_overlay.plというファイルを作成します。
リスト1.  build_text_overlay.pl
#!/usr/bin/perl -w
# build_text_overlay.pl, creates the transparent image with user specified
# text in the foreground
use strict;  
use GD;  # graphics library

my $text = $ARGV[0] or die "Please specify text\n";  # text to overlay

my $textlen = length($text);  # length of text

# specify your font location here:
# remember that if you change the font, the magic number needs 
# to change to give the image the appropriate width  
my $font = "./VeraMoBd.ttf";
my $width = 400 * $textlen;   # 400 is magic number suitable for VeraMoBd font

# create a new GD image of $width, 600 pixels high so it will fit nicely on
# the screen, and the printed page
my $image = new GD::Image($width,600);

# initialize some colors
my $white = $image->colorAllocate(255,255,255);

$image->transparent($white);  # set white as transparent

# write the file to disk
open(PNGOUT,"> overlays/empty_white_$text.png") or die
  "can't write to output file overlays/empty_white_$text.png";
print PNGOUT $image->png;
close(PNGOUT);

# setup convert command with font, foreground color, fontsize
# -draw 'text 50,490' gives a nice offset from the top left corner
my $res = qq{ convert -font  $font  }.
          qq{ -fill "#ffffff" -pointsize 601 -draw 'text 50,490 "$text"' }.
          qq{ overlays/empty_white_$text.png overlays/done_$text.png};

$res =`$res`; # run the command
  1. 添付されているVeraMoBd.ttfファイルを作業ディレクトリーにダウンロードします。
  2. build_text_overlay.plスクリプト、perl build_text_overlay.pl developerWorksを実行します。
  3. オーバーレイ画像を、コマンド、feh overlays/done_developerWorks.pngを使ってチェックします。

これでオーバーレイ・テキストが作成されたので、同じサイズを持つタイル状の背景画像を作成し、次にこの2つを合成します。

  1. backgroundsディレクトリーを作成します。
  2. テキスト・オーバーレイのサイズを、identify overlays/done_developerWorks.pngというコマンドで決定します。この場合、オーバーレイのサイズが5,600 x 600であることが分かると思います。
  3. 次のコードを使って、build_background.plというファイルを作成します。
リスト2.  build_background.pl
#!/usr/bin/perl -w
# build_backgroun.pl, creates the tiled background of mosaic images
use strict;
use GD;  # image library
use List::Util 'shuffle';  # to randomize the image list

my $im_width = $ARGV[0] or die "specify an image width, height, and filename";
my $im_height = $ARGV[1] or die "specify an image width, height, and filename";
my $filename = $ARGV[2] or die "specify an image width, height, and filename";

my @tilelist = `ls -1 images/`;  # create an array of tile images
my @randlist = shuffle(@tilelist);  # randomize the array

# create a new image in true color for background only
my $backimage = new GD::Image($im_width,$im_height);

# initialize some colors
my $white = $backimage->colorAllocate(255,255,255);
my $black = $backimage->colorAllocate(0,0,0);

# write the file to disk
open(PNGOUT,"> backgrounds/backimage_$filename.png") or die
  "can't write to output file backgrounds/backimage_$filename.png";
print PNGOUT $backimage->png;
close(PNGOUT);

# create a new image in true color
my $image = new GD::Image($im_width,$im_height,1);

my $xpos = 0;  # incrementer for x axis
my $ypos = 0;  # incrementer for y axis
my $row_total = $im_height / 25; # number of rows for a 600 pixel high image

# for each row
while( $ypos <=  $row_total ){
  $xpos = 0;
  #for each column
  while( $xpos <= $im_width ){

    # if the random list is all used up, regenerate it
    if( @randlist < 1 ){
      @randlist = ();
      @randlist = shuffle(@tilelist);
    }

    # remove image from random list so it is not reused in this row
    my $currimage = pop @randlist;

    # open the image
    my $tileimg = newFromJpeg GD::Image( "images/$currimage");

    # insert the image into the existing large template
    $image->copy($tileimg,$xpos,($ypos*25),0,0,25,25);

    # move to next column
    $xpos += 25;

  }#while xpos < = width

  # move to next row
  $ypos++;

}#while coutn < $width 

# write out the image
open( TILEOUT,"> backgrounds/back_$filename.png") or die
   "can't write to backgrounds/back_$filename.png";
  print TILEOUT $image->png;
close(TILEOUT);
  1. 「identify」コマンドで決まった大きさを使って、build_background.plスクリプトを実行します。(つまり、perl build_background.pl 5600 600 developerWorks)
  2. feh backgrounds/back_developerWorks.pngというコマンドを使って、背景画像を確認します。

これで、背景用のタイル画像と、透明な背景オーバーレイを持つ白いテキストができたので、2つを合成する準備が整いました。compositeディレクトリーを作成し、ImageMagickのcompositeコマンドを使って、両者を重ね合わせます(下記)。

composite -compose in \
  backgrounds/back_developerWorks.png \
  overlays/done_developerWorks.png \
  composite/step1_developerWorks.png

この場合、-compose inオプションはImageMagickに対して、オーバーレイの白レイヤーを実質的に『パススルー』レイヤーとして扱うように伝えています。これによって、タイル状のモザイクで塗りつぶされた白いテキストを持った、透明な背景が作られます。

今度は、白い背景を適用します。多くのpngリーダー(Internet Explorerなど)は、背景が透明な場合には、背景を白ではなく黒として表示するため、このステップが必要となります。

composite -compose over \
  composite/step1_developerWorks.png \
  backgrounds/backimage_developerWorks.png \
  composite/complete_developerWorks.png

-compose overオプションはImageMagickに対して、2番目の画像の上に最初の画像をオーバーレイするように伝えています。これで最終的な作品ができあがります。最終的な結果を見るためには、feh composite/complete_developerWorks.pngをタイプします。小さなモザイクのバージョンを作るには、次のようにconvertを使います。

convert -resize 800x600 \
  composite/complete_developerWorks.png \
  composite/800x600_complete_developerWorks.png
図 2.  developerWorksテキスト・オーバーレイ(「e」は詳細を示すために拡大されています)
developerWorksテキスト・オーバーレイ(「e」は詳細を示すために拡大されています)

これで終わりです。テキスト・オーバーレイが完成しました。同じ手順を使って、皆さんの好きなテキストでテキスト・オーバーレイを作ることができます。また、別の画像をプラグインすることもできます。皆さんの持っている既存のグラフィック・コンテンツにモザイクを追加することもでき、あるいは、大型のプリンターで画像を印刷することができます。背景の画像生成コードを変更して、各タイルの正確な座標を記録するように変更することも、容易にできます。この情報を使うと、ユーザーの画像がモザイクのどこにあるかを示す動的なアプリケーションを作成することができます。この先では、グラフィックスとモザイクとを統合する方法について説明します。


画像オーバーレイ・モザイク

テキスト・オーバーレイは作成できたので、今度はグラフィカルなオーバーレイを作りましょう。この記事では、Linuxのマスコットであるペンギン、タックスの画像を使います。タックスは法律的な面で扱いが手軽な上に、体の大部分も目も単純な白なので、非常に使いやすいのです。モザイク作成に使える色は白のみ、と言うわけではありませんが、統合ステップは簡単になります。

テキスト・オーバーレイの例を思い出してください(皆さんの職場や組織のための自動ポスターとして使えるかも知れません)。その場合には、モザイク片の格子で構成される画像を作り、それと同じサイズを持つ、テキストの透明背景の上に白を作り、そしてそれらをcomposite -compose -inコマンドを使ってオーバーレイしました(やれやれ!)。同じプロセスを、画像の例にも当てはめることができます。最後に1つのステップを追加すればよいのです。今度は、(1つではなく)2つのマスクを作る必要があります。

  1. タックスの画像を入手します。なかなか素敵な、大きな画像(2,400 x 2,796)があります(ダウンロードのセクションを見てください)。
  2. このファイルをThe Gimpから開き、余分な白の背景からタックスを分離します。fuzzy selectツールを使って、タックスの外側の白い部分の上でクリックします。選択を反転し、選択されたものを新しいファイルとしてカット・アンド・ペーストします。このファイルをtransparent.tux.pngとして保存します。これが、最終画像に対するデフォルトのキャンバス・サイズとなります。
  3. transparent.tux.pngから始め、タックスの外側を作成します。そのためにはfuzzy selectツールを選択し、タックスの腹の白い部分の上でクリックしてから、Ctrl+Xで削除します。同じことを、目の中の白い部分に対して行い、ファイルをepi.overlay.tux.pngとして保存します。
図 3.  タックスの外側
タックスの外側
  1. 再度transparent.tux.pngから始め、select by colorツールを使って、タックスの腹の上でクリックします。これによって、腹と目の中の白い部分がすべて選択されます。Ctrl+Iを使って選択を反転し、Ctrl+Xを使って、腹と目の白い部分以外をすべて削除します。これをint.overlay.tux.pngとして保存します。
図 4.  タックスの内側
タックスの内側

これで、タックスの「白い部分のみ(腹と目)」ができました。これが画像フレームの中心に置かれています。これは、先ほどテキスト・オーバーレイの例で作成した、透明背景上の白いテキストと等価です。今度は、タックスのフレームと同じサイズのタイル画像を作る必要があります。

  1. タックスの背景サイズを、identify transparent.tux.pngというコマンドで決定します。この場合、フレームは2,312 x 2,741であることが分かります。
  2. 背景を、perl build_background.pl 2312 2741 tuxで構成します。
  3. 次に、下記のようにしてコンポーネント合成を行います。
composite -compose in \
  backgrounds/back_tux.png \
  int.overlay.tux.png step1.png

これで、腹と目が、モザイク状のタイルで塗りつぶされます。次に2番目のマスクを適用します。

composite -compose over \
  step1.png \
  epi.overlay.tux.png \
  composite/complete_tux.png

-compose overオプションはImageMagickに対して、2番目の画像の上に最初の画像を重ね合わせるように伝えています。これで最終的な作品ができあがります。結果を見るには、feh composite/complete_tux.pngをタイプします。もっと小さいモザイクを作成するには、convertを使います。つまり次のようにします。

convert -resize 800x600 \
  composite/complete_tux.png \
  composite/800x600_complete_tux.png
図 5.  タックスの頭の部分を拡大したもの
タックスの頭の部分を拡大したもの

謝辞

Linuxのタックスの画像として、http://www.isc.tamu.edu/~lewing/linux/ を利用させていただきました。


まとめ

ここで示した仕組みとサンプル・モザイクを利用すると、非常に様々なグラフィックスを構成することができます。ImageMagickとPerlの機能を組み合わせることによって、フェード(fade)の割合を変えてみたり、色の選択を変更してみたり、あるいはその他にも素晴らしいことができますので、皆さんもぜひ試してみるようにお勧めします。この仕組みと、オープンソースのMPEGソフトウェアとを組み合わせることによって、ビデオから幾つかのフレームを抽出してから再構成し、それぞれのフレームにマスクを適用することができます。convert -cropオプションを使うと、ズームイン効果を作り出すことができ、そこから小さなムービーを作ることができます。こうした形式の単純なモザイク・ムービーは手軽に作ることができ、それを使えば効果的なプレゼンテーションを行うことができます。


ダウンロード

内容ファイル名サイズ
Sample codeos-mosaic_posters.zip790KB

参考文献

学ぶために

  • ImageMagickについて学んでください。
  • Boutell.comを見て、GDとは何か、またそのAPIについて学んでください。またサンプル・コードを入手することもできます。
  • 包括的なPerlアーカイブ・ネットワークであるCPANには、GD.pmを含め、他にも様々なPerlモジュールがあります。
  • developerWorks technical events and webcastsを利用して、最新技術を学んでください。
  • developerWorksのOpen sourceゾーンをご覧ください。オープンソース技術を使った開発や、IBM製品でオープンソース技術を使用するためのハウ・ツー情報やツール、プロジェクトの更新情報など、豊富な情報が用意されています。

製品や技術を入手するために

  • Tom Gilbertによる画像ビューアー、fehをダウンロードしてください。
  • 最高の画像操作ソフトウェアが必要であれば、The Gimpを入手してください。
  • WebSphere Application Server V6.0の無料試用版をダウンロードしてください。
  • 皆さんの次期開発プロジェクトを、IBM trial softwareを使って構築してください。developerWorksから直接ダウンロードすることができます。
  • 皆さんの次期オープンソース開発プロジェクトを、IBM trial softwareを使って革新してください。developerWorksからダウンロードで、あるいはDVDで入手することができます。

議論するために

  • KernelNewbies.orgにはFAQやIRCチャネル、メーリングリストなどが用意されており、最近カーネルをいじり始めた人達のためのリソースとして好適です。
  • developerWorks blogsに参加して、developerWorksコミュニティーに加わってください。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source, Java technology
ArticleID=237328
ArticleTitle=PerlとImageMagickを使ってモザイク画像を作る
publish-date=01242006