雑食性雑感雑記

知識の整理場。ため込んだ知識をブログ記事として再構築します。

ImageMagick + Wand で正方形画像の結合

概要

  • 大量の正方形画像を ImageMagick を使って結合し、1枚の巨大な写真にしてみる。
    • ImageMagick は Python ( Wand ) から利用。

前提条件

  • Linux 環境で実施 ( CentOS )
  • ImageMagick + Wand がインストールされていること
  • 入力画像は全て正方形画像
    • 正方形画像の作り方も前記事に。

画像の結合

  • 画像の結合は、以下の感じで行う:
    1. 巨大な一枚の blank 画像を用意 ( サイズはあらかじめ計算しておく )
    2. composite メソッドで、指定した場所に小さい画像を張り付け。
  • composite は「image.composite( parts_image, left = , top = )」として使用。
    • image が張り付け先画像 ( = 巨大な blank 画像 )
    • parts_image が張り付け元画像 ( = 小さな正方形画像 )
    • left と top を利用して、左端と上端を合わせる。
  • 張り付け元画像の複数パスを引数にして、巨大な画像を返すメソッドを作成。
    • 引数に画像自体を渡すのはメモリ増大するのでダメ!!
def mergeImages( src_filenames, part_width, part_height, row_max, col_max ) :
    '''
    入力ファイルパスの画像を張り付ける。足りない場合はループで回す。
    画像は全て同じサイズであることを前提としている。
    @param src_filenames 画像のファイルパス ( 複数 )
    @param part_width    画像一枚の幅
    @param part_height   画像一枚の高さ
    @param row_max       縦の画像枚数最大値
    @param col_max       横の画像枚数最大値
    '''
    merged_image = Image( width = ( part_width * col_max ), height = ( part_height * row_max ) )

    file_count = 0
    file_max   = len( src_filenames )
    for j in range( row_max ) :
        for i in range( col_max ) :
            image = Image( filename = src_filenames[file_count] )
            merged_image.composite( image, left = ( part_width * i ), top = ( part_width * j ) )
            file_count += 1

            if file_count >= file_max :
                file_count = 0

    return merged_image

画像結合スクリプト作成

  • 実行形式「python merge_images.py [src_dir] [size] [dest_file] [row_max] [col_max]」
    • src_dir 内の画像を結合し、dest_file として保存。
    • src_dir 内の画像は全て、size × size の正方形画像。
# -*- coding: utf-8 -*-
from glob import glob
from wand.image import Image
import os, sys

def __saveImage( image, path ) :
    '''
    指定されたパスに画像を保存
    @param image
    @param path
    '''
    image.save( filename = path )

def mergeImages( src_filenames, part_width, part_height, row_max, col_max ) :
    pass # 省略。上に記述。

if __name__ == '__main__' :

    argv = sys.argv
    argc = len( argv )
    
    if argc < 6 :
        print "Usage: $ python {0} <src_dir> <dest_file> <size> <row_max> <col_max>".format( argv[0] )
        quit()
    
    src_dir       = argv[1]
    dest_filename = argv[2]
    size          = argv[3]
    row_max       = argv[4]
    col_max       = argv[5]
    
    # 入力ディレクトリ無ければエラー
    if not os.path.exists( src_dir ) :
        print "Source directory \"{0}\" is not found.".format( src_dir )

    # 縦横枚数正しくなければエラー
    try :
        size    = int( size )
        row_max = int( row_max )
        col_max = int( col_max )
    except Exception as e :
        print "Size parameter \"({0}, {1}, {2})\" is incorrect format./ {3}".format( size, row_max, col_max, e )
        quit()
    
    # 実行
    image = mergeImages( glob( "{0}/*".format( src_dir ) ), size, size, row_max, col_max )
    __saveImage( image, dest_filename )

実行結果

  • 自分が取った写真を並べてみる。
    • 風景多めだから面白くない。。色々混ぜこぜにするとアートっぽくなるかも。
    • 手元に 45 枚しかなかったので、上記コードを若干編集して、random に読み込んでいます。
    • 256 × 256 画像で作成し、手元で Web 表示用に小さくしてあります。 本当は 2560 × 2560 画像。

f:id:kazuki_nagasawa:20131212182804j:plain