GPT Image 2 やその他の AI 画像生成モデルを使用してマーケティング素材を作成している開発者の多くが、一度は頭を抱える問題があります。ChatGPT のウェブ版に既存の QR コードを読み込ませて合成すると、毎回読み取り可能な完成品が得られるのに、API を通じて同じモデル、同じプロンプトで生成すると、生成された QR コードが毎回壊れてしまい、100% 読み取りに失敗するというものです。問題はプロンプトにあるわけでも、モデルにあるわけでもありません。ワークフローそのものが、最初から方向を間違えているのです。
<rect x="105" y="20" width="35" height="35" fill="#0f172a"/>
<rect x="112" y="27" width="21" height="21" fill="#ffffff"/>
<rect x="117" y="32" width="11" height="11" fill="#0f172a"/>
<rect x="20" y="105" width="35" height="35" fill="#0f172a"/>
<rect x="27" y="112" width="21" height="21" fill="#ffffff"/>
<rect x="32" y="117" width="11" height="11" fill="#0f172a"/>
<!-- random data modules -->
<g fill="#0f172a">
<rect x="65" y="20" width="7" height="7"/><rect x="80" y="20" width="7" height="7"/>
<rect x="65" y="35" width="7" height="7"/><rect x="90" y="35" width="7" height="7"/>
<rect x="75" y="50" width="7" height="7"/><rect x="65" y="65" width="7" height="7"/>
<rect x="20" y="65" width="7" height="7"/><rect x="35" y="80" width="7" height="7"/>
<rect x="50" y="65" width="7" height="7"/><rect x="20" y="90" width="7" height="7"/>
<rect x="105" y="65" width="7" height="7"/><rect x="120" y="80" width="7" height="7"/>
<rect x="80" y="95" width="7" height="7"/><rect x="65" y="110" width="7" height="7"/>
<rect x="100" y="115" width="7" height="7"/><rect x="115" y="130" width="7" height="7"/>
<rect x="85" y="125" width="7" height="7"/><rect x="70" y="135" width="7" height="7"/>
<rect x="65" y="80" width="7" height="7"/><rect x="50" y="95" width="7" height="7"/>
<rect x="100" y="95" width="7" height="7"/><rect x="125" y="65" width="7" height="7"/>
</g>
</g>
<!-- red X overlay -->
<line x1="0" y1="0" x2="160" y2="160" stroke="#ef4444" stroke-width="6" opacity="0.85"/>
<line x1="160" y1="0" x2="0" y2="160" stroke="#ef4444" stroke-width="6" opacity="0.85"/>
<text x="80" y="195" text-anchor="middle" font-family="-apple-system, system-ui, sans-serif" font-size="13" fill="#fca5a5" font-weight="700">❌ AI再描画 · QRコード読み取り失敗</text>
<rect x="105" y="20" width="35" height="35" fill="#0f172a"/>
<rect x="112" y="27" width="21" height="21" fill="#ffffff"/>
<rect x="117" y="32" width="11" height="11" fill="#0f172a"/>
<rect x="20" y="105" width="35" height="35" fill="#0f172a"/>
<rect x="27" y="112" width="21" height="21" fill="#ffffff"/>
<rect x="32" y="117" width="11" height="11" fill="#0f172a"/>
<!-- aligned data modules -->
<g fill="#0f172a">
<rect x="65" y="20" width="7" height="7"/><rect x="80" y="20" width="7" height="7"/>
<rect x="65" y="35" width="7" height="7"/><rect x="90" y="35" width="7" height="7"/>
<rect x="75" y="50" width="7" height="7"/><rect x="65" y="65" width="7" height="7"/>
<rect x="20" y="65" width="7" height="7"/><rect x="35" y="80" width="7" height="7"/>
<rect x="50" y="65" width="7" height="7"/><rect x="20" y="90" width="7" height="7"/>
<rect x="105" y="65" width="7" height="7"/><rect x="120" y="80" width="7" height="7"/>
<rect x="80" y="95" width="7" height="7"/><rect x="65" y="110" width="7" height="7"/>
<rect x="100" y="115" width="7" height="7"/><rect x="115" y="130" width="7" height="7"/>
<rect x="85" y="125" width="7" height="7"/><rect x="70" y="135" width="7" height="7"/>
<rect x="65" y="80" width="7" height="7"/><rect x="50" y="95" width="7" height="7"/>
<rect x="100" y="95" width="7" height="7"/><rect x="125" y="65" width="7" height="7"/>
</g>
<!-- green check badge -->
<circle cx="155" cy="-5" r="14" fill="#10b981"/>
<text x="155" y="0" text-anchor="middle" font-family="-apple-system, system-ui, sans-serif" font-size="14" fill="#ffffff" font-weight="700">✓</text>
<text x="80" y="195" text-anchor="middle" font-family="-apple-system, system-ui, sans-serif" font-size="13" fill="#86efac" font-weight="700">✓ 後処理による連結 · 100% スキャン可能</text>
核心となる結論を一言で言うと、**「QR コードを AI に『描かせて』はいけない。AI の役割は背景画像の生成であり、QR コードは画像処理ライブラリを使って後処理で合成すべきである」**ということです。本記事では、OpenAI の公式ドキュメント、Stable Diffusion ControlNet の実践例、および QR コードの誤り訂正原理に基づき、なぜ AI による QR コードの再描画が必然的に破損を招くのかを体系的に解説します。また、APIYI (apiyi.com) プラットフォームの GPT Image 2 インターフェースと Python の完全なコードを組み合わせ、10 分で「AI による画像生成+読み取り可能な QR コード」の完全なパイプラインを構築する方法を紹介します。
1. AI 生成画像で QR コードが破損する理由
1.1 典型的な失敗例の再現
最もよくある失敗シナリオは、ユーザーがきれいな QR コード画像をアップロードし、「この QR コードを画面の右下に配置し、背景は温かみのあるカフェにして」というプロンプトを書いて GPT Image 2 API を呼び出すケースです。返ってきた画像には視覚的に QR コードが存在し、構図も合っていますが、どの読み取りツールを使っても認識されません。
肉眼では「モジュールの境界が少しぼやけているだけ」に見えるかもしれませんが、QR コードはピクセルの精度に対して非常にシビアです。単一のモジュール(小さな四角)の形状、位置、コントラストのいずれかが約 5% 以上ずれるだけで、コード全体が機能しなくなる可能性があります。 AI による再描画は、ニューラルネットワークを使ってこの QR コードを「描き直す」ことに等しく、どれほど高精度なモデルであっても 100% の再現を保証することはできません。
1.2 GPT Image 2 の再描画で破損する 3 つの根本原因
この問題を分解すると、AI による再描画で QR コードが破損する技術的な原因は以下の 3 層に集約されます。どれか一つでも欠けては解決できません。
| 原因層 | 技術的詳細 | 結果 |
|---|---|---|
| セマンティック再描画 | AI が QR コードを画像コンテンツとして理解し、ピクセルコピーではなく意味に基づいて再生成する | モジュールの形状が「美化」または歪曲される |
| 解像度のリサンプリング | モデルの出力には固定解像度(512/1K/2K/4K)があり、入力がリサイズされる | モジュールの境界にエイリアシングが発生する |
| 非可逆圧縮 | デフォルトの JPEG/WebP 出力では高周波成分が失われる | 黒と白のモジュールの境界にグレーのグラデーションが生じる |
これら 3 つの層が重なることで、本来厳密な二値(純粋な黒/純粋な白)であるべき QR コードのモジュールが「ぼやけたグレースケールの行列」に変化してしまいます。その結果、読み取りアルゴリズムのポジショニングパターンやデータモジュールの認識が失敗します。
さらに厄介なのは、この破損が肉眼では軽微に見えることです。完成した画像は依然として QR コードのように見える四角形で、コントラストも辛うじて保たれているように見えますが、読み取りソフトウェアはモジュールグリッドの正確な位置と二値密度に依存しているため、人間が無視するような 1〜2 ピクセルのズレにも非常に敏感です。これが、多くの人が「プロンプトの書き方が悪いのではないか」と疑い、プロンプトエンジニアリングに膨大な時間を費やしても、結局どう修正しても読み取れない理由です。
1.3 なぜ ChatGPT のウェブ版では成功することがあるのか
「ウェブ版では成功するのに、なぜ API ではダメなのか」と疑問に思うユーザーは多いでしょう。その真相は、ChatGPT のウェブ版内部では、QR コードに対して特別な後処理ロジックが組み込まれているからです。入力が QR コードであることを検出し、完全な再描画ではなく画像合成の手法を用いて生成を試みます。このロジックは API パラメータとして公開されていないため、API を直接呼び出す際にはこの特別なパスを利用できません。
つまり、「API 呼び出しで毎回壊れる」のはバグではなく、API が純粋なモデル生成パスを通っており、ウェブ版にあるような特別なガードレールが存在しないためです。プロンプトエンジニアリングでこの問題を解決しようとするのは徒労に終わります。これはアーキテクチャ上の制限であり、プロンプトの問題ではないからです。
🎯 核心的な考え方: API 呼び出しのシナリオでは、AI に QR コードを「含める」または「再描画」させることは絶対に避けてください。このルールを鉄則として心に刻んでおけば、後のデバッグ時間を大幅に節約できます。まずは APIYI (apiyi.com) で「AI による QR コードの再描画は必ず壊れる」という現象を一度検証してみてください。実際に体験すれば、このルールを一生忘れることはないはずです。
二、AI 画像QRコード合成の3つの正しいワークフロー
「AI画像生成」と「QRコード」という2つのタスクを役割分担させることが、唯一の正しいアプローチです。以下の3つの手法は、それぞれ異なる技術スタックやビジネスシーンに適しています。

2.1 手法1:AI背景生成 + 後処理合成(推奨、最も安定)
これは最もシンプルで安定した手法です。核心となる考え方は、**「AIには背景のみを生成させ、QRコードの存在を一切教えない」**こと。その上で、PythonやNode.jsなどのバックエンド言語を使用して、正確にQRコードを重ね合わせます。
ワークフローは以下の4ステップです:
- GPT Image 2を使用して純粋な背景画像を生成します。プロンプトには「右下にブランド要素用のクリーンな淡色エリアを確保すること」と明記します。
qrcodeライブラリを使用してローカルでQRコードを生成します(誤り訂正レベル、モジュールサイズ、クワイエットゾーンを制御)。- PILの
paste()メソッドを使用して、背景画像の指定位置にQRコードを合成します。 - PNG形式で出力します(JPEGは避けてください)。これにより、QRコードの境界線の鮮明さが保たれます。
このプロセス全体において、AIは「背景を描く」ことのみを担当します。QRコードはAIモデルを一切通らないため、破損する心配はありません。
2.2 手法2:AIによるプレースホルダー生成 + Canvas/Sharpによる自動配置
フロントエンドでの動的合成(例:ECサイトでユーザーがリアルタイムにQRコード付きポスターを生成する場合)を行う場合、手法1では少し重いため、手法2が適しています。
この手法は手法1に「自動配置」のステップを加えたものです。AIに背景画像内の**純色プレースホルダー(白やブランドカラーの矩形など)**を確保させ、OpenCVやSharpを使用してその位置を検出し、自動的にQRコードを合成します。フロントエンドであればCanvas APIで実装可能で、バックエンドの介入は不要です。
メリットは、多様なサイズへの適応やブラウザ上でのリアルタイム合成が可能な点です。デメリットは、プロンプト内でプレースホルダーの色やサイズを厳密に指定する必要があり、手法1よりもデバッグコストがわずかに高いことです。
2.3 手法3:ControlNet QR-Art(芸術的QRコード、上級編)
単に「QRコードを貼り付ける」だけでなく、QRコード自体をアートの一部にしたい場合(例:QRコードの黒白モジュールを花や建築物、テクスチャで構成するなど)は、Stable Diffusion + ControlNetのQR-Art手法が必要です。
この手法の本質は、ControlNetを使用してQRコードを「制御条件」としてSDに渡し、生成される画像のピクセル分布がQRコードの構造を維持するようにすることです。これはGPT Image 2では実現できません。GPT Image 2にはControlNetのインターフェースがないため、芸術的なQRコードを作成するにはSDワークフローへの切り替えが必須となります。
ControlNet QR-Artを使用する場合でも、誤り訂正レベルをH(30%)に設定し、生成後に必ずスキャンツールで検証することをお勧めします。そうしないと、見た目は美しくても読み取れない確率が高くなります。
| 手法 | 複雑さ | QR読み取り率 | 適用シーン |
|---|---|---|---|
| ① 後処理合成 | ⭐ 低 | ⭐⭐⭐⭐⭐ 100% | マーケティングポスター、製品パッケージ、印刷物 |
| ② Canvas自動配置 | ⭐⭐ 中 | ⭐⭐⭐⭐⭐ 100% | EC動的合成、ユーザー作成ポスター |
| ③ ControlNet QR-Art | ⭐⭐⭐⭐ 高 | ⭐⭐⭐ 70-90% | クリエイティブマーケティング、アートQRコード、ブランドイベント |
🎯 手法選択のアドバイス: 90%のビジネスシーンでは手法1で十分です。APIYI (apiyi.com) でGPT Image 2を呼び出して背景画像を生成し、ローカル環境でPythonを使って合成すれば、わずか10行程度のコードで一連のフローを構築できます。
三、AI 画像とQRコードを合成するPython完全コード例
原理を理解したところで、このセクションではそのままコピーして実行できるPythonの完全なコードを紹介します。最も一般的な「手法1」を網羅しています。
3.1 極小版:30行で全プロセスを完了
import io
import requests
import qrcode
from PIL import Image
from openai import OpenAI
# 1. GPT Image 2を呼び出して背景画像を生成(APIYI経由)
client = OpenAI(
api_key="your_api_key",
base_url="https://vip.apiyi.com/v1"
)
response = client.images.generate(
model="gpt-image-2",
prompt=(
"Cozy coffee shop poster, warm afternoon light, "
"wooden table with a cup of latte, "
"leave a clean light-colored square area at bottom right "
"for branding element, photorealistic"
),
size="1024x1536",
quality="high",
)
bg = Image.open(io.BytesIO(requests.get(response.data[0].url).content))
# 2. ローカルでQRコードを生成(高精度な誤り訂正 + 大きなクワイエットゾーン)
qr = qrcode.QRCode(
version=None,
error_correction=qrcode.constants.ERROR_CORRECT_H,
box_size=10,
border=4,
)
qr.add_data("https://apiyi.com")
qr.make(fit=True)
qr_img = qr.make_image(fill_color="black", back_color="white").convert("RGB")
qr_img = qr_img.resize((300, 300), Image.LANCZOS)
# 3. 後処理で合成:右下に貼り付け
bg.paste(qr_img, (bg.width - 360, bg.height - 360))
bg.save("poster_with_qr.png", "PNG", optimize=True)
このコードの重要なポイントは、QRコードがAIモデルに一切入力されていない点です。qrcodeライブラリからPIL.paste()、そして最終的なsave("PNG")まで、すべて純粋なピクセル操作であるため、QRコードは100%読み取り可能です。
3.2 重要なパラメータの詳細解説
コード内の目立たないながらも成功を左右するパラメータを紹介します。
error_correction=ERROR_CORRECT_H:誤り訂正レベルH(30%)。モジュールの30%が隠れても読み取り可能で、マーケティング用途における安全閾値です。border=4:クワイエットゾーン(余白)は4モジュール幅以上である必要があります。これより狭いと、複雑な背景では読み取り率が大幅に低下します。Image.LANCZOS:リサイズ時にLanczosアルゴリズムを使用し、QRコードの境界をシャープに保ちます。save(..., "PNG"):JPEGではなく必ずPNGを使用してください。JPEGの8×8ブロック圧縮は、モジュールの境界にカラーノイズを発生させます。
3.3 QRコード誤り訂正レベル早見表
シーンに応じて適切な誤り訂正レベルを選択しましょう。
| レベル | データ冗長性 | 適用シーン |
|---|---|---|
| L (Low) | 7% | クリーンな背景、純白地。合成には非推奨 |
| M (Medium) | 15% | デフォルト値。シンプルな背景なら使用可 |
| Q (Quartile) | 25% | 複雑な背景、装飾要素がある場合 |
| H (High) | 30% | 強く推奨:AI生成画像への合成には必須 |
🎯 安定性のヒント: AI生成画像に合成するQRコードは、迷わずHレベルの誤り訂正を使ってください。15%の冗長性を追加するだけで、見た目には分かりませんが、読み取り率の安定性が劇的に向上します。APIYI (apiyi.com) で合成フローをデバッグする際、このパラメータ設定で手戻りを大幅に減らせます。
四、AI QRコード合成の4つの高度な最適化テクニック
基本フローをマスターしたら、以下の4つのテクニックで読み取り率を95%から100%に引き上げましょう。

4.1 QRコードに白地のカードを追加する
黒白のQRコードを直接カラー背景に貼り付けると、視覚的に「浮いて」しまいます。プロの手法は、角丸で影付きの白いカードの中にQRコードを配置することです。これにより、読み取りエリアを確保しつつ、デザイン全体に馴染ませることができます。
from PIL import Image, ImageDraw, ImageFilter
card = Image.new("RGB", (340, 340), "white")
draw = ImageDraw.Draw(card)
# 角丸白カード + QRコードを中央配置
card.paste(qr_img, (20, 20))
# 影をつけてから背景画像に貼り付け
shadow = card.filter(ImageFilter.GaussianBlur(8))
bg.paste(shadow, (bg.width - 370, bg.height - 360))
bg.paste(card, (bg.width - 370, bg.height - 365))
白カード+影は、グラフィックデザインにおけるQRコードの標準的な包装であり、見栄えと読み取り率の両立が可能です。
4.2 AIプロンプトで配置エリアを明示する
AIに「どこを空けておくべきか」を伝えることは、後の手戻りを減らす鍵です。プロンプトには以下のように直接記述することをお勧めします。
leave a clean rectangular area approximately 300x300 pixels at the bottom right corner with light solid color, suitable for placing a brand element
ピクセルサイズと位置を具体的に指定すれば、AIは80%以上の確率で期待通りのレイアウトを出力します。一度でうまくいかなくても、コードを修正するよりプロンプトを調整する方がはるかに低コストです。
4.3 合成後にスキャンライブラリで自動検証する
合成した画像はすべて、スキャンライブラリを使用して自動検証を行い、確実に読み取れることを確認すべきです。
from pyzbar.pyzbar import decode
result = decode(bg)
assert result and result[0].data.decode() == "https://apiyi.com"
このステップをCIパイプラインに組み込めば、「公開後に読み取れないことが発覚する」といった事故は二度と起こりません。
4.4 バッチ処理時は背景とQRコードをキャッシュする
ECサイトの運用などでは「同じ背景に数百種類の異なるQRコードを配置する」といったケースがよくあります。この場合、背景画像は一度だけAIで生成してオブジェクトストレージにキャッシュし、その後の数百回の合成はローカルでのピクセル操作のみにすることで、APIコストを数百回分から1回分に削減できます。
| 高度なテクニック | 解決する問題 | メリット |
|---|---|---|
| 白地カード + 影 | QRコードと背景の視覚的な不一致 | 高 |
| プロンプトでエリア確保 | 合成位置と背景内容の衝突 | 高 |
| スキャンライブラリで自動検証 | 公開後の読み取り不可事故 | 極めて高い |
| 背景のバッチキャッシュ | APIコストの暴走 | 極めて高い |

五、AI QRコード合成に関するよくある質問(FAQ)
5.1 なぜChatGPTのWeb版ではうまくいくのに、APIではうまくいかないのですか?
Web版ではQRコードのシナリオに対して内部的な特殊処理(検出+合成)が行われていますが、このロジックはAPIのパラメータとして公開されていません。「APIもWeb版のように自動でQRコードを処理してくれる」と期待するのは現実的ではありません。正しいアプローチは、本記事の「手法1」のように、独自のコードでこの合成ロジックを再現することです。
5.2 GPT Image 2の画像編集モードとマスクを使用して、QRコード領域を「保持」することは可能ですか?
理論上、マスクは指定領域の再描画を防ぐはずですが、実測ではマスクの境界線に1〜3ピクセルの移行領域が発生します。QRコードのようなピクセル単位で判定されるシナリオでは、これは致命的です。マスク手法は諦め、後処理による合成を行うことを強く推奨します。
5.3 プロンプトで「QRコードを修正しないで」と繰り返し強調しても効果がありません。
効果はありません。プロンプトは「AIが何を描くか」には影響しますが、AIの出力プロセス自体にリサイズ、圧縮、ニューラルネットワークによる生成が含まれており、これらのステップがQRコードを無差別に破壊します。AIが「そうしたいかどうか」とは無関係です。
5.4 合成した画像をJPEGで出力してもいいですか?ファイルサイズが小さくなるので。
推奨しません。JPEGの8×8ブロック離散コサイン変換により、QRコードのモジュール境界にカラーノイズが発生し、読み取り率が著しく低下します。どうしてもJPEGにする必要がある場合は、品質パラメータを95以上に設定し、QRコード領域はPNGで重ね合わせるのが賢明です。最も確実なのはPNGで出力し、pngquantなどのツールで圧縮することです。
5.5 GPT Image 2を使って背景画像を安定して生成するにはどこを使えばいいですか?
国内のエンジニアは、APIYI(apiyi.com)を通じてGPT Image 2を呼び出すことができます。base_url を https://vip.apiyi.com/v1 に置き換えるだけで、プロキシ設定なしで利用可能です。同プラットフォームはGPT Image 2やNano Banana Proなど複数の主要な画像モデルをサポートしており、ビジネスシーンに合わせて最適なモデルを比較検討できます。
5.6 「QRコード自体がアートになっている」効果が欲しい場合、ControlNetは必須ですか?
はい、ControlNet QR-Artが現在利用可能な唯一のソリューションです。GPT Image 2にはピクセル単位の制御条件インターフェースがないため、「QRコードのモジュールがアートコンテンツで構成される」ような効果は出せません。もし「QRコードをアート背景の上に綺麗に配置したい」というニーズであれば、手法1+白背景カード+影の組み合わせで十分であり、ControlNetを使う必要はありません。
5.7 印刷用のQRコードに特別な要件はありますか?
あります。印刷用には、QRコードの物理サイズを2.5cm × 2.5cm以上、誤り訂正レベルを「H」、クワイエットゾーン(余白)を5モジュール以上確保し、色は厳密に黒と白(グレースケール不可)にすることをお勧めします。これらのパラメータにより、印刷の色ムラ、紙の反射、読み取り距離の変化があっても、QRコードを確実に読み取ることができます。
六、まとめ:AI画像生成とQRコードの役割分離原則
冒頭の問い「AIで生成した画像にどうやってQRコードを合成すれば壊れないか」に対する最も正確な答えは、**「AIにQRコードを合成させないこと」**です。AIには背景画像の生成のみを任せ、QRコードは画像処理ライブラリを使って後処理で合成してください。この原則を確立すれば、「再描画による破損」という問題は瞬時に解決します。
以下の3つの核心原則を覚えておいてください:
- 役割の分離: AIは背景を生成し、コードはプログラムで貼り付ける。この2つを一つのAPI呼び出しに混ぜてはいけません。
- 誤り訂正レベルを最大化: 合成シナリオでは常に「H(30%)」の誤り訂正を使用し、15%の冗長性で読み取りの信頼性を確保します。
- PNG出力 + 自動検証: PNGでモジュールの鋭さを維持し、pyzbarを使って読み取り率を自動検証します。
🎯 次のアクション: 本記事のPythonコードをプロジェクトにコピーし、APIYI(apiyi.com)のGPT Image 2インターフェースでパイプラインを一度実行してみてください。10分で読み取り率100%を達成できるはずです。このフローを構築すれば、今後のマーケティングポスター、製品パッケージ、イベント用素材など、あらゆるQRコードのシナリオで再利用可能です。
QRコードは画像コンテンツではなく、構造化データの視覚的エンコーディングです。本質はテキストやバーコードと同じです。「AIが理解できる画像」ではなく「ピクセル単位の正確さが求められる資産」として扱うことこそが、AI画像生成ツールを使いこなすための不可欠なマインドセットです。「プロンプトを3日間調整しても読み取れない」という苦しみから、今日で卒業しましょう。
著者: APIYI 技術チーム
対応プラットフォーム: APIYI(apiyi.com) GPT Image 2 / Nano Banana Pro 等の画像生成インターフェース
