かわいくてごめん
GeminiのNano Banana Proで画像を編集してみた。
実は簡易版なんですけど、Gemini 画像加工指示ツールていうのを作ったので使ってみた画像です。
生成内容は東京の街並みでフィルムのような画面で、MV撮影しているような風景でカメラのアングルだけ変更しています。
Gemini 画像加工指示ツールとは何か?
というとGeminiに画像生成を指示するYAMLを生成するツールです。
YAMLってなんやねんと思う人もいるでしょうけど、簡単に言うと人間とAIとの通訳みたいなもんだと思っていただければと思います。
普通に日本語とかでも指示は出来るんですけど、なかなか理解しない場合があるので、YAMLで指示してあげるとスムーズに理解してくれる場合が多いです。
ワイみたいな本当に素人用のツールなんですけど、使い方は・・・
①この投稿に貼っているソースコードをテキストファイルにコピーして、HTML形式で保存する。※一旦テキストで保存して拡張子をHTMLに変更でも可。
②パソコンで保存したファイルを開く。
③開くとブラウザでツールが開くので、まずは画像したい画像ファイルをツールで読み込む。
④あとは設定項目を指示に従って選択とか入力する。
※入力項目は特に指定はなくてしたいことを入力してください。入力しなくても大丈夫です。
⑤各項目の指定が終わったら「指示書YAMLを生成」のボタンをクリックします。
⑥YAMLが生成されるのでコピーします。
⑦Geminiにアクセスして、編集したい画像ファイルをアップロードして、入力欄で先程コピーしたYAMLのソースをペーストします。
⑧画像生成します。
以上。
以下、ソースコード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gemini 画像加工指示ツール</title>
<style>
body { font-family: "Helvetica Neue", Arial, sans-serif; background-color:
#f0f2f5; color: #333; padding: 20px; }
.container { max-width: 900px; margin: 0 auto; background:
#fff; padding: 30px; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
h1 { text-align: center; color:
#ff5722; margin-bottom: 30px; } /* 画像系なので少し暖色に */
h2 { border-bottom: 2px solid
#ff5722; padding-bottom: 10px; margin-top: 30px; font-size: 1.2em; }
/* ファイルアップロード */
.file-upload-area { border: 2px dashed
#ccc; padding: 20px; text-align: center; border-radius: 8px; margin-bottom: 30px; background:
#fafafa; }
#fileNameDisplay { margin-top: 10px; font-weight: bold; color:
#ff5722; }
/* 動的フォームエリア */
.control-group { margin-bottom: 20px; padding: 15px; background:
#f9f9f9; border-radius: 8px; border-left: 4px solid
#ddd; }
.control-label { font-weight: bold; display: block; margin-bottom: 8px; }
select, input[type="text"] { width: 100%; padding: 10px; border: 1px solid
#ccc; border-radius: 4px; }
/* ラジオボタン、チェックボックスのスタイル調整 */
.radio-group, .checkbox-group { display: flex; flex-wrap: wrap; gap: 10px; }
.radio-option, .checkbox-option { background:
#fff; padding: 8px 12px; border: 1px solid
#ddd; border-radius: 20px; cursor: pointer; transition: all 0.2s; }
.radio-option:hover, .checkbox-option:hover { background:
#eee; }
input[type="radio"], input[type="checkbox"] { margin-right: 8px; accent-color:
#ff5722; }
/* フリーテキスト */
textarea { width: 100%; height: 80px; padding: 10px; border: 1px solid
#ccc; border-radius: 4px; resize: vertical; }
.btn-gen { display: block; width: 100%; padding: 15px; background-color:
#ff5722; color: white; border: none; border-radius: 4px; font-size: 18px; font-weight: bold; cursor: pointer; margin-top: 30px; transition: background 0.3s; }
.btn-gen:hover { background-color:
#e64a19; }
pre { background:
#2d2d2d; color:
#f8f8f2; padding: 20px; border-radius: 4px; overflow-x: auto; white-space: pre-wrap; position: relative; }
.copy-btn { position: absolute; top: 10px; right: 10px; background: #555; color: white; border: none; padding: 5px 10px; border-radius: 4px; cursor: pointer; font-size: 12px; }
</style>
</head>
<body>
<div class="container">
<h1>Gemini 画像加工指示ツール</h1>
<h2>STEP 1: 画像選択</h2>
<div class="file-upload-area">
<input type="file" id="imageInput" accept="image/png, image/jpeg, image/webp">
<div id="fileNameDisplay">ファイルが選択されていません</div>
</div>
<h2>STEP 2: 加工指示の設定</h2>
<div id="dynamicFormArea"></div>
<div class="control-group" style="border-left-color:
#ff5722;">
<label class="control-label">その他の自由記述 (Additional Notes)</label>
<textarea id="freeText" placeholder="上記項目で表現しきれない細かいニュアンスなどを記述"></textarea>
</div>
<button class="btn-gen" onclick="generateImageYaml()">指示書YAMLを生成</button>
<div id="outputArea" style="display:none; margin-top: 30px;">
<h2>生成結果</h2>
<pre id="yamlOutput"><button class="copy-btn" onclick="copyToClipboard()">コピー</button><code id="yamlCode"></code></pre>
</div>
</div>
<script>
// =========================================
// 【設定エリア】将来の拡張はここを編集します
// =========================================
const FORM_CONFIG = [
{
id: "style",
title: "① スタイル・画風 (Style)",
type: "select", // ドロップダウン形式
options: ["指定なし (元のスタイルを維持)", "写真 (Photorealistic)", "アニメ調 (Anime style)", "水彩画風 (Watercolor)", "サイバーパンク (Cyberpunk)", "ピクセルアート (Pixel Art)"]
},
{
id: "composition",
title: "② カメラ構図・アングル (Composition)",
type: "radio", // ラジオボタン形式(単一選択)
options: ["指定なし", "クローズアップ", "バストアップ", "全身が写るように", "広角レンズでダイナミックに", "真上からの視点 (Top-down view)"]
},
{
id: "background",
title: "③ 背景の変更 (Background)",
type: "text", // 自由入力形式
placeholder: "例: 賑やかな東京の街並みに変更、背景を完全に白抜きにする、など"
},
{
id: "lighting",
title: "④ 照明・雰囲気 (Lighting & Mood)",
type: "select",
options: ["指定なし", "自然光 (Natural light)", "劇的なライティング (Dramatic lighting)", "夕暮れ (Golden hour)", "ネオンサインの光 (Neon lights)", "薄暗くシリアスな雰囲気"]
},
{
id: "elements_to_add",
title: "⑤ 追加要素 (Add Elements)",
type: "text",
placeholder: "例: 被写体に赤いマフラーを追加、空に飛行船を追加、など"
}
// ★将来ここに新しい設定ブロックを追加するだけで、画面に自動反映されます★
];
// =========================================
// システムロジック(触らなくてOK)
// =========================================
// 起動時にフォームを動的に生成する
window.onload = function() {
const formArea = document.getElementById('dynamicFormArea');
FORM_CONFIG.forEach(config => {
let html = `<div class="control-group" data-id="${
config.id}" data-type="${config.type}">`;
html = `<label class="control-label">${config.title}</label>`;
if (config.type === 'select') {
html = `<select id="${
config.id}">`;
config.options.forEach(opt => {
html = `<option value="${opt}">${opt}</option>`;
});
html = `</select>`;
} else if (config.type === 'radio') {
html = `<div class="radio-group">`;
config.options.forEach((opt, index) => {
const radioId = `${
config.id}_${index}`;
html = `<label class="radio-option" for="${radioId}">`;
html = `<input type="radio" id="${radioId}" name="${
config.id}" value="${opt}" ${index === 0 ? 'checked' : ''}>${opt}`;
html = `</label>`;
});
html = `</div>`;
} else if (config.type === 'text') {
html = `<input type="text" id="${
config.id}" placeholder="${config.placeholder}">`;
}
html = `</div>`;
formArea.innerHTML = html;
});
// ファイル選択時の表示更新
document.getElementById('imageInput').addEventListener('change', function(e) {
const fileName =
e.target.files[0] ?
e.target.files[0].name : "ファイルが選択されていません";
document.getElementById('fileNameDisplay').textContent = "選択中: " fileName;
});
};
function generateImageYaml() {
const fileInput = document.getElementById('imageInput');
const fileName = fileInput.files[0] ? fileInput.files[0].name : "(画像をアップロードしてください)";
const freeText = document.getElementById('freeText').value;
// 動的フォームの値を取得
let instructionsYamlStr = "";
FORM_CONFIG.forEach(config => {
let value = "";
if (config.type === 'select' || config.type === 'text') {
value = document.getElementById(
config.id).value;
} else if (config.type === 'radio') {
const checkedRadio = document.querySelector(`input[name="${
config.id}"]:checked`);
if (checkedRadio) value = checkedRadio.value;
}
// "指定なし" や空欄以外をYAMLに追加
if (value && !value.startsWith("指定なし")) {
instructionsYamlStr = ` ${
config.id}: "${value}"\n`;
}
});
// 自由記述を追加
if (freeText) {
instructionsYamlStr = ` additional_notes: |\n${indentString(freeText, 6)}\n`;
}
// 最終的なYAMLを組み立て(画像編集指示用のプロンプト構造)
const finalYaml = `system_instruction:
role: "熟練した画像編集レタッチャー兼AIアーティスト"
task: "ユーザーが提供する入力画像を、指示に基づいて加工・修正し、新しい画像を生成すること。"
request:
input_image_reference: "${fileName}"
editing_instructions:
${instructionsYamlStr || " (特に指定なし。元画像の良さを活かしてください。)"}
`;
document.getElementById('yamlCode').textContent = finalYaml;
document.getElementById('outputArea').style.display = 'block';
}
function indentString(str, count) {
const indent = ' '.repeat(count);
return str.split('\n').map(line => indent line).join('\n');
}
function copyToClipboard() {
const text = document.getElementById('yamlCode').textContent;
navigator.clipboard.writeText(text).then(() => alert('コピーしました!'));
}
</script>
</body>
</html>
将来的に指定したい項目を足したい人はソース内の
// ★将来ここに新しい設定ブロックを追加するだけで、画面に自動反映されます★
の行に以下のようなソースを足していただければ指定項目は増やせます。
例:天気の項目を増やしたい場合
, { id: "weather", // YAMLのキー名になります title: "⑥ 天候 (Weather)", // 画面の表示名 type: "select", // select(ドロップダウン)か radio(ボタン)か text(自由入力) options: ["指定なし", "快晴", "雨天", "雪", "嵐"] // 選択肢 }
#Gemini #NanoBananaPro #Gemini画像加工指示ツール