python: 画像を分割して保存する

プログラミング
スポンサーリンク




こんにちは、おみです。

機械学習で麻雀牌を学習させる際に、テストデータを用意する必要があったのですが、牌を一つずつ撮影するのは面倒です。

そこで、一気に撮影して後から分割数を指定して保存するアプリケーションを作成しました。

エラー処理とかはそんなに考えていないので、実際に使う際はご注意ください。

スポンサーリンク

機能の説明

テキストボックスに必要な情報を入力し、「実行ボタン」を押すと

分割後の画像が出力されます。

 

設定項目の詳細

・入力画像パス

分割を行いたい画像の絶対パスを記述します。

・出力フォルダパス

分割後の画像を出力したいフォルダのパスを記述します。

・出力画像名

分割後の画像の名前を記述します。

・縦分割数

縦の分割数を記述します。

・横分割数

横の分割数を記述します。

ソースコード

・ファイル構造

・Main.py

import tkinter as tk

from src.Model import Model
from src.View import View
from src.Controller import Controller


class Application(tk.Frame):
    def __init__(self, root):
        # スーパークラスのコンストラクタを呼び出し
        super().__init__(root)

        # モデルをインスタンス化
        self.model = Model(root)

        # ビューをインスタンス化
        self.view = View(root, self.model)

        # コントローラーをインスタンス化
        self.controller = Controller(root, self.model, self.view)

        # Viewにメソッドをセット
        self.view.btn_execute["command"] = lambda: self.controller.call_execute()

        # 画面の設定
        root.geometry(str(self.model.width) + "x" + str(self.model.height))
        root.title(self.model.title)


def main():
    root = tk.Tk()
    window = Application(root)
    window.mainloop()


if __name__ == "__main__":
    main()

・Model.py

import configparser as c
import tkinter as tk
import os
from PIL import Image


class Model(object):
    def __init__(self, root):
        # ---------------------------------
        # 初期設定
        # ---------------------------------
        self.root = root

        # configファイルを読み込み
        self.config = c.ConfigParser()
        self.config.read("config.ini")

        # 画面タイトルを取得
        self.title = self.config["DISPLAY_INFO"]["title"]

        # 画面サイズを取得
        self.width = int(self.config["DISPLAY_INFO"]["width"])
        self.height = int(self.config["DISPLAY_INFO"]["height"])

        # 画面要素に紐づける変数の生成
        # 入力画像パス
        self.ent_input_path_text = tk.StringVar()
        # 出力フォルダパス
        self.ent_output_path_text = tk.StringVar()
        # 分割後画像名
        self.ent_output_name_text = tk.StringVar()
        # 縦分割数
        self.ent_h_div_num_text = tk.StringVar()
        # 横分割数
        self.ent_w_div_num_text = tk.StringVar()
        # 処理メッセージラベル
        self.lbl_message_text = tk.StringVar()
        self.lbl_message_text.set("入力してください。")

    # 画像を分割して保存する
    def execute(self):
        if os.path.exists(self.ent_input_path_text.get()) and os.path.exists(self.ent_output_path_text.get()):
            # 画像を開く
            img = Image.open(self.ent_input_path_text.get())
            # 分割後の画面サイズを取得
            w = img.size[0] / int(self.ent_w_div_num_text.get())
            h = img.size[1] / int(self.ent_h_div_num_text.get())

            # 画像を分割して保存する
            for w_count in range(int(self.ent_w_div_num_text.get())):
                for h_count in range(int(self.ent_h_div_num_text.get())):
                    # 始点座標を取得
                    x = w_count * w
                    y = h_count * h

                    # 分割後画像を生成
                    i = img.crop((x, y, x + w, y + h))

                    # 画像を保存
                    i.save(self.ent_output_path_text.get() + "/" + self.ent_output_name_text.get() + str(w_count + 1) + str(
                        h_count + 1) + ".png", "PNG")

            self.lbl_message_text.set("正常終了")

        else:
            self.lbl_message_text.set("存在しないパスが入力されています。")

・View.py

import tkinter as tk


class View(object):
    def __init__(self, root, model):
        self.root = root
        self.model = model

        # ---------------------------------
        # 画面の部品を生成
        # ---------------------------------
        # 入力画像パスラベル
        self.lbl_input_path = tk.Label(
            root,
            text="入力画像パス"
        )

        # 入力画像パス入力欄
        self.ent_input_path = tk.Entry(
            root,
            textvariable=model.ent_input_path_text,
            width=30
        )

        # 実行ボタン
        self.btn_execute = tk.Button(
            root,
            text="実行",
            command=lambda: model.btn_clicked()
        )

        # 出力フォルダパスラベル
        self.lbl_output_path = tk.Label(
            root,
            text="出力フォルダパス"
        )

        # 出力フォルダパス入力欄
        self.ent_output_path = tk.Entry(
            root,
            textvariable=model.ent_output_path_text,
            width=30
        )

        # 出力画像名ラベル
        self.lbl_output_name = tk.Label(
            root,
            text="出力画像名"
        )

        # 出力画像名入力欄
        self.ent_output_name = tk.Entry(
            root,
            textvariable=model.ent_output_name_text,
            width=30
        )

        # 縦分割数ラベル
        self.lbl_h_div_num = tk.Label(
            root,
            text="縦分割数"
        )

        # 縦分割数入力欄
        self.ent_h_div_num = tk.Entry(
            root,
            textvariable=model.ent_h_div_num_text,
            width=30
        )

        # 横分割数ラベル
        self.lbl_w_div_num = tk.Label(
            root,
            text="横分割数"
        )

        # 横分割数入力欄
        self.ent_w_div_num = tk.Entry(
            root,
            textvariable=model.ent_w_div_num_text,
            width=30
        )

        # メッセージラベル
        self.lbl_message = tk.Label(
            root,
            textvariable=model.lbl_message_text
        )

        # ---------------------------------
        # 画面の部品を配置
        # ---------------------------------
        self.lbl_input_path.grid(row=0, column=0)
        self.ent_input_path.grid(row=0, column=1)
        self.btn_execute.grid(row=0, column=2)

        self.lbl_output_path.grid(row=1, column=0)
        self.ent_output_path.grid(row=1, column=1)

        self.lbl_output_name.grid(row=2, column=0)
        self.ent_output_name.grid(row=2, column=1)

        self.lbl_h_div_num.grid(row=3, column=0)
        self.ent_h_div_num.grid(row=3, column=1)

        self.lbl_w_div_num.grid(row=4, column=0)
        self.ent_w_div_num.grid(row=4, column=1)

        self.lbl_message.grid(row=5, column=0, columnspan=3)

・Controller.py

import tkinter as tk


class Controller(object):
def __init__(self, root, model, view):
self.root = root
self.model = model
self.view = view

def call_execute(self):
self.model.execute()

・config.ini

[DISPLAY_INFO]
title = "画像分割"
width = 450
height = 180

 

コメント

タイトルとURLをコピーしました