PR

やっぱりAIってすさまじいなと改めて思ったのでその共有

インフラ技術

なにがすごいのか

いろいろとブログを運用しているのですが、その運用方法としてある程度自動化したいなと思うことがよくあります。

例えば、アフィリエイトサイトの商品紹介をするために記事を複数テキストで作成しておき、自動でアップロードするなどは余裕でしてくれます。

仕組みとしては、Excelでテンプレートを作成しておき、アフィリエイトのURLなどを貼り付け、VBAでテキストを出力。

そのテキストを自動でブログにアップロードするという仕組みを考えたときに、どういった方法でできるか聞いたところ、即座にPythonのコードを示してくれました。

その記事は今後書くとして(タイトルだけ書いて、下書き保存されて進んでません)、今回はその運用の中で面倒だと思っていたことを自動化できた話を書こうと思います。

どんなことをしたのか

以前にも少し書きましたが、AIで画像を出力していますが、その画像を紹介するブログも運営しています。

そのブログの画像を無断で転載されたくないため、ウォーターマークとしてブログ名とURLを描いたロゴのようなものを手作業で貼り付けていました。

けど、毎回毎回面倒すぎて、何とかならないかなと思いました。

そこで、チャットGPTの出番です。

こんな感じで、要件を整理して、コードを書いてもらいました。

・GUIで操作できること
 GUIは実行フォルダを指定する形式
 フォルダ指定時は、ファイルエクスプローラーを呼び出す形式で、視覚的にフォルダを選択できること
 convert というボタンを配置し押下することで以下の処理実行
 mark というボタンを配置し、どのウォーターマークを配置するかをリスト形式で選択
 ウォーターマークは3つ程度コードの中に埋め込んでおき、指定パスを見に行く仕組み
 exit というボタンを配置し、押下することで、GUIを終了する
・インプットファイルはpngファイル
・インプットファイルは「XXXXXX-123456789123456789-0.png」のようなファイル名
・インプットファイルのファイル名から、「AA-XXXXXX」、または「XXXXXX-」を削除し、「01--123456789123456789-0.png」となるようにファイル名を修正
 先頭の01部分は連番にする
・上記処理後、「convert」というフォルダを作成し、そこにファイルをコピー配置
・コピーされたファイルの変換処理
 変換内容としては、ウォーターマークを貼り付け後、画像の縮小
 貼り付け位置は、画像の左下に固定
 ウォーターマーク貼り付け後、画像ファイルはサイズを60%に縮小
 ウォーターマークを画像に張り付けてから、画像の縮小を行うこと
 ファイル名を「01-123456789123456789-0.png_con.png」にする
・元のフォルダのファイルすべてを対象に実行する

と要件を伝え、出てきたコードが以下

import os
import shutil
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image

# =========================
# 設定
# =========================
WATERMARKS = {
    "Mark A": r"WindowsPath1\画像1.png",
    "Mark B": r"WindowsPath2\画像2.png",
    "Mark C": r"WindowsPath3\画像3.png",
}

SCALE_RATIO = 0.6  # 最終的に60%縮小
MARGIN = 10        # 左下余白(px)

# =========================
# GUI
# =========================
class ImageConverterGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("PNG Converter")

        self.target_dir = ""
        self.selected_mark = tk.StringVar(value="Mark A")

        tk.Button(root, text="フォルダ選択", command=self.select_folder).pack(pady=5)
        self.folder_label = tk.Label(root, text="未選択")
        self.folder_label.pack()

        tk.Label(root, text="ウォーターマーク選択").pack(pady=5)
        for key in WATERMARKS:
            tk.Radiobutton(
                root, text=key,
                variable=self.selected_mark,
                value=key
            ).pack(anchor="w")

        tk.Button(root, text="Convert", command=self.convert).pack(pady=10)
        tk.Button(root, text="Exit", command=root.quit).pack(pady=5)

    def select_folder(self):
        self.target_dir = filedialog.askdirectory()
        if self.target_dir:
            self.folder_label.config(text=self.target_dir)

    def convert(self):
        if not self.target_dir:
            messagebox.showerror("エラー", "フォルダを選択してください")
            return

        convert_dir = os.path.join(self.target_dir, "convert")
        os.makedirs(convert_dir, exist_ok=True)

        watermark = Image.open(
            WATERMARKS[self.selected_mark.get()]
        ).convert("RGBA")

        png_files = sorted(
            f for f in os.listdir(self.target_dir)
            if f.lower().endswith(".png")
        )

        for idx, file in enumerate(png_files, start=1):
            src_path = os.path.join(self.target_dir, file)

            # ===== ファイル名整形 =====
            name = file
            name = name.replace("AA-XXXXX-", "")
            name = name.replace("XXXXX-", "")

            base = os.path.splitext(name)[0]
            seq = f"{idx:02d}"
            out_name = f"{seq}-{base}_con.png"
            out_path = os.path.join(convert_dir, out_name)

            # ===== 画像処理 =====
            img = Image.open(src_path).convert("RGBA")

            # --- ウォーターマーク貼り付け(元サイズのまま) ---
            pos = (
                MARGIN,
                img.height - watermark.height - MARGIN
            )
            img.paste(watermark, pos, watermark)

            # --- 画像全体を縮小(WMも一緒に) ---
            new_size = (
                int(img.width * SCALE_RATIO),
                int(img.height * SCALE_RATIO)
            )
            img = img.resize(new_size, Image.BILINEAR)

            img.convert("RGB").save(out_path)

        messagebox.showinfo("完了", "変換が完了しました")

# =========================
# 起動
# =========================
if __name__ == "__main__":
    root = tk.Tk()
    app = ImageConverterGUI(root)
    root.mainloop()

こんな感じでした。

画像の変換処理なので、「ImageConverter」として、動作してくれています。

どんな形のがぞうになっているのかは、以下の記事から運用中のサイトのリンクがあるので、そちらから探してみてください。

今後求められるスキル

Pythonを覚えたいと思っていましたが、覚える必要もなくPythonのコードを出力してくれ、普通に使えています。

この、要件をしっかりと言語化し、AIに伝える。

AIがコードを出力する。

動作確認をこちらが行い、要件と合致しているかテストをする。

今後は、コーディングなどはAIでもできてしまうので、
要件をしっかりまとめられる力
・その要件を理解して正しいかをチェック、テストをする力
こういった点は今後も必要と思います。

逆に、コーディングなどはできなくても個人で使う分には問題なく動かせることができそうです。

なので、仕事として使うためには、AIが嘘をついていないかチェックできるくらい、深い知識が求められると思います。

要件を理解できる日本語力、やりたいことを言語化できるくらい日本語力を高める。

コードを見てどこがおかしいかを、あるべき姿を思い描けるようPythonの理解をする。

など、今後はより深い知識が求められていくというのは間違いないと思います。

と、ここまで、インフラっぽくないことを書いてきたのですが、要件の定義などはインフラ関係なく求められます。

なんなら、コミュニケーションの基本ともいえると思います。


最近はインフラ系の記事が少なくなってしまいましたので、近々Azureの記事でも上げていきたいなとは思っています。

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