OJT 2025:自然言語での画像レタッチング

こんにちは。 2025年度入社のリサーチャーの安達です。 今回は、弊社で実施している新人グループ研修について報告します。

目次

はじめに

今年度の参加者は安達、周、ユガンダーの3名で、2か月間にわたりチーム開発を実施しました。 テーマは自然言語での画像レタッチングです。

写真加工アプリやSNSの普及を背景に、自撮り文化が世界中で広がっています。 こうした流れから、写真レタッチ市場も拡大しています。 一方で「加工が面倒」「操作が複雑でよく分からない」という声もあり、誰もが手軽に利用できる状況ではないという課題も残されています。

こうした課題を受け、私たちは自然言語で直感的に操作できる自撮り画像向けレタッチツールを開発しました。 このツールの最大の特徴は、「誰だか分からないようにして」や「肌のトラブルを何とかして」といった曖昧な命令でも、高精度なレタッチが可能なことです。

今回は、以下の3つの加工機能に絞り込み、WebUIとして実装しました。

  • プライバシー保護機能:顔や物体へのぼかし処理
  • 顔補正       :ニキビ除去や自然な小顔補正
  • 背景置き換え    :不要物の削除や背景の変更

WebUIの実行例

システム構成

本システムの開発においては、ユーザが入力する多様な自然言語命令を、いかに正確に中間表現であるプログラムへ変換するかという課題が主眼となっていました。 特に、変換過程で用いる例示プロンプトの調整が、最終的に出力されるレタッチ画像の精度に非常に大きく影響することが判明しました。

この課題に対応するため、私たちはメインロジックであるレタッチ実行部の前段にRAG(Retrieval-Augmented Generation;検索拡張生成)を導入し、システムを二段階のコンポーネントで構成しました。

まずRAGでは、ユーザからの自然言語命令を解析し、その命令に合致する最適な例示プロンプトを生成します。 この例示プロンプトは、レタッチ命令をプログラムに変換するための参照情報として機能します。

次にレタッチ実行部では、RAGから渡された例示プロンプトを基に、LLM(Large Language Models;大規模言語モデル)を用いてレタッチ実行プログラムを生成します。 このプログラムを実行することで、入力画像にレタッチ処理が施され、ユーザの意図に沿ったレタッチ画像を出力します。

このように、RAGを導入し処理を二段階に分けることで、例示プロンプトを動的に調整し、ユーザの多様な命令への柔軟な対応を実現しました。

全体のシステム構成図

VisProg

In-context Learningは、LLMのもつ重要な能力の一つです。 これは、モデルの重みを更新することなく、与えられたコンテキストに基づいて新たなタスクを理解し、適切な応答を生成する能力のことです。

今回は、この能力を最大限に活用するために、VisProg[1]と呼ばれるフレームワークを導入しました。 VisProgは、自然言語の命令をLLMで解析し、あらかじめ実装されたインタプリタを組み合わせて、動的にレタッチプログラムを生成します。

例えば、画像全体にぼかしをかけるという命令を考えてみましょう。 この場合、VisProgは以下のようにレタッチプログラムを生成します。

IMAGE=READ_IMAGE(path='./test.jpg') # 画像を読み込む
RESULT1=BLUR(image=IMAGE, ksize=51) # 画像全体にぼかしをかける
FINAL_RESULT=RESULT(var=RESULT1)    # レタッチ画像を出力

この例では、画像を読み込むREAD_IMAGE、画像にぼかしをかけるBLUR、画像を出力するRESULTという3つの独自に実装したインタプリタを組み合わせることで、一連の処理が自動で構築されます。

今回私たちは、特定の物体へのぼかし、小顔化、ニキビ除去、背景置き換え機能に対応するインタプリタを実装しました。

レタッチ実行部

では、画像レタッチを実行するレタッチ実行部の概要を説明します。

まず、ユーザの命令は、VisProgのプログラム生成部に渡されます。 ここで、Gemma 3 というLLMが、RAGから渡された命令とプログラムのペアを例示プロンプトとして参照しながら、入力命令に応じたレタッチ用プログラムを自動生成します。

次に、生成されたプログラムは、VisProgのプログラム実行エンジンに渡されます。 ここでは、プログラム内の各ステップを解析し、機能ごとに独自に実装された専用のインタプリタを呼び出します。 実際に実装したインタプリタの例としては、

  • BLUR:ぼかし処理
  • REMOVE_ACNE:ニキビ除去

といった具合です。

最後に、処理が完了した画像がユーザに返され、レタッチ処理が完了します。

レタッチ実行部のシステム構成図

Gemma 3

LLMは、膨大なテキストデータと深層学習技術、特にTransformerと呼ばれるアーキテクチャを用いて構築された、高度な自然言語処理モデルです。 これを活用することで、文章の作成・要約・翻訳、質問に対する応答など幅広いタスクをこなすことができます。

今回のシステムでは、2025年3月にGoogleが発表した最新のLLMであるGemma 3[2]を採用しました。 このモデルは、主に以下の特長を備えています。

  • 多様なモデルサイズ(1B, 4B, 12B, 27Bなど)を選択可能
  • 最大128Kトークン(英単語約25万語相当)もの長文を入力可能
  • 140以上の多様な言語に対応

ぼかし機能インタプリタ

本記事では、実装した機能の中からぼかし機能で使用した技術について説明します。 ぼかし機能は、大きく分けて2つのインタプリタから構成されます。

1つ目は、MASK_FROM_PROMPTインタプリタです。 これは、入力命令に基づいて、ぼかしを適用すべき対象領域を自動的に特定し、その領域のマスク画像を抽出します。 内部的には、以下の技術を組み合わせて実装しています。

  • LangSAM[3]:プロンプトから画像中の特定のオブジェクトに対するマスクを生成するモデル。GroundingDINOとSegment-Anything Modelを組み合わせて構築されている。

  • Mask Selection:位置の指定(例. 右から2番目の人、一番上のコップ)がされた場合、その部分だけのマスクを抽出する独自の関数。

2つ目は、BLURインタプリタです。 これは、OpenCVが提供するGaussianBlur関数を用いて、マスク領域に対してガウシアンブラーを適用します。

これら2つのインタプリタを組み合わせることで、ユーザが自然言語で指定した対象物に対して、ピンポイントでぼかしを適用する機能を実装しました。

ぼかし機能を実現するパイプライン

直面した課題

ここまでの実装により、入力命令と画像からレタッチ画像を出力する一連の処理フローは完成しました。 しかし、様々な命令や例示プロンプトで実験した結果、大きく4つの課題が明らかになりました。 その中でも特に深刻だったのが、プロンプトに大量の異なる例を与えると、Gemma 3が混乱して意図しない応答を返すという現象です。 具体的には、「ニキビを消したい」や「背景を青い空に置き換えて」など、異なる例示プロンプトを大量に与えると、Gemma 3はどの命令を選択すべきかを判断できず、意図と異なるレタッチ結果を返すことが頻発しました。 これは一般的に、Context Confusion(コンテキストの混乱)と呼ばれる課題です。 本記事では、この課題に焦点を当てて、その解決策を説明します。

RAG

Context Confusionを解決するには、Gemma 3に対して一度に大量の例を与えるのではなく、必要最低限の例だけを与える仕組みが必要です。 そこで、今回はRAGを導入することで、入力命令に最も関連性の高い少数の例のみをGemma 3に渡すアプローチを試みました。

RAGとは、LLMの回答能力を外部の知識ベースやデータベースと組み合わせることで拡張する技術です。 今回の場合は、事前に用意した大量の例示プロンプトが、データベースの位置づけとなります。 具体的な動作の流れは以下の通りです。

  1. ユーザからの入力命令を受け取る
  2. 命令文を埋め込みベクトルに変換し、事前に用意した大量の例示プロンプトから類似度検索を実行
  3. 最も関連性の高い少数の例(今回は3つ)だけを取得し、Gemma 3に渡す
  4. モデルは、選ばれた例を参考に最終的なレタッチ画像を生成

類似度検索の手法

まず、ユーザからの命令を埋め込みモデル(all-MiniLM-L6-v2[4])でベクトル形式に変換します。 このモデルは、テキストの意味的特徴を抽出し、高次元の特徴量空間へ埋め込むよう事前学習されています。 そのため、意味的に似ている文は、このベクトル空間上で互いに似た向きのベクトルになります。

次に、このベクトルを用いて、事前に用意した大量の例示プロンプトの中から、最も関連性の高い例をコサイン類似度(cosine similarity)を用いて検索します。 コサイン類似度とは、2つのベクトルの向きの一致度を -1.0〜1.0 の範囲で数値化する指標です。 大きさではなく方向の一致度を測るため、文の長さやスケールに依存せず、純粋な意味的な近さを測定できます。

この計算結果に基づき、最も類似度が高い上位3件の例のみを抽出し、Gemma 3に渡すようにしました。 このように例示プロンプトを厳選したことで、Gemma 3が不要な例に惑わされることなく、ユーザの意図をより正確に解釈できるようになりました。 結果として、誤ったレタッチ機能を選択することが少なくなり、よりユーザの意図に沿った編集システムを実現できました。

WebUI

Flaskは、Pythonで利用できる軽量かつシンプルなWebフレームワークです。 今回のシステムは、フロントエンドWebフレームワーク層(Flask)バックエンドの三層構造で設計されています。

WebUIの構造

フロントエンド

画像アップロードボタンや領域選択、対話ボックスなど、ユーザが直接操作する部分を担当します。 今回はHTML・CSS・JavaScriptを組み合わせてフロントエンドを構築しました。

Webフレームワーク層(Flask)

フロントエンドとバックエンドの橋渡しを行う層です。 Flaskのルーティング機能を用いてAPIエンドポイントを定義し、フロントエンドから送られたリクエストを適切な処理関数に振り分けます。 また、バックエンドで生成された結果は、JSONレスポンスや画像ファイルとして、フロントエンドに返されます。 これにより、UIの操作内容をシームレスにバックエンドへ橋渡しできます。

バックエンド

アプリケーションの中核となるロジックを担当します。 具体的には、これまで説明してきた一連の画像処理を実行し、チャット応答やレタッチ画像をフロントエンドに返します。

結果

明確な命令の場合

まずは、命令が明確な場合です。 例えば、"Replace the background of the man."と入力した場合、システムは命令の内容を正確に理解し、背景置き換え機能を適切に選択しました。 その結果、背景のみが自然に置き換えられ、所望のレタッチ画像が出力されました。

Replace the background of the man.と入力した結果

曖昧な命令の場合

次に、命令が曖昧な場合です。 例えば、"Make the people unrecognizable."という命令には、"顔をぼかす"というような具体的な画像処理の内容は含まれていません。 しかし、システムはユーザの意図を汲み取り、顔へのぼかし機能が最も適切であると判断しました。 その結果、人物の顔が自然にぼかされた画像が出力されました。

Make the people unrecognizable.と入力した結果

非常に曖昧な命令の場合

最後に、命令が非常に曖昧な場合です。 例えば、"Can you make it more anonymous?"という命令は、これまでの命令と比べても非常に抽象的な命令です。 特に「anonymous」という表現は解釈の幅が広く、具体的にどのような処理を期待しているのかが明確ではありません。 ここでシステムは、1つの機能ではなく、ぼかし機能と背景置き換えの複数の機能を組み合わせて、匿名化を実現しました。 その結果、人物の顔をぼかして、白黒背景に置き換えた画像が出力されました。

Can you make it more anonymous?と入力した結果

まとめ

今回の研修ではVisProgをベースに、自然言語による自撮り画像向けのレタッチツールを開発しました。 特に、曖昧な命令にも対応できるようにしたことで、より実用性の高いシステムを実現しました。 また、RAGの実装により、将来的に機能が増えても安定して動作できるよう設計を工夫しました。

今後の課題としては、主に次の3つが挙げられます。

  1. 実装機能のさらなる拡充
  2. より軽量なモデルを活用し高速化の実現
  3. 自社の画像処理製品との統合

最後までお読みいただき、ありがとうございました。

参考文献

[1] Tanmay Gupta, Aniruddha Kembhavi(2022), Visual Programming: Compositional visual reasoning without training, CVPR 2023, https://arxiv.org/abs/2211.11559

[2] Google, Gemma 3 モデルの概要, https://ai.google.dev/gemma/docs/core?hl=ja

[3] luca-medeiros, Language Segment-Anything, https://github.com/luca-medeiros/lang-segment-anything

[4] Hugging Face, sentence-transformers/all-MiniLM-L6-v2, https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2