0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Nano Banana Pro 完全ガイド:動物写真のAI編集・生成テクニック

0
Posted at

Nano Banana Pro 完全ガイド:動物写真のAI編集・生成テクニック

はじめに

AI画像生成ツール Nano Banana Pro を使って動物写真を編集・生成するための実践ガイドです。TypeScriptでミニアプリを開発する際に、「思い通りの動物画像を生成する」ためのプロンプト設計の本質を解説します。

このガイドは、実際のプロダクト開発で遭遇した数々の失敗から学んだ、再現性の高いプロンプト設計手法をまとめたものです。


目次

  1. Nano Banana Proの基本理解
  2. 最大の課題:AIの予測不可能性
  3. プロンプト設計の5つの黄金原則
  4. TypeScript実装のベストプラクティス
  5. よくある失敗パターンと対策
  6. 2画像入力の活用テクニック
  7. 品質を上げる実践Tips

Nano Banana Proの基本理解

Nano Banana Proとは

画像生成AIをベースとしたツールで、既存の動物写真を編集・変換することに特化しています。

主な用途:

  • 動物の毛色・模様の変更
  • 背景の変更・削除
  • ポーズや表情の微調整
  • 品種特徴の強調・変更
  • 2枚の動物写真の特徴を組み合わせ

他のAI画像生成ツールとの違い

特徴 一般的なAI画像生成 Nano Banana Pro
入力 テキストのみ 動物写真 + テキスト
制御性 低い(予測困難) 高い(元写真をベースに編集)
用途 ゼロからの生成 既存写真の編集・変換
再現性 低い 比較的高い

なぜ難しいのか?

AI画像生成には本質的な課題があります:

❌ AIは「理解」していない

  • プロンプトの言語的な意味を読み取るが、動物の生物学的特徴は理解しない
  • 「この部分だけ変更」「この特徴は保持」という概念が曖昧
  • 品種特有の特徴を正確に理解していない

❌ 確率的な生成プロセス

  • 同じプロンプトでも毎回異なる結果
  • 「ほぼ正しい」が実用では「完全に間違い」(例:足の数が5本)

✅ だからこそプロンプト設計が重要


最大の課題:AIの予測不可能性

実際に起きた失敗例

ケース1:意図しない部分まで変わる

やりたかったこと: 犬の毛色だけ変更したい

❌ 単純なプロンプト:
"change fur color to golden"

結果: 
- 毛色は変わったが、目の色も変わった
- 耳の形が変形した
- 背景の色まで変わった

原因: AIは「毛色だけ変更」を理解できていない


ケース2:解剖学的に不自然な結果

やりたかったこと: 猫の表情を笑顔にしたい

❌ 単純なプロンプト:
"smiling cat"

結果:
- 足が5本になった
- 耳の位置がおかしい
- 尻尾が2本に増えた
- 人間のような笑顔(不気味)

原因: 「笑顔」の指示が曖昧で、AIが動物の解剖学を無視


ケース3:背景削除で動物まで消える

やりたかったこと: 背景だけ削除して白背景にしたい

❌ 単純なプロンプト:
"remove background"

結果:
- 動物の耳の一部が消えた
- 尻尾が半分透明になった
- 足が背景と同化して消えた

原因: 削除範囲が不明確で、「保持すべきもの」の指示がない


なぜこれらが起きるのか?

理由1: プロンプトの優先順位が曖昧

AIは複数の指示があると、どれを重視すべきか判断できません。

"golden retriever with blue eyes, realistic"
→ "golden retriever" と "blue eyes" が品種として矛盾する可能性をAIは理解できない

理由2: 否定形が弱い

「〜しない」より「〜する」の方が強く作用します。

"don't change eye color" < "preserve original eye color exactly"

理由3: 解剖学的知識の限界

人間なら当然わかる「常識」をAIは持っていません。

"add wings to cat" 
→ 人間: ファンタジー的な表現
→ AI: 足の代わりに翼、6本足など、解剖学的に不自然な結果

プロンプト設計の5つの黄金原則

これらの原則に従うことで、AIの予測不可能性を最小化できます。


原則1️⃣: 明示的な指示(Explicit Instructions)

❌ 悪い例:

"cute dog photo"

✅ 良い例:

"golden retriever puppy, 3 months old, sitting position,
fluffy fur texture, brown eyes, natural outdoor lighting,
professional pet photography, 8k quality"

ポイント:

  • 曖昧な形容詞(cute, nice, beautiful)を避ける
  • 具体的な属性を列挙する(品種、年齢、ポーズ、毛質)
  • 品質指定も明示(professional photography, 8k)

原則2️⃣: 保持と変更の明確な分離

❌ 悪い例:

"change fur color to brown"

✅ 良い例:

"change fur color to chocolate brown,
preserve original: eye color, ear shape, nose, body proportions, pose,
maintain anatomical accuracy,
no other modifications"

テンプレート構造:

[変更内容], 
preserve original [保持すべき特徴],
maintain [保持すべき解剖学的特徴],
no other modifications

実装例:

function buildAnimalPrompt(change: string, preserve: string[]): string {
  return `${change}, 
preserve original ${preserve.join(', ')}, 
maintain anatomical accuracy,
no other modifications,
professional pet photography, 8k quality`;
}

// 使用例
const prompt = buildAnimalPrompt(
  "change fur color to golden brown",
  ["eye color", "ear shape", "nose", "body proportions", "facial expression"]
);

原則3️⃣: ネガティブプロンプトの活用

ネガティブプロンプトは「生成してはいけないもの」を指定します。

基本構造:

Positive prompt: やりたいこと
Negative prompt: 避けたいこと

実例:

const positivePrompt = `
labrador retriever, change fur color to black,
preserve eye color, facial features, body structure
`;

const negativePrompt = `
extra legs, extra tails, missing body parts,
deformed paws, incorrect anatomy, human features,
extra eyes, mutated, distorted proportions,
unnatural pose
`;

動物画像でよく使うネガティブキーワード:

  • 解剖学的異常防止: extra legs, extra tails, missing limbs, deformed, mutated
  • 品質低下防止: blurry, low quality, pixelated, artifacts
  • 不自然な特徴防止: human features, anthropomorphic, cartoon, unrealistic

原則4️⃣: 段階的アプローチ

複雑な変更は一度にやらず、段階的に実行します。

❌ 悪いアプローチ:

// 一度に全部やる
const prompt = "change breed, change color, change background, add accessories";

✅ 良いアプローチ:

// Step 1: 毛色変更
const step1 = generateImage({
  baseImage: originalDog,
  prompt: "change fur color to golden, preserve all other features"
});

// Step 2: 背景変更
const step2 = generateImage({
  baseImage: step1,
  prompt: "change background to white studio, preserve animal completely"
});

// Step 3: アクセサリー追加
const step3 = generateImage({
  baseImage: step2,
  prompt: "add red collar only, preserve everything else"
});

メリット:

  • 各段階で品質チェック可能
  • 問題が起きた場合、どこで失敗したか特定しやすい
  • 解剖学的異常が発生した段階で修正できる

原則5️⃣: パラメータの体系的管理

プロンプトをハードコーディングせず、パラメータ化します。

❌ 悪い例:

const prompt = "cute cat with blue eyes";

✅ 良い例:

interface AnimalPromptParams {
  species: string;        // 種(dog, cat, bird等)
  breed?: string;         // 品種
  age?: string;          // 年齢
  furColor?: string;     // 毛色
  eyeColor?: string;     // 目の色
  pose?: string;         // ポーズ
  background?: string;   // 背景
  lighting?: string;     // 照明
}

function buildAnimalPrompt(params: AnimalPromptParams): string {
  const parts = [];
  
  if (params.breed) {
    parts.push(`${params.breed} ${params.species}`);
  } else {
    parts.push(params.species);
  }
  
  if (params.age) parts.push(`${params.age} old`);
  if (params.furColor) parts.push(`${params.furColor} fur`);
  if (params.eyeColor) parts.push(`${params.eyeColor} eyes`);
  if (params.pose) parts.push(params.pose);
  if (params.background) parts.push(`${params.background} background`);
  if (params.lighting) parts.push(params.lighting);
  
  parts.push('professional pet photography', '8k quality', 'sharp focus');
  
  return parts.join(', ');
}

// 使用例
const params: AnimalPromptParams = {
  species: "dog",
  breed: "golden retriever",
  age: "puppy, 3 months",
  furColor: "light golden",
  eyeColor: "dark brown",
  pose: "sitting, looking at camera",
  background: "natural outdoor park",
  lighting: "soft natural daylight"
};

const prompt = buildAnimalPrompt(params);

TypeScript実装のベストプラクティス

1. 動物画像専用プロンプトビルダーパターン

class AnimalPromptBuilder {
  private parts: string[] = [];
  private negatives: string[] = [];

  // 基本動物情報
  setAnimal(species: string, breed?: string): this {
    if (breed) {
      this.parts.push(`${breed} ${species}`);
    } else {
      this.parts.push(species);
    }
    return this;
  }

  // 変更内容
  addModification(modification: string): this {
    this.parts.push(modification);
    return this;
  }

  // 保持する特徴
  preserveFeatures(features: string[]): this {
    this.parts.push(`preserve original ${features.join(', ')}`);
    this.parts.push('maintain anatomical accuracy');
    return this;
  }

  // ポーズ・状態
  setPose(pose: string): this {
    this.parts.push(pose);
    return this;
  }

  // 背景
  setBackground(background: string): this {
    this.parts.push(`${background} background`);
    return this;
  }

  // 品質指定
  setQuality(quality: string = '8k'): this {
    this.parts.push(`professional pet photography, ${quality} quality, sharp focus`);
    return this;
  }

  // ネガティブプロンプト
  addNegative(items: string[]): this {
    this.negatives.push(...items);
    return this;
  }

  // 解剖学的異常の防止(デフォルト)
  preventAnatomicalIssues(): this {
    this.negatives.push(
      'extra legs', 'extra tails', 'missing limbs',
      'deformed paws', 'incorrect anatomy', 'mutated',
      'distorted proportions', 'extra eyes', 'extra ears'
    );
    return this;
  }

  // 構築
  build(): { positive: string; negative: string } {
    return {
      positive: this.parts.join(', '),
      negative: this.negatives.join(', ')
    };
  }
}

// 使用例1: 毛色変更
const colorChange = new AnimalPromptBuilder()
  .setAnimal('dog', 'golden retriever')
  .addModification('change fur color to chocolate brown')
  .preserveFeatures(['eye color', 'facial features', 'body structure'])
  .setPose('sitting, looking at camera')
  .setBackground('white studio')
  .setQuality('8k')
  .preventAnatomicalIssues()
  .build();

// 使用例2: 背景変更
const backgroundChange = new AnimalPromptBuilder()
  .setAnimal('cat', 'persian')
  .addModification('change background to outdoor garden')
  .preserveFeatures(['fur color', 'eye color', 'pose', 'all body features'])
  .setQuality('8k')
  .preventAnatomicalIssues()
  .addNegative(['blurry', 'low quality'])
  .build();

2. 動物プリセット管理システム

// 動物特有のプリセット定義
const ANIMAL_PRESETS = {
  anatomical_accuracy: {
    positive: [
      'correct animal anatomy',
      'proper proportions',
      'natural pose',
      'realistic features'
    ],
    negative: [
      'extra legs', 'extra tails', 'missing limbs',
      'deformed paws', 'incorrect anatomy', 'mutated',
      'extra eyes', 'extra ears', 'distorted body',
      'unnatural proportions', 'anthropomorphic'
    ]
  },

  preserve_identity: {
    positive: [
      'maintain breed characteristics',
      'preserve facial features',
      'keep original eye color',
      'maintain fur pattern'
    ],
    negative: [
      'different breed', 'changed facial structure',
      'altered eye shape', 'modified nose',
      'different ear shape'
    ]
  },

  fur_quality: {
    positive: [
      'detailed fur texture',
      'individual hair strands visible',
      'natural fur flow',
      'realistic coat'
    ],
    negative: [
      'flat fur', 'painted look', 'plastic appearance',
      'unnatural texture', 'blurry fur'
    ]
  },

  professional_photo: {
    positive: [
      'professional pet photography',
      'sharp focus on eyes',
      'studio lighting quality',
      '8k ultra detailed',
      'award winning photography'
    ],
    negative: [
      'blurry', 'low quality', 'pixelated',
      'amateur photo', 'poor lighting',
      'out of focus'
    ]
  },

  natural_expression: {
    positive: [
      'natural animal expression',
      'realistic facial features',
      'authentic behavior',
      'species-appropriate demeanor'
    ],
    negative: [
      'human expression', 'cartoon', 'animated',
      'anthropomorphic', 'unnatural smile',
      'human-like features'
    ]
  }
};

// プリセット適用関数
function applyAnimalPresets(
  basePrompt: string,
  presetNames: (keyof typeof ANIMAL_PRESETS)[]
): { positive: string; negative: string } {
  
  const positives = [basePrompt];
  const negatives: string[] = [];

  presetNames.forEach(name => {
    const preset = ANIMAL_PRESETS[name];
    if (preset) {
      positives.push(...preset.positive);
      negatives.push(...preset.negative);
    }
  });

  return {
    positive: positives.join(', '),
    negative: negatives.join(', ')
  };
}

// 使用例
const result = applyAnimalPresets(
  'golden retriever puppy, change fur color to white',
  ['anatomical_accuracy', 'preserve_identity', 'fur_quality', 'professional_photo']
);

3. 動物画像バリデーション機能

interface AnimalValidationResult {
  isValid: boolean;
  errors: string[];
  warnings: string[];
}

function validateAnimalPrompt(prompt: string): AnimalValidationResult {
  const errors: string[] = [];
  const warnings: string[] = [];

  // 解剖学的保護チェック
  const hasAnatomicalProtection = 
    prompt.includes('anatomical') || 
    prompt.includes('correct anatomy') ||
    prompt.includes('proper proportions');
  
  if (!hasAnatomicalProtection) {
    warnings.push('解剖学的精度の保護がありません。異常な生成結果の可能性があります。');
  }

  // 保持指示チェック
  if (!prompt.includes('preserve') && !prompt.includes('maintain')) {
    errors.push('保持指示がありません。意図しない特徴変更の可能性があります。');
  }

  // 危険なキーワードチェック
  const dangerousTerms = ['mutate', 'transform', 'morph', 'hybrid'];
  dangerousTerms.forEach(term => {
    if (prompt.toLowerCase().includes(term)) {
      warnings.push(`危険な表現 "${term}" が含まれています。予測不可能な結果になる可能性があります。`);
    }
  });

  // 曖昧な表現チェック
  const vagueTerms = ['cute', 'nice', 'beautiful', 'better', 'improved'];
  vagueTerms.forEach(term => {
    if (prompt.toLowerCase().includes(term)) {
      warnings.push(`曖昧な表現 "${term}" が含まれています。具体的な指示に置き換えてください。`);
    }
  });

  // 品種と特徴の矛盾チェック
  if (prompt.includes('golden retriever') && prompt.includes('blue eyes')) {
    warnings.push('品種特徴の矛盾: ゴールデンレトリバーは通常青い目を持ちません。');
  }

  if (prompt.includes('siamese cat') && prompt.includes('orange fur')) {
    warnings.push('品種特徴の矛盾: シャム猫は通常オレンジ色の毛を持ちません。');
  }

  // 人間化の警告
  if (prompt.includes('smiling') || prompt.includes('laughing')) {
    warnings.push('人間的な表情指定があります。不自然な結果になる可能性があります。"happy expression" または "alert" を推奨します。');
  }

  return {
    isValid: errors.length === 0,
    errors,
    warnings
  };
}

// 使用例
const validation = validateAnimalPrompt(
  "cute golden retriever with blue eyes, smiling"
);

if (!validation.isValid) {
  console.error('Errors:', validation.errors);
}
if (validation.warnings.length > 0) {
  console.warn('Warnings:', validation.warnings);
}

4. 動物種別テンプレートシステム

interface AnimalContext {
  species: 'dog' | 'cat' | 'bird' | 'rabbit' | 'other';
  breed?: string;
  age?: string;
  modification: string;
  preserve: string[];
  background?: string;
  lighting?: string;
}

class AnimalPromptTemplate {
  private static SPECIES_SPECIFICS = {
    dog: {
      commonFeatures: ['tail', 'ears', 'snout', 'paws'],
      anatomyChecks: ['4 legs', 'proper tail position', 'correct ear placement'],
      negatives: ['extra legs', 'human features', 'cartoon appearance']
    },
    cat: {
      commonFeatures: ['whiskers', 'tail', 'ears', 'paws'],
      anatomyChecks: ['4 legs', 'flexible spine', 'proper whisker count'],
      negatives: ['extra legs', 'missing whiskers', 'dog features']
    },
    bird: {
      commonFeatures: ['wings', 'beak', 'feathers', 'talons'],
      anatomyChecks: ['2 wings', '2 legs', 'proper beak shape'],
      negatives: ['extra wings', 'missing wings', 'mammal features']
    },
    rabbit: {
      commonFeatures: ['long ears', 'cotton tail', 'paws'],
      anatomyChecks: ['4 legs', 'proper ear length', 'small tail'],
      negatives: ['short ears', 'long tail', 'predator features']
    },
    other: {
      commonFeatures: [],
      anatomyChecks: ['correct anatomy for species'],
      negatives: ['anatomical errors', 'mixed species']
    }
  };

  static build(context: AnimalContext): { positive: string; negative: string } {
    const specifics = this.SPECIES_SPECIFICS[context.species];
    
    const parts: string[] = [];
    
    // 基本情報
    if (context.breed) {
      parts.push(`${context.breed} ${context.species}`);
    } else {
      parts.push(context.species);
    }
    
    if (context.age) {
      parts.push(context.age);
    }

    // 変更内容
    parts.push(context.modification);

    // 保持する特徴
    const preserveList = [...context.preserve, ...specifics.commonFeatures];
    parts.push(`preserve original ${[...new Set(preserveList)].join(', ')}`);

    // 解剖学的精度
    parts.push(...specifics.anatomyChecks);

    // 背景・照明
    if (context.background) parts.push(`${context.background} background`);
    if (context.lighting) parts.push(context.lighting);

    // 品質
    parts.push('professional pet photography', '8k quality', 'sharp focus');

    // ネガティブプロンプト
    const negatives = [
      ...specifics.negatives,
      'blurry', 'low quality', 'distorted',
      'extra body parts', 'missing body parts',
      'unnatural proportions', 'mutated'
    ];

    return {
      positive: parts.join(', '),
      negative: negatives.join(', ')
    };
  }
}

// 使用例
const dogPrompt = AnimalPromptTemplate.build({
  species: 'dog',
  breed: 'golden retriever',
  age: 'puppy, 3 months old',
  modification: 'change fur color to white',
  preserve: ['eye color', 'facial expression'],
  background: 'natural outdoor park',
  lighting: 'soft natural daylight'
});

const catPrompt = AnimalPromptTemplate.build({
  species: 'cat',
  breed: 'persian',
  modification: 'remove background',
  preserve: ['fur color', 'eye color', 'pose'],
  background: 'white studio'
});

よくある失敗パターンと対策

失敗1: プロンプトが曖昧

症状: 毎回全く異なる動物が生成される

原因:

 const prompt = "cute dog";

対策:

 const prompt = `
golden retriever puppy, 3 months old,
light golden fur with natural texture,
dark brown eyes, black nose,
sitting position looking at camera,
natural outdoor lighting, soft focus background,
professional pet photography, 8k quality
`;

ポイント:

  • 品種、年齢、毛色、目の色、ポーズを全て明示
  • 照明と品質も具体的に指定

失敗2: 解剖学的精度の指示不足

症状: 足が5本、尻尾が2本、目が3つなど異常な結果

原因:

 const prompt = "change cat fur to orange";

対策:

 const prompt = `
domestic shorthair cat, change fur color to orange tabby pattern,
preserve original: eye color, facial features, body structure, pose,
maintain correct anatomy: 4 legs, 1 tail, 2 eyes, 2 ears,
proper feline proportions, natural pose,
no anatomical abnormalities
`;

TypeScript実装例:

function ensureAnatomicalAccuracy(basePrompt: string, species: string): string {
  const anatomySpecs = {
    dog: '4 legs, 1 tail, 2 eyes, 2 ears, proper canine proportions',
    cat: '4 legs, 1 tail, 2 eyes, 2 ears, proper feline proportions',
    bird: '2 wings, 2 legs, 1 beak, proper avian structure',
    rabbit: '4 legs, 2 long ears, 1 small tail, proper lagomorph proportions'
  };

  const spec = anatomySpecs[species] || 'correct anatomy for species';
  
  return `${basePrompt}, maintain ${spec}, no anatomical abnormalities`;
}

失敗3: ネガティブプロンプトの欠如

症状: 人間のような表情、変形した体、不自然な特徴

原因:

 const config = {
  prompt: "happy dog"
  // negativePrompt がない
};

対策:

 const config = {
  prompt: `
    golden retriever, alert and friendly expression,
    natural canine behavior, realistic features
  `,
  negativePrompt: `
    human expression, anthropomorphic, cartoon,
    extra legs, extra tails, missing body parts,
    deformed, mutated, distorted proportions,
    unnatural smile, human features
  `
};

TypeScript実装例:

interface AnimalImageConfig {
  prompt: string;
  negativePrompt: string;
  strength?: number;
}

function createSafeAnimalConfig(
  prompt: string,
  species: string
): AnimalImageConfig {
  
  const commonNegatives = [
    'blurry', 'low quality', 'distorted', 'pixelated',
    'extra legs', 'extra tails', 'missing limbs',
    'deformed paws', 'mutated', 'incorrect anatomy'
  ];

  const speciesNegatives = {
    dog: ['cat features', 'human expression', 'anthropomorphic'],
    cat: ['dog features', 'human expression', 'anthropomorphic'],
    bird: ['mammal features', 'extra wings', 'missing wings'],
    rabbit: ['predator features', 'short ears', 'long tail']
  };

  const negatives = [
    ...commonNegatives,
    ...(speciesNegatives[species] || [])
  ];

  return {
    prompt,
    negativePrompt: negatives.join(', '),
    strength: 0.7
  };
}

失敗4: 過度な要求

症状: 生成品質が著しく低下、または奇形

原因:

 const prompt = `
change breed, change color, change pose,
add accessories, change background,
modify facial features, adjust proportions,
...(15個の指示)
`;

対策: 段階的実行

 
async function complexAnimalTransformation(baseImage: string) {
  // Step 1: 毛色変更のみ
  const step1 = await generateImage({
    baseImage,
    prompt: "change fur color to golden brown, preserve all other features"
  });

  // 検証: 解剖学的異常がないか確認
  if (!await validateAnatomy(step1)) {
    throw new Error('Anatomical issues detected in step 1');
  }

  // Step 2: 背景変更
  const step2 = await generateImage({
    baseImage: step1,
    prompt: "change background to white studio, preserve animal completely"
  });

  // Step 3: アクセサリー追加
  const step3 = await generateImage({
    baseImage: step2,
    prompt: "add red collar only, preserve everything else"
  });

  return step3;
}

失敗5: パラメータ値の不適切な設定

症状: 意図しない変形、品種の変更

原因:

 const config = {
  prompt: "change fur color only",
  strength: 0.9  // 強すぎる!
};

対策: 操作タイプに応じた適切な値

 
const ANIMAL_OPERATION_CONFIGS = {
  fur_color_change: {
    strength: 0.3-0.4,  // 控えめ(表面的な変更)
    cfgScale: 7-9
  },
  
  background_change: {
    strength: 0.4-0.6,  // 中程度
    cfgScale: 7-9
  },
  
  remove_background: {
    strength: 0.6-0.8,  // 強め(Inpainting推奨)
    cfgScale: 7-9
  },
  
  minor_feature_adjust: {
    strength: 0.2-0.3,  // 非常に控えめ
    cfgScale: 8-10
  },

  breed_characteristics: {
    strength: 0.5-0.7,  // 中〜強め
    cfgScale: 9-11
  }
};

function getOptimalConfig(operation: string) {
  return ANIMAL_OPERATION_CONFIGS[operation] || {
    strength: 0.5,
    cfgScale: 7
  };
}

失敗6: 品種特徴との矛盾

症状: ありえない特徴の組み合わせ

原因:

 const prompt = "golden retriever with blue eyes and black fur";

対策: 品種チェッカーの実装

interface BreedCharacteristics {
  typicalFurColors: string[];
  typicalEyeColors: string[];
  distinctiveFeatures: string[];
}

const BREED_DATABASE: Record<string, BreedCharacteristics> = {
  'golden_retriever': {
    typicalFurColors: ['golden', 'light golden', 'dark golden', 'cream'],
    typicalEyeColors: ['brown', 'dark brown'],
    distinctiveFeatures: ['floppy ears', 'long fur', 'friendly expression']
  },
  'siberian_husky': {
    typicalFurColors: ['black and white', 'gray and white', 'red and white'],
    typicalEyeColors: ['blue', 'brown', 'heterochromia'],
    distinctiveFeatures: ['pointed ears', 'thick double coat', 'curled tail']
  },
  'siamese_cat': {
    typicalFurColors: ['seal point', 'blue point', 'chocolate point', 'lilac point'],
    typicalEyeColors: ['blue'],
    distinctiveFeatures: ['color points', 'slender body', 'large ears']
  }
};

function validateBreedFeatures(
  breed: string,
  requestedFeatures: { furColor?: string; eyeColor?: string }
): { valid: boolean; warnings: string[] } {
  
  const characteristics = BREED_DATABASE[breed];
  if (!characteristics) {
    return { valid: true, warnings: ['Unknown breed - cannot validate'] };
  }

  const warnings: string[] = [];

  if (requestedFeatures.furColor && 
      !characteristics.typicalFurColors.some(c => 
        requestedFeatures.furColor.toLowerCase().includes(c)
      )) {
    warnings.push(
      `Warning: ${requestedFeatures.furColor} is not typical for ${breed}. ` +
      `Typical colors: ${characteristics.typicalFurColors.join(', ')}`
    );
  }

  if (requestedFeatures.eyeColor && 
      !characteristics.typicalEyeColors.some(c => 
        requestedFeatures.eyeColor.toLowerCase().includes(c)
      )) {
    warnings.push(
      `Warning: ${requestedFeatures.eyeColor} eyes are not typical for ${breed}. ` +
      `Typical colors: ${characteristics.typicalEyeColors.join(', ')}`
    );
  }

  return {
    valid: warnings.length === 0,
    warnings
  };
}

// 使用例
const validation = validateBreedFeatures('golden_retriever', {
  furColor: 'black',
  eyeColor: 'blue'
});

if (!validation.valid) {
  console.warn(validation.warnings);
  // ユーザーに確認を求める、または自動的に修正
}

2画像入力の活用テクニック

Nano Banana Proは2枚の動物写真を組み合わせられます。これは非常に強力な機能です。

基本構造

interface TwoAnimalImagePrompt {
  baseImage: string;      // 画像1: 体型・ポーズを保持したいベース
  referenceImage: string; // 画像2: 毛色・模様の参照元
  prompt: string;
  negativePrompt: string;
}

ユースケース1: 毛色・模様の転写

シナリオ: 画像1の犬に、画像2の毛色を適用したい

const config: TwoAnimalImagePrompt = {
  baseImage: "my_dog.jpg",
  referenceImage: "desired_fur_pattern.jpg",
  prompt: `
    apply fur color and pattern from reference image to target dog,
    preserve exact anatomy of original image: 
    body shape, facial features, pose, eye color, ear shape,
    transfer only fur coloration and pattern,
    maintain original proportions and structure,
    photorealistic result, 8k quality
  `,
  negativePrompt: `
    anatomical changes, different breed, altered body structure,
    extra limbs, missing body parts, changed facial features,
    distorted proportions, mutated
  `
};

ユースケース2: 品種特徴の組み合わせ

シナリオ: 画像1の猫に、画像2の目の色を適用

const config: TwoAnimalImagePrompt = {
  baseImage: "my_cat.jpg",
  referenceImage: "blue_eyed_cat.jpg",
  prompt: `
    apply eye color from reference image to target cat,
    preserve all other features from original image:
    fur color, fur pattern, facial structure, body shape, pose, ears,
    transfer only eye color, maintain natural feline appearance,
    photorealistic, 8k quality
  `,
  negativePrompt: `
    change fur color, change fur pattern, altered face shape,
    different breed, extra eyes, anatomical errors,
    unnatural appearance
  `
};

ユースケース3: 背景のスタイル転写

シナリオ: 画像1の動物を、画像2のような背景に配置

const config: TwoAnimalImagePrompt = {
  baseImage: "pet_photo.jpg",
  referenceImage: "studio_background.jpg",
  prompt: `
    transfer background style from reference image,
    preserve animal completely from original image:
    all body features, fur color, pose, facial expression,
    apply only background lighting and atmosphere from reference,
    seamless integration, professional pet photography, 8k quality
  `,
  negativePrompt: `
    change animal features, alter animal appearance,
    modify fur color, change pose, anatomical changes,
    blurry animal, distorted pet
  `
};

重要な注意点

// ❌ 悪い例: 曖昧な指示
const badPrompt = "make image 1 look like image 2";

// ✅ 良い例: 転写内容を明確に指定
const goodPrompt = `
use reference image for: fur color and pattern only
preserve from base image: body shape, facial features, pose, eye color, all anatomical structure
transfer method: surface coloration only, no structural changes
`;

実装例

class TwoAnimalImagePromptBuilder {
  private baseImage: string = '';
  private referenceImage: string = '';
  private transferFeatures: string[] = [];
  private preserveFeatures: string[] = [];

  setBaseImage(path: string): this {
    this.baseImage = path;
    return this;
  }

  setReferenceImage(path: string): this {
    this.referenceImage = path;
    return this;
  }

  transferFrom(features: string[]): this {
    this.transferFeatures = features;
    return this;
  }

  preserveFrom(features: string[]): this {
    this.preserveFeatures = features;
    return this;
  }

  build(): TwoAnimalImagePrompt {
    const prompt = `
      transfer ${this.transferFeatures.join(', ')} from reference image,
      preserve ${this.preserveFeatures.join(', ')} from base image exactly,
      maintain anatomical accuracy, no structural modifications,
      photorealistic, 8k quality
    `;

    const negativePrompt = `
      anatomical changes, extra limbs, missing body parts,
      altered ${this.preserveFeatures.join(', ')},
      distorted proportions, mutated, unnatural appearance
    `;

    return {
      baseImage: this.baseImage,
      referenceImage: this.referenceImage,
      prompt: prompt.trim(),
      negativePrompt: negativePrompt.trim()
    };
  }
}

// 使用例
const twoImageConfig = new TwoAnimalImagePromptBuilder()
  .setBaseImage('original_dog.jpg')
  .setReferenceImage('golden_fur.jpg')
  .transferFrom(['fur color', 'fur texture'])
  .preserveFrom(['body shape', 'facial features', 'pose', 'eye color', 'ear shape'])
  .build();

品質を上げる実践Tips

Tip 1: 解像度・品質キーワードを常に追加

const QUALITY_KEYWORDS = [
  'professional pet photography',
  '8k ultra detailed',
  'sharp focus on eyes',  // 動物写真では目にフォーカス
  'award winning photography',
  'high definition',
  'crisp fur details'  // 毛並みの詳細
];

function addQualityKeywords(prompt: string): string {
  return `${prompt}, ${QUALITY_KEYWORDS.join(', ')}`;
}

Tip 2: 照明を動物撮影に最適化

const ANIMAL_LIGHTING_PRESETS = {
  natural_outdoor: 'soft natural daylight, outdoor lighting, golden hour warmth',
  studio_professional: 'professional studio lighting, soft diffused light, catch light in eyes',
  indoor_natural: 'natural window light, soft indoor illumination, warm ambient',
  dramatic: 'dramatic side lighting, rim light highlighting fur, deep shadows'
};

function withAnimalLighting(
  prompt: string, 
  lighting: keyof typeof ANIMAL_LIGHTING_PRESETS
): string {
  return `${prompt}, ${ANIMAL_LIGHTING_PRESETS[lighting]}`;
}

Tip 3: 毛並み・質感を具体的に

// ❌ 悪い例
const vague = "fluffy dog";

// ✅ 良い例
const specific = "golden retriever with thick double coat, individual hair strands visible, natural fur flow, soft and silky texture";

// テンプレート化
interface FurSpec {
  type: string;      // 毛の種類
  length: string;    // 長さ
  texture: string;   // 質感
  pattern?: string;  // 模様
}

function describeFur(spec: FurSpec): string {
  const parts = [spec.type, spec.length, spec.texture];
  if (spec.pattern) parts.push(spec.pattern);
  parts.push('individual hair strands visible', 'natural fur flow');
  return parts.join(', ');
}

// 使用例
const goldenRetrieverFur = describeFur({
  type: 'double coat',
  length: 'medium to long',
  texture: 'soft and silky',
  pattern: 'light golden color'
});

Tip 4: 品種特有の特徴を強調

interface BreedEmphasis {
  breed: string;
  keyFeatures: string[];
}

function emphasizeBreedFeatures(spec: BreedEmphasis): string {
  return `${spec.breed}, distinctive features: ${spec.keyFeatures.join(', ')}`;
}

// 使用例
const huskyEmphasis = emphasizeBreedFeatures({
  breed: 'siberian husky',
  keyFeatures: [
    'striking blue eyes',
    'thick double coat',
    'pointed erect ears',
    'bushy curled tail',
    'distinctive facial markings'
  ]
});

Tip 5: 表情・感情を自然に表現

// ❌ 避けるべき表現(人間的すぎる)
const unnatural = [
  'smiling', 'laughing', 'grinning',
  'winking', 'crying', 'frowning'
];

// ✅ 自然な動物の表情
const NATURAL_EXPRESSIONS = {
  happy: 'alert and bright-eyed, relaxed posture, open mouth panting gently',
  curious: 'head tilted, ears perked up, focused gaze, attentive expression',
  calm: 'relaxed facial muscles, soft eyes, peaceful demeanor',
  playful: 'energetic stance, playful bow position, bright alert eyes',
  content: 'soft relaxed features, gentle expression, calm breathing'
};

function getNaturalExpression(mood: keyof typeof NATURAL_EXPRESSIONS): string {
  return NATURAL_EXPRESSIONS[mood];
}

Tip 6: バッチテストで最適化

async function findOptimalAnimalPrompt(
  baseImage: string,
  variations: string[]
): Promise<{ prompt: string; score: number }> {
  
  const results = await Promise.all(
    variations.map(async (prompt) => {
      const image = await generateImage({ baseImage, prompt });
      
      // 解剖学的精度チェック + 品質評価
      const anatomyCheck = await validateAnatomy(image);
      const qualityScore = await evaluateQuality(image);
      
      const score = anatomyCheck.isValid ? qualityScore : 0;
      
      return { prompt, score, image, anatomyIssues: anatomyCheck.issues };
    })
  );

  // 解剖学的に正しく、かつ最高品質のプロンプトを返す
  const validResults = results.filter(r => r.score > 0);
  
  if (validResults.length === 0) {
    throw new Error('All variations produced anatomically incorrect results');
  }
  
  return validResults.reduce((best, current) => 
    current.score > best.score ? current : best
  );
}

// 使用例
const variations = [
  "golden retriever, change fur to white, preserve all features",
  "golden retriever puppy, pure white fur, maintain original: eyes, face, body shape, pose",
  "golden retriever with snow white coat, preserve: brown eyes, facial structure, body proportions, sitting pose"
];

const optimal = await findOptimalAnimalPrompt("dog.jpg", variations);
console.log(`Best prompt: ${optimal.prompt} (score: ${optimal.score})`);

Tip 7: 解剖学的検証の自動化

interface AnatomyCheckResult {
  isValid: boolean;
  issues: string[];
  confidence: number;
}

async function validateAnatomy(imagePath: string): Promise<AnatomyCheckResult> {
  // 実際には画像解析AIを使用
  // ここではサンプル実装
  
  const checks = {
    legCount: await countLegs(imagePath),  // 4本であるべき
    tailCount: await countTails(imagePath), // 1本であるべき
    eyeCount: await countEyes(imagePath),   // 2つであるべき
    proportions: await checkProportions(imagePath)
  };

  const issues: string[] = [];
  
  if (checks.legCount !== 4) {
    issues.push(`Incorrect leg count: ${checks.legCount} (expected 4)`);
  }
  if (checks.tailCount !== 1) {
    issues.push(`Incorrect tail count: ${checks.tailCount} (expected 1)`);
  }
  if (checks.eyeCount !== 2) {
    issues.push(`Incorrect eye count: ${checks.eyeCount} (expected 2)`);
  }
  if (!checks.proportions.isNatural) {
    issues.push('Unnatural body proportions detected');
  }

  return {
    isValid: issues.length === 0,
    issues,
    confidence: calculateConfidence(checks)
  };
}

Tip 8: エラーハンドリングとリトライ(動物特化)

async function robustAnimalGenerate(
  config: AnimalImageConfig,
  maxRetries: number = 3
): Promise<string> {
  
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const result = await generateImage(config);
      
      // 解剖学的検証
      const anatomyCheck = await validateAnatomy(result);
      
      if (!anatomyCheck.isValid) {
        console.warn(`Attempt ${attempt}: Anatomy issues`, anatomyCheck.issues);
        
        // 解剖学的問題に対する自動修正
        config = adjustForAnatomyIssues(config, anatomyCheck.issues);
        continue;
      }
      
      // 品質チェック
      const qualityCheck = await validateImageQuality(result);
      
      if (qualityCheck.isAcceptable) {
        return result;
      }
      
      console.warn(`Attempt ${attempt}: Quality issues`, qualityCheck.issues);
      config = adjustForQualityIssues(config, qualityCheck.issues);
      
    } catch (error) {
      console.error(`Attempt ${attempt} failed:`, error);
      
      if (attempt === maxRetries) {
        throw new Error(`Failed after ${maxRetries} attempts`);
      }
      
      await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
    }
  }
  
  throw new Error('Should not reach here');
}

function adjustForAnatomyIssues(
  config: AnimalImageConfig,
  issues: string[]
): AnimalImageConfig {
  
  let adjustedPrompt = config.prompt;
  let adjustedNegative = config.negativePrompt;
  
  if (issues.some(i => i.includes('leg count'))) {
    adjustedPrompt += ', exactly 4 legs, correct canine anatomy';
    adjustedNegative += ', extra legs, missing legs';
  }
  
  if (issues.some(i => i.includes('proportions'))) {
    adjustedPrompt += ', natural body proportions, anatomically correct';
    adjustedNegative += ', distorted proportions, unnatural anatomy';
  }
  
  // strength を下げて、元画像の解剖学的構造を強く保持
  const newStrength = Math.max(0.3, (config.strength || 0.7) - 0.1);
  
  return {
    ...config,
    prompt: adjustedPrompt,
    negativePrompt: adjustedNegative,
    strength: newStrength
  };
}

まとめ:動物画像生成の10のチェックリスト

プロンプトを作成する際、以下をチェックしてください:

✅ 必須項目

  1. [ ] 品種・種が明記されている

    • ❌ "dog"
    • ✅ "golden retriever, 3 months old puppy"
  2. [ ] 解剖学的精度の保護がある

    • 必須: correct anatomy, proper proportions
  3. [ ] 保持すべき特徴が列挙されている

    • 最低限: eye color, facial features, body structure
  4. [ ] ネガティブプロンプトに解剖学的異常防止がある

    • extra legs, extra tails, missing limbs, mutated
  5. [ ] 品質指定がある

    • professional pet photography, 8k quality

✅ 推奨項目

  1. [ ] 人間的表現を避けている

    • smiling → alert and friendly expression
  2. [ ] 毛並みの質感が具体的

    • fluffy → soft double coat, individual strands visible
  3. [ ] 照明条件が指定されている

    • soft natural daylight, catch light in eyes
  4. [ ] 品種特徴との矛盾がない

    • golden retriever + blue eyes = 矛盾(要チェック)
  5. [ ] 段階的アプローチを計画済み

    • 複雑な変更は分割実行

最後に

Nano Banana Proで動物画像を扱う際の最大の課題は解剖学的精度の維持です。

成功の鍵は:

  • 動物の解剖学的構造を常に意識する
  • 品種特有の特徴を理解し尊重する
  • 人間的な表現を避け、自然な動物の姿を追求する
  • 段階的アプローチで異常を早期発見
  • 継続的な検証と最適化

このガイドで紹介したテクニックを実践し、あなたのプロダクトに最適な動物画像生成プロンプトライブラリを構築してください。


0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?