背景
Figmaから生まれた「画像のカオス」をどう整理するか
Figma の AutoHTML プラグインなどでホームページを制作すると、デザイン再現性は高い一方で、画像ファイルが過剰に増える問題に直面します。
見た目が同じでも、Figma 上のオブジェクト名が違うだけで image1.png, image2.png, icon_a.svg, icon_b.svg のように別ファイルとして大量に書き出されます。これを手で統合するのは現実的ではありません。
そこで、AI駆動で重複画像を統合し、HTMLの img[src] 参照まで一括更新するスクリプトを組み立てました。
MD5 ハッシュではダメだった
最初に思いつくのは MD5 による完全一致判定です。2つのファイルの MD5 が一致すれば、内容は同一と断定できます。
しかしその方法では、ほとんど消せませんでした。理由は、Figmaの書き出しで生じる微差です。
-
SVG: 自動生成される
id(例:mask0_123とmask0_456)の違いだけでテキストは別物になる - PNG/JPG: 解像度差や圧縮時の微小差(1ビット差でも)でハッシュが変わる
人間には同じに見えても、機械的な「完全一致」だけでは不十分でした。
AI が提案した重複判定ロジック
SVG の「セマンティック指紋」
単純な文字列一致をやめ、SVG の構造情報で比較します。
-
pathのdに含まれる数値を量子化して比較 -
data:image/...;base64,...の埋め込み画像はデコード後ハッシュで比較 - ルートの寸法 (
width/heightまたはviewBox) も指紋に含める
def path_d_coordinate_bins(d: str, step: float = 0.2):
"""
path の d に含まれる数値を量子化した整数列に正規化。
0.2 単位で丸めることで、浮動小数の微差を吸収する。
"""
nums = []
for nm in _SVG_PATH_NUM_RE.finditer(d):
v = float(nm.group(0))
nums.append(int(math.floor(v / step + 0.5)))
return tuple(nums)
ラスターの「正規化 + aHash + 色」
解像度が違っても比較できるよう、いったん固定サイズへ正規化して判定します。
- 固定サイズ(例:
512x32)へ stretch リサイズ -
aHash(平均ハッシュ)で形状類似 - 16x16 平均色距離を併用して誤統合を抑制
def compute_canonical_ahash_and_color(file_path):
"""
一度 (512, 32) にストレッチしてから aHash と平均色を計算。
解像度差をまたいだ「同じ絵」の検出に使う。
"""
with Image.open(file_path) as im:
im = im.convert("RGB").resize(CANONICAL_DEDUPE_SIZE, Image.Resampling.LANCZOS)
# ... ここで aHash と平均色を計算 ...
私なりの解釈
このロジックを読み解いて、私はこう解釈しました。
「人間が『これ、同じだよね』と感じる曖昧な感覚を、機械が理解できる数式と手順に翻訳する作業である。」
たとえば、今回の0.2単位で丸める処理。これは、人間が細かい端数を「誤差」として無視し、本質的な形だけを見る感覚を、あえて解像度を落としたモザイクとして表現しているようなものです。
「画像をリサイズしてからハッシュを取る」のも同じです。高精細な画像そのままでは、1ピクセルの違いも許さない判定になってしまいます。そこで、あえて画像を小さく、粗いモザイク状に圧縮することで、人間が「遠目に見れば同じ絵だ」と判断するプロセスを数学的に再現しているのです。
AI駆動開発の鉄則
「AI が生成したコードを、100%理解できないなら、それは世に出すな。」
この言葉は本質的です。
AIは時として、動くけれどもメンテナンス不能なコードや、エッジケースで牙を向くロジックを出してきます。内容を理解せずに、動いたからOKで進めるのは、技術的負債を抱える行為になります。
AI時代こそ「アルゴリズムの引き出し」が武器になる
AI駆動開発は、決してAIへの丸投げではありません。むしろ、人間側がどの比較アルゴリズムを使い、どう調整するかを具体的に指定できることで、アウトプットの品質が劇的に上がります。
今回、重複画像を整理する中で、アルゴリズムの引き出しの多さが、そのままAIへの指示力に直結することを痛感しました。
「点」の知識から「面」の知恵へ
私の知識がMD5という一つの引き出ししかなければ、Figmaから書き出された大量の重複画像は、一枚も消せないままで行き詰まっていました。
今回の解決策である画像をあえてモザイクのようにざっくり捉えて比較する(リサイズ+aHash判定)というロジックは、AIとの試行錯誤の中でAI側から提案されたものでした。
そのコードを見たとき、私は思いました。
「もし最初からこのアルゴリズムを私が知っていたら、迷わず最短距離で指示を出せたはずだ」と。
AIが答えを出してくれるのを待つのではなく、こちらに引き出しがあれば、もっと早く、もっと正確にAIを使いこなせたはず。この知っていることの差が、開発スピードの決定的な差になると身をもって知りました。
AIが出してくれたアルゴリズムを読み解き、理解することで、自分の中に新しい知識ができました。仕組みがわかれば、AIが失敗したときも「あ、ここは判定の網目が細かすぎたんだな」と、すぐに原因を突き止められます。
「なんとなく」を卒業し、理屈で品質を守る
AIが出してくれたアルゴリズムを読み解き、自分の知識にすることで、大きな変化がありました。仕組みがわかれば、AIが失敗したときも「ここは判定の網目が細かすぎたんだな」と、すぐに原因を突き止められます。
「なんとなく動いた」ではなく、理屈でミスを防ぎ、品質を最後まで担保できているという実感。これは、エンジニアとしての自分への大きな安心感に繋がっています。
お客様にプロの言葉で説明できる信頼
そして何より、この知識はお客様からの信頼に直結します。
今回のようなケースでも、「画像を消しました」と報告するだけではありません。「あえてモザイク状に判定させることで、見た目が同じ画像を確実に特定し、最適化しました」と、自分の言葉でロジカルに説明できるようになります。
「どこまでができて、どこからが難しいのか」をハッキリ提示できるエンジニアは、お客様にとって心強い存在になるかなと思います。最近、直接お客様とやり取りする機会が増えた私にとって、この説明できる力の重要性を実感してます。
終わりに
AIは生成する力を持っていますが、「どういうルールで作るか」を決めるのは人間の役割だと考えています。
今回はAIに教えられる形で新しいロジックに出会いましたが、これからは自分の中にアルゴリズムの引き出しをどんどん増やしていきたい。そうすれば、AIに対して、最高の司令塔として振る舞えるようになるはずです。
続編
次は、このAI駆動で用いたプロンプトのマネジメントについて書こうと思います。