Pythonを使用して画像のコラージュを作成する方法

コラージュは、思い出や画像セットを美しく展示するのに最適な方法です。オンラインのコラージュ作成ツールにはセキュリティ上の懸念があり、オフラインアプリは有料で必要な機能が不足している場合があります。

独自のイメージコラージュ作成ツールを構築することで、これらの懸念を排除し、完全な制御を維持できます。では、どのように作成すればよいでしょうか。

TkinterとPILモジュール

画像コラージュアプリケーションを構築するには、TkinterとPILモジュールが必要です。Tkinterを使用すると、デスクトップアプリケーションを作成できます。さまざまなウィジェットを提供しており、GUIを簡単に開発できます。

Pillowライブラリ(Python Imaging Library(PIL)のフォーク)は、画像の編集、作成、ファイル形式の変換、画像の保存に役立つ画像処理機能を提供します。

TkinterとPillowをインストールするには、ターミナルを開いて次を実行します。

pip install tk pillow

GUIのセットアップと画像の操作

このプロジェクトのソースコードは、GitHubリポジトリにあります。

最初に、必要なモジュールをインポートします。ImageCollageAppというクラスを作成し、ウィンドウのタイトルとサイズを設定します。tk.Canvas()を使用してキャンバスを定義し、親要素、幅、高さ、背景色を設定します。

import tkinter as tkfrom tkinter import filedialog, simpledialog, messageboxfrom PIL import Image, ImageTkclass ImageCollageApp:def __init__(self, root):self.root = rootself.root.title("Image Collage Maker")self.images = []self.image_refs = []self.collage_size = (600, 500)self.collage_canvas = tk.Canvas(self.root,width=self.collage_size[0],height=self.collage_size[1],bg="white",)self.collage_canvas.pack()

2つのボタンを作成します。画像の追加コラージュの作成です。親要素、表示するテキスト、実行するコマンド、フォントスタイルを定義します。適切なパディングを追加してボタンを整理します。drag_dataを初期化して、ドラッグ操作に関する情報を格納します。

image_positionsを初期化して、キャンバス上の画像の位置を格納します。3つのイベントハンドラを定義して、画像の選択、ドラッグ、およびリリースに応答します。

self.btn_add_image = tk.Button(self.root,text="Add Image",command=self.add_images,font=("Arial", 12, "bold"),)self.btn_add_image.pack(pady=10)self.btn_create_collage = tk.Button(self.root,text="Create Collage",command=self.create_collage,font=("Arial", 12, "bold"),)self.btn_create_collage.pack(pady=5)self.drag_data = {"x": 0, "y": 0, "item": None}self.image_positions = []self.collage_canvas.bind("", self.on_press)self.collage_canvas.bind("", self.on_drag)self.collage_canvas.bind("", self.on_release)

メソッドon_pressを定義します。ユーザーがマウスをクリックした場所から最も近いキャンバスアイテムを取得し、drag_dataディクショナリのitemキーの下に格納します。マウスクリックのx座標とy座標を格納します。これを使用して、ドラッグ中にユーザーがマウスを移動した距離を計算します。

def on_press(self, event):self.drag_data["item"] = self.collage_canvas.find_closest(event.x, event.y)[0]self.drag_data["x"] = event.xself.drag_data["y"] = event.y

メソッドon_dragを定義します。ユーザーがドラッグ中にマウスを移動した水平方向と垂直方向の距離を計算し、画像の位置をそれに応じて更新します。画像の更新された座標をdrag_dataディクショナリのxキーとyキーの下に格納します。

def on_drag(self, event):delta_x = event.x - self.drag_data["x"]delta_y = event.y - self.drag_data["y"]self.collage_canvas.move(self.drag_data["item"], delta_x, delta_y)self.drag_data["x"] = event.xself.drag_data["y"] = event.y

メソッドon_releaseを定義します。ユーザーがドラッグしていた画像への参照と、その座標をクリアします。update_image_positionsを呼び出して、ユーザーがドラッグしてリリースした後、キャンバス上のすべての画像の位置を更新します。

def on_release(self, event):self.drag_data["item"] = Noneself.drag_data["x"] = 0self.drag_data["y"] = 0self.update_image_positions()

メソッドupdate_image_positionsを定義します。image_positionsリストをクリアし、すべてのキャンバスアイテムを反復処理します。各アイテムについて、座標を検索し、リストに追加します。

def update_image_positions(self):self.image_positions.clear()for item in self.collage_canvas.find_all():x, y = self.collage_canvas.coords(item)self.image_positions.append((x, y))

メソッドadd_imagesを定義します。コラージュの画像の数をユーザーに入力するよう求めるダイアログボックスを作成します。ユーザーが有効な数値を入力した場合、ユーザーが画像ファイルのみを選択できるようにするファイルダイアログボックスを開きます。ユーザーが1つ以上の画像を選択したら、PillowのImage.open()メソッドでそれぞれを開きます。

resize_imageメソッドを呼び出し、Tkinter互換のPhotoImageを作成します。これをimage_refsリストに追加し、update_canvasメソッドを呼び出します。

def add_images(self):num_images = simpledialog.askinteger("Number of Images", "Enter the number of images:")if num_images is not None:file_paths = filedialog.askopenfilenames(filetypes=[("Image files", "*.png;*.jpg;*.jpeg;*.gif")])if file_paths:for i in range(min(num_images, len(file_paths))):file_path = file_paths[i]image = Image.open(file_path)resized_image = self.resize_image(image)self.images.append(resized_image)self.image_refs.append(ImageTk.PhotoImage(resized_image))self.update_canvas()

メソッドresize_imageを定義します。画像の幅と高さを取得し、そのアスペクト比を計算します。1より大きい場合は、新しい幅をコラージュの幅の半分に設定します。アスペクト比を維持しながら、対応する新しい高さを計算します。

アスペクト比が1より小さい場合は、新しい高さをコラージュの高さの半分に設定します。同様に、対応する幅を計算します。Pillowのresizeメソッドを使用して、計算されたパラメータを使用してサイズ変更された画像を返します。

def resize_image(self, image):img_width, img_height = image.sizeaspect_ratio = img_width / img_heightif aspect_ratio > 1:new_width = self.collage_size[0] // 2new_height = int(new_width / aspect_ratio)else:new_height = self.collage_size[1] // 2new_width = int(new_height * aspect_ratio)return image.resize((new_width, new_height))

メソッドupdate_canvasを定義します。すべてのアイテムをクリアし、ファイルダイアログボックスを使用してユーザーに目的の行数と列数を尋ねます。コラージュの幅と高さを指定されたコラージュサイズの半分になるように設定します。画像位置のリストをクリアします。xyのオフセットをゼロに初期化して、行と列に画像を配置するための位置オフセットを追跡できるようにします。

def update_canvas(self):self.collage_canvas.delete("all")rows = simpledialog.askinteger("Number of Rows", "Enter the number of rows:")cols = simpledialog.askinteger("Number of Columns", "Enter the number of columns:")collage_width = self.collage_size[0] * cols // 2collage_height = self.collage_size[1] * rows // 2self.collage_canvas.config(width=collage_width, height=collage_height)self.image_positions.clear()x_offset, y_offset = 0, 0

image_refsリストを反復処理し、指定されたオフセットを使用してキャンバスに画像を作成します。アンカーを北西に設定して、指定された座標に画像の左上隅を配置します。これらの座標をimage_positionsリストに追加します。

次の画像を配置する準備をするために、x_offsetを更新してコラージュの幅の半分を追加します。現在の行に配置された画像の数が指定された列数の倍数である場合、x_offsetをゼロに設定します。これは、新しい行の開始を示します。次の行のy座標を設定するために、コラージュの高さの半分を追加します。

for i, image_ref in enumerate(self.image_refs):self.collage_canvas.create_image(x_offset, y_offset, anchor=tk.NW, image=image_ref)self.image_positions.append((x_offset, y_offset))x_offset += self.collage_size[0] // 2if (i + 1) % cols == 0:x_offset = 0y_offset += self.collage_size[1] // 2

コラージュの作成と保存

メソッドcreate_collageを定義します。コラージュに画像がない場合は、警告を表示します。コラージュの幅と高さを収集します。白い背景を持つPillowImageを作成します。imagesリストを反復処理し、各画像を指定された位置に背景に貼り付けます。

コラージュを保存し、デフォルトの画像ビューアを使用して表示します。

def create_collage(self):if len(self.images) == 0:messagebox.showwarning("Warning", "Please add images first!")returncollage_width = self.collage_canvas.winfo_width()collage_height = self.collage_canvas.winfo_height()background = Image.new("RGB", (collage_width, collage_height), "white")for idx, image in enumerate(self.images):x_offset, y_offset = self.image_positions[idx]x_offset, y_offset = int(x_offset), int(y_offset)paste_box = (x_offset,y_offset,x_offset + image.width,y_offset + image.height,)background.paste(image, paste_box)background.save("collage_with_white_background.jpg")background.show()

TkinterとImageCollage Appクラスのインスタンスを作成します。mainloop()関数は、PythonにTkinterイベントループを実行し、ウィンドウを閉じるまでイベントをリッスンするように指示します。

if __name__ == "__main__":root = tk.Tk()app = ImageCollageApp(root)root.mainloop()

画像コラージュメーカーのさまざまな機能のテスト

プログラムを実行すると、画像の追加コラージュの作成の2つのボタンがあるウィンドウが表示されます。画像の追加ボタンをクリックすると、ダイアログボックスにコラージュする画像の数が尋ねられます。画像の数を5と入力して選択すると、別のダイアログボックスが表示されます。行数と列数の入力を求めます。

2行3列を入力すると、ウィンドウは画像をグリッド構造で整理します。

プレビューでは、必要に応じて画像をドラッグすることができます。コラージュの作成ボタンをクリックすると、プログラムは画像を保存します。

画像を見ると、プログラムがコラージュを正常に作成したことを確認できます。

画像コラージュメーカーの機能を強化する

表形式の代わりに、ユーザーが選択できるさまざまなデフォルトテンプレートを提供できます。背景色の変更、テキストの追加、画像へのフィルターの適用、インターネットからのステッカーの挿入などの機能を追加します。

これらの機能を追加する際には、元に戻すまたはやり直すオプションを使用して、コラージュを簡単に編集できるようにします。ユーザーが自分の好みに合わせて画像を切り抜き、サイズ変更し、反転できるようにします。また、目的の形式で画像を保存するオプションも追加する必要があります。