Iterative Image Prompt Refinement
Analyzing generated images and adjusting prompts systematically.
Iterative Image Prompt Refinement is a free AI Prompt Engineering lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the AI Prompt Engineering learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Why Iterative Refinement?
First-generation image prompts rarely produce the exact result you want. Iterative refinement is a systematic workflow: generate, analyze, identify gaps, adjust the prompt, and regenerate. Each cycle narrows the gap between intent and output.
The Refinement Loop
The iterative refinement loop has four steps: Generate (create an image from current prompt), Analyze (identify what is wrong or missing), Adjust (modify the prompt to address issues), and Regenerate. Repeat until satisfied or stopped by budget/time constraints.
class PromptRefinementSession:
def __init__(self, initial_prompt, negative_prompt=''):
self.history = []
self.current_prompt = initial_prompt
self.current_negative = negative_prompt
self.iteration = 0
def record_iteration(self, issues_found, adjustments_made):
self.history.append({
'iteration': self.iteration,
'prompt': self.current_prompt,
'negative': self.current_negative,
'issues': issues_found,
'adjustments': adjustments_made
})
self.iteration += 1
def update_prompt(self, new_prompt, new_negative=None):
self.current_prompt = new_prompt
if new_negative is not None:
self.current_negative = new_negative
def get_history(self):
return self.history
# Usage
session = PromptRefinementSession(
initial_prompt='a woman walking in a rainy city at night',
negative_prompt='blurry, low quality'
)
print('Refinement session started. Iteration 0.')Analyzing a Generated Image: Issue Taxonomy
When analyzing what went wrong, categorize issues by type. This directs which part of the prompt needs adjustment — adding detail, removing conflict, or adjusting weights.
ISSUE_TAXONOMY = {
'Subject issues': [
'Subject missing or wrong species/gender/age',
'Key detail absent (clothing, expression, props)',
'Pose or action incorrect',
'Background wrong or distracting'
],
'Style issues': [
'Wrong art style (photo when painting expected)',
'Too stylized/not stylized enough',
'Style inconsistency (mixing styles incoherently)'
],
'Lighting issues': [
'Wrong time of day',
'Too dark or too bright',
'Shadows wrong direction',
'Missing dramatic effect'
],
'Composition issues': [
'Wrong framing (too close/far)',
'Subject cropped awkwardly',
'Rule of thirds not applied',
'Cluttered vs. desired clean composition'
],
'Quality issues': [
'Blurry or low detail',
'Anatomical distortion (extra fingers)',
'Watermark or text artifact',
'Overexposed/underexposed areas'
]
}
for category, issues in ISSUE_TAXONOMY.items():
print(f'{category}: {issues[0]}')Iteration 1: Before and After
Here is a concrete before/after example showing how identifying issues and adjusting the prompt improves results.
# ITERATION 0: Initial prompt (too vague)
prompt_v0 = 'a woman walking in a rainy city at night'
# Issues found:
# - Style unspecified -> model defaulted to generic illustration
# - Lighting unspecified -> flat even light, no mood
# - No detail on clothing or setting
# - No composition direction
# ITERATION 1: Add style, lighting, detail
prompt_v1 = (
'a young woman in a yellow raincoat walking down '
'a rain-soaked Tokyo street at night, '
'neon signs reflected in puddles, steam rising from grates, '
'cinematic photography style, street photography, '
'warm neon glow, wet pavement reflections, '
'medium shot, slightly low angle, bokeh background'
)
negative_v1 = 'blurry, low quality, watermark, extra fingers, cartoon'
# Remaining issues after v1:
# - Raincoat not yellow (model defaulted to dark colors)
# - Woman facing wrong way
print('V0 length:', len(prompt_v0.split()))
print('V1 length:', len(prompt_v1.split()))
print('Iteration adds: style, lighting, composition, specific details')Iteration 2: Fixing Specific Elements
The second iteration targets the remaining issues precisely — do not rewrite the whole prompt, just address the specific problems found in iteration 1.
# ITERATION 1 issues:
# - Raincoat not yellow (model defaulted to dark)
# - Woman facing wrong way (walking away from camera)
# ITERATION 2: targeted fixes
prompt_v2 = (
'a young woman in a BRIGHT YELLOW raincoat '
'walking TOWARD the camera '
'down a rain-soaked Tokyo street at night, '
'neon signs reflected in puddles, steam rising from grates, '
'face visible, slight smile, carrying groceries, '
'cinematic photography style, street photography, '
'warm neon glow, wet pavement reflections, '
'medium shot, slightly low angle, bokeh background'
)
# Changes made:
# 1. "BRIGHT YELLOW" capitalization + adjective for emphasis
# 2. Added "walking TOWARD the camera" to fix direction
# 3. Added "face visible" to prevent back-to-camera result
# 4. Added specific detail: "carrying groceries, slight smile"
# Best practice: track what you changed and why
changelog = {
'v0_to_v1': 'Added style, lighting, composition, city details',
'v1_to_v2': 'Fixed raincoat color, fixed walking direction, added face constraint'
}
print('Changelog:', changelog)Using Fixed Seeds for Comparison
When comparing prompt variations, use a fixed random seed so the only variable is the prompt change. Without a fixed seed, you cannot tell if output changes are from your prompt edit or from randomness.
import requests
SD_API_URL = 'http://localhost:7860/sdapi/v1/txt2img'
def compare_prompt_versions(prompts_dict, negative='blurry, low quality',
seed=12345, steps=30):
results = {}
for version, prompt in prompts_dict.items():
payload = {
'prompt': prompt,
'negative_prompt': negative,
'seed': seed, # FIXED SEED for fair comparison
'steps': steps,
'cfg_scale': 7,
'width': 512,
'height': 512
}
response = requests.post(SD_API_URL, json=payload)
results[version] = response.json().get('images', [None])[0]
print(f'{version}: generated with seed {seed}')
return results
promptvariants = {
'v0': 'a woman walking in a rainy city at night',
'v1': 'cinematic, rainy Tokyo night, yellow raincoat, neon reflections',
'v2': 'BRIGHT YELLOW raincoat, facing camera, cinematic Tokyo rain night'
}
# compare_prompt_versions(prompt_variants, seed=42)The Subtractive Approach
Sometimes prompts become bloated after many iterations. The subtractive approach starts with a detailed prompt and removes terms one by one to see which ones are actually doing work — and which are adding noise.
# Start with a detailed prompt
full_prompt = (
'young woman, yellow raincoat, Tokyo, rain, neon, night, '
'street photography, cinematic, bokeh, wet pavement, '
'medium shot, warm tones, highly detailed, 8K, masterpiece, '
'award winning, beautiful, stunning, gorgeous'
)
# Remove terms and test if output quality degrades
test_removed = [
'masterpiece, award winning, beautiful, stunning, gorgeous', # quality tokens
'8K, highly detailed', # resolution tokens
'wet pavement', # specific detail
'cinematic', # style term
]
# Results typically show:
# - Generic quality tokens (masterpiece, beautiful) have minimal effect
# - Specific scene details (wet pavement, neon) matter most
# - Remove token: if output unchanged, that term is not contributing
print('Subtractive testing: remove terms and observe impact')
print('Terms that do not change output when removed can be discarded')
print('This produces lean, effective prompts')Refinement for Specific Failure Modes
Common image generation failure modes each have known fixes. Building this knowledge into a systematic checklist accelerates refinement.
FAILURE_FIXES = {
'Extra or deformed fingers': [
'Add to negative: extra fingers, deformed hands, bad anatomy',
'Add to positive: perfect hands, anatomically correct',
'Use inpainting to fix the specific area'
],
'Text artifacts / watermarks': [
'Add to negative: watermark, text, signature, logo',
'Increase CFG scale slightly',
'Use a different model checkpoint'
],
'Wrong style (cartoonish when photo expected)': [
'Add to negative: cartoon, anime, illustration, painted',
'Add to positive: photorealistic, DSLR, film photography',
'Use a photorealism-focused checkpoint'
],
'Background too busy / distracting': [
'Add to positive: simple background, clean background, blurred background',
'Add: shallow depth of field, bokeh background',
'Add to negative: cluttered background, busy background'
],
'Wrong color (model ignores color spec)': [
'Emphasize color: BRIGHT RED (caps), crimson red, deep scarlet',
'Add color to multiple places in prompt',
'Use img2img with a color reference image'
]
}
for failure, fixes in list(FAILURE_FIXES.items())[:3]:
print(f'\nISSUE: {failure}')
for fix in fixes:
print(f' FIX: {fix}')Prompt Versioning for Image Generation
Track prompt versions and their outputs systematically. This creates a reference library for future projects and reveals patterns in what works for specific subjects and styles.
import json
from datetime import datetime
from pathlib import Path
def save_refinement_session(session_name, iterations, output_dir='prompt_sessions'):
Path(output_dir).mkdir(exist_ok=True)
session_data = {
'name': session_name,
'created': datetime.now().isoformat(),
'iterations': iterations
}
filepath = f'{output_dir}/{session_name}.json'
with open(filepath, 'w') as f:
json.dump(session_data, f, indent=2)
print(f'Session saved: {filepath}')
# Example session record
session = [
{
'version': 'v0',
'prompt': 'a woman walking in a rainy city at night',
'issues': ['too vague', 'no style', 'no lighting'],
'seed': 12345
},
{
'version': 'v1',
'prompt': 'young woman, yellow raincoat, Tokyo night rain, neon, cinematic',
'issues': ['raincoat not yellow', 'facing wrong way'],
'seed': 12345
},
{
'version': 'v2',
'prompt': 'BRIGHT YELLOW raincoat, facing camera, Tokyo rain, neon, cinematic',
'issues': [],
'seed': 12345,
'status': 'accepted'
}
]
save_refinement_session('tokyo_rain_woman', session)Refinement Budget: How Many Iterations?
Refinement has diminishing returns. A practical framework for deciding how many iterations to invest based on the use case:
ITERATION_BUDGET_GUIDE = {
'Quick internal mockup': {
'budget': '2-3 iterations',
'goal': 'Good enough to communicate concept',
'stopping_criteria': 'Main subject correct, rough style established'
},
'Marketing asset': {
'budget': '4-6 iterations',
'goal': 'Professional quality, brand-consistent',
'stopping_criteria': 'Color, style, composition match brief exactly'
},
'Hero image / campaign visual': {
'budget': '8-12 iterations + final manual touchup',
'goal': 'Publication quality, no visible artifacts',
'stopping_criteria': 'Zero artifacts, passes creative director review'
},
'Generative art piece': {
'budget': 'Unlimited — creative exploration',
'goal': 'Discover unexpected aesthetic direction',
'stopping_criteria': 'Emotional resonance with creator\'s intent'
}
}
for use_case, guide in ITERATION_BUDGET_GUIDE.items():
print(f'{use_case}: {guide["budget"]}')
print(f' Stop when: {guide["stopping_criteria"]}')
print()LLM-Assisted Prompt Refinement
Use a text LLM to help analyze image problems and suggest prompt improvements. This combines LLM reasoning with image generation to create a meta-refinement loop.
import anthropic
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
REFINEMENT_ADVISOR_PROMPT = '''I am generating an image with this prompt:
Current prompt: {current_prompt}
Negative prompt: {current_negative}
The image has these problems:
{issues}
Suggest specific changes to the prompt that would fix these problems.
Provide:
1. Modified positive prompt (full, ready to use)
2. Modified negative prompt (full, ready to use)
3. Explanation of each change
Keep your changes minimal — only fix the stated issues, do not redesign the image.'''
def get_refinement_suggestion(current_prompt, current_negative, issues):
response = client.messages.create(
model='claude-opus-4-5', max_tokens=1000,
messages=[{'role': 'user', 'content':
REFINEMENT_ADVISOR_PROMPT.format(
current_prompt=current_prompt,
current_negative=current_negative,
issues='\n'.join(f'- {i}' for i in issues)
)}]
)
return response.content[0].text
suggestion = get_refinement_suggestion(
current_prompt='a woman in a raincoat at night',
current_negative='blurry',
issues=['raincoat appears dark not yellow', 'background too busy']
)
print(suggestion[:300], '...')Quick Check
You want to compare two versions of an image prompt to see if your edit improved results. What must you keep constant for a fair comparison?
Iterative Refinement Summary
Iterative image prompt refinement is a systematic, learnable skill:
- The loop: Generate → Analyze → Adjust → Regenerate
- Issue taxonomy: categorize problems as subject, style, lighting, composition, or quality
- Fixed seed: always compare prompt versions on the same seed
- Targeted edits: fix specific identified issues, do not rewrite the whole prompt
- Subtractive approach: remove terms to identify which are actually contributing
- Version tracking: record prompt, issues, and changes for each iteration
- Budget awareness: 2-3 iterations for mockups, 8-12 for hero assets
Frequently asked questions
Is the “Iterative Image Prompt Refinement” lesson free?
Yes — the full text of “Iterative Image Prompt Refinement” is free to read here on the web, and the AI Prompt Engineering course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the AI Prompt Engineering course, upgrade to CoddyKit PRO.
What will I learn in “Iterative Image Prompt Refinement”?
Analyzing generated images and adjusting prompts systematically. You practise AI Prompt Engineering with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start AI Prompt Engineering?
No prior experience is required. AI Prompt Engineering on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Iterative Image Prompt Refinement” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this AI Prompt Engineering lesson?
Yes. Every AI Prompt Engineering lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Anatomy of an Image Generation Prompt
- Style and Artistic Medium Specification
- Negative Prompts and Exclusions
- Iterative Image Prompt Refinement