Negative Prompt ile İstemediğin Unsurları Görselden Çıkarma
Stable Diffusion ile çalışırken bir noktada fark ediyorsun: prompt ne kadar iyi yazılırsa yazılsın, istemediğin şeyler görüntüye sızıyor. Fazladan eller, bozuk yüzler, aşırı doygun renkler, gereksiz arka plan detayları… İşte tam bu noktada negative prompt devreye giriyor ve modelin dikkatini “bunları üretme” yönünde yönlendiriyor. Bu yazıda negative prompt’u sadece teorik olarak değil, gerçek senaryolarla, API entegrasyonuyla ve otomasyon betikleriyle birlikte ele alacağız.
Negative Prompt Nedir ve Nasıl Çalışır
Stable Diffusion, görüntü üretirken hem pozitif hem de negatif prompt’u birlikte değerlendirir. Model, pozitif prompt’ta belirttiğin şeylere yaklaşmaya, negatif prompt’ta belirttiğin şeylere ise uzaklaşmaya çalışır. Bu, CFG (Classifier-Free Guidance) mekanizması sayesinde gerçekleşir.
Teknik olarak bakarsak: model her adımda pozitif ve negatif yönde iki tahmin üretir. Bu iki tahmin arasındaki fark, CFG scale değeriyle çarpılarak nihai yönlendirme hesaplanır. CFG scale ne kadar yüksekse, negative prompt o kadar güçlü etki eder.
# AUTOMATIC1111 Web UI'yi başlatırken CFG değerini kontrol et
# webui-user.sh içindeki ayarlar
export COMMANDLINE_ARGS="--api --listen --port 7860 --no-half-vae"
Peki bu bize ne kazandırıyor? Eğitilmiş bir modelin “varsayılan davranışlarını” override etme imkanı. Model normalde belirli bir estetik yönelime sahiptir. Negatif prompt ile bu yönelimi kırabilirsin.
Temel Negatif Prompt Yapısı
Başlangıç için her görüntü üretim görevinde kullanabileceğin evrensel bir negatif prompt bloğu oluşturmak mantıklı. Bunu bir “base template” olarak düşün.
# negative_prompt_base.txt dosyası oluştur
cat > ~/sd_prompts/negative_base.txt << 'EOF'
ugly, deformed, disfigured, poor details, bad anatomy, wrong anatomy,
extra limb, missing limb, floating limbs, disconnected limbs, mutation,
mutated, disgusting, blurry, watermark, signature, text, jpeg artifacts,
low quality, worst quality, bad quality, normal quality, lowres,
extra fingers, fewer fingers, missing fingers, fused fingers
EOF
Bu listedeki her maddenin bir amacı var:
- ugly, deformed: Genel estetik kalite düşüklüğünü önler
- bad anatomy: Vücut orantılarındaki bozuklukları engeller
- extra limb, missing limb: Fazla veya eksik uzuv sorununu çözer
- watermark, signature, text: Eğitim verisinden gelen istem dışı metinleri bastırır
- jpeg artifacts: Düşük kalite sıkıştırma izlerini azaltır
- lowres, worst quality: Kalite tokenlarını negatif yönde kullanır
Senaryo 1: Portre Fotoğraflarında Yüz Bozulmalarını Önleme
Portre üretiminde en sık karşılaşılan sorun yüz anatomisi. Özellikle düşük çözünürlük veya yüksek step sayısında yüzler garip bir hal alabilir.
#!/usr/bin/env python3
# portrait_generator.py - API üzerinden portre üretimi
import requests
import base64
import json
from datetime import datetime
API_URL = "http://localhost:7860"
def generate_portrait(positive_prompt, output_dir="/tmp/portraits"):
negative_prompt = (
"ugly, deformed, bad anatomy, bad face, bad hands, "
"extra fingers, fewer fingers, missing fingers, fused fingers, "
"too many fingers, long neck, bad proportions, gross proportions, "
"malformed limbs, missing arms, missing legs, extra arms, extra legs, "
"mutated hands, poorly drawn hands, poorly drawn face, mutation, "
"deformed, blurry, dehydrated, disfigured, extra limbs, "
"cloned face, out of frame, ugly, duplicate, morbid, mutilated, "
"poorly drawn, gross proportions, watermark, text, signature"
)
payload = {
"prompt": positive_prompt,
"negative_prompt": negative_prompt,
"steps": 30,
"cfg_scale": 7.5,
"width": 512,
"height": 768,
"sampler_name": "DPM++ 2M Karras",
"restore_faces": True,
"n_iter": 1,
"batch_size": 1
}
response = requests.post(f"{API_URL}/sdapi/v1/txt2img", json=payload)
if response.status_code == 200:
result = response.json()
img_data = base64.b64decode(result["images"][0])
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"{output_dir}/portrait_{timestamp}.png"
with open(filename, "wb") as f:
f.write(img_data)
print(f"Görüntü kaydedildi: {filename}")
return filename
else:
print(f"Hata: {response.status_code}")
return None
if __name__ == "__main__":
prompt = "professional headshot, 35mm portrait, sharp focus, studio lighting"
generate_portrait(prompt)
Burada dikkat edilmesi gereken nokta: restore_faces: True parametresi yüz düzeltme modelini (GFPGAN veya CodeFormer) devreye soksa da, negative prompt ile problemi kaynakta bastırmak çok daha verimli sonuç veriyor.
Senaryo 2: Mimari ve İç Mekan Görsellerinde Arka Plan Kontrolü
Bir emlak firması için iç mekan görseli ürettiğini düşün. Gerçekçi görünmesi gerekiyor, sürrealist unsurlar istemiyorsun, fazladan mobilya ya da kalabalık bir kompozisyon da olmasın istiyorsun.
#!/bin/bash
# batch_interior.sh - Toplu iç mekan görseli üretimi
ROOMS=("living room" "bedroom" "kitchen" "bathroom" "office")
API_URL="http://localhost:7860/sdapi/v1/txt2img"
OUTPUT_DIR="/var/www/html/property/images"
NEGATIVE_BASE="cartoon, anime, illustration, painting, drawing, unrealistic,
distorted perspective, fisheye lens distortion, too many furniture pieces,
cluttered, messy, dirty, dark shadows, overexposed, underexposed,
blurry, out of focus, low quality, watermark, text, signature,
people, person, human figure, extra windows, floating objects"
mkdir -p "$OUTPUT_DIR"
for room in "${ROOMS[@]}"; do
echo "Üretiliyor: $room"
POSITIVE="modern ${room}, clean interior design, natural lighting,
minimalist, high quality photography, 8k resolution, photorealistic"
PAYLOAD=$(cat <<JSON
{
"prompt": "${POSITIVE}",
"negative_prompt": "${NEGATIVE_BASE}",
"steps": 35,
"cfg_scale": 8,
"width": 1024,
"height": 768,
"sampler_name": "DPM++ SDE Karras"
}
JSON
)
curl -s -X POST "$API_URL"
-H "Content-Type: application/json"
-d "$PAYLOAD" |
python3 -c "
import sys, json, base64
data = json.load(sys.stdin)
img = base64.b64decode(data['images'][0])
with open('${OUTPUT_DIR}/${room// /_}.png', 'wb') as f:
f.write(img)
print('Kaydedildi: ${room}')
"
sleep 2
done
echo "Tum gorseller uretildi: $OUTPUT_DIR"
Negatif Prompt Ağırlıklandırma
AUTOMATIC1111 ve ComfyUI, prompt içinde parantez kullanarak ağırlık belirlemeyi destekler. Bu, bazı negatif unsurları diğerlerinden daha güçlü bastırmak için kritik bir özellik.
# Ağırlıklı negative prompt örnekleri
# Standart sözdizimi: (kelime:ağırlık)
# Varsayılan ağırlık 1.0
# 1.0'dan büyük = daha güçlü etki
# 1.0'dan küçük = daha zayıf etki
WEIGHTED_NEGATIVE="(worst quality:1.4), (low quality:1.4), (normal quality:1.2),
(blurry:1.2), (extra fingers:1.5), (fewer fingers:1.5),
(bad anatomy:1.3), text, watermark, (deformed:1.3)"
Ağırlıkları şu şekilde düşün:
- 1.0 – 1.2 arası: Hafif bastırma, model hala biraz bu yönde gidebilir
- 1.2 – 1.5 arası: Güçlü bastırma, çoğu durumda etkili
- 1.5 üzeri: Çok agresif bastırma, bazen artefakta neden olabilir
- 2.0 ve üzeri: Genellikle önerilmez, görüntü kalitesini bozabilir
Senaryo 3: Logo ve Grafik Tasarım Üretiminde Metin Bastırma
Stable Diffusion görüntülere rastgele metin veya sahte yazılar ekleyebilir. Logo tasarımı ya da grafik üretiminde bu ciddi bir sorun. Özellikle eğitim verisinden gelen watermark kalıpları rahatsız edici olabiliyor.
#!/usr/bin/env python3
# logo_generator.py - Metin artefaktlarından temiz logo üretimi
import requests
import base64
import os
import sys
class LogoGenerator:
def __init__(self, api_url="http://localhost:7860"):
self.api_url = api_url
self.text_negative = (
"text, letters, words, writing, typography, font, alphabet, "
"numbers, digits, characters, script, handwriting, caption, "
"watermark, signature, label, title, heading, copyright, "
"trademark, registered symbol, url, website, email address, "
"blurry, noisy, grainy, pixelated, jpeg artifacts, "
"low resolution, bad quality"
)
def generate(self, concept, style="flat design", colors="blue and white"):
positive = (
f"logo design, {concept}, {style}, {colors} color scheme, "
f"vector style, clean lines, professional, modern, minimalist, "
f"white background, high contrast, crisp edges, scalable design"
)
payload = {
"prompt": positive,
"negative_prompt": self.text_negative,
"steps": 40,
"cfg_scale": 9,
"width": 512,
"height": 512,
"sampler_name": "Euler a",
"seed": -1
}
response = requests.post(
f"{self.api_url}/sdapi/v1/txt2img",
json=payload,
timeout=120
)
if response.status_code != 200:
raise Exception(f"API hatasi: {response.status_code}")
data = response.json()
return base64.b64decode(data["images"][0])
def save(self, image_data, filename):
os.makedirs(os.path.dirname(filename), exist_ok=True)
with open(filename, "wb") as f:
f.write(image_data)
print(f"Logo kaydedildi: {filename}")
if __name__ == "__main__":
gen = LogoGenerator()
logos = [
("mountain hiking company", "geometric", "green and brown"),
("tech startup", "flat design", "purple and cyan"),
("coffee shop", "vintage", "brown and cream")
]
for concept, style, colors in logos:
img_data = gen.generate(concept, style, colors)
filename = f"/tmp/logos/{concept.replace(' ', '_')}.png"
gen.save(img_data, filename)
ComfyUI ile Negative Prompt Workflow
AUTOMATIC1111 dışında ComfyUI kullanıyorsan, negative prompt’u API üzerinden JSON workflow ile yönetiyorsun. Bu daha programatik bir kontrol sağlıyor.
#!/bin/bash
# comfyui_negative_test.sh - ComfyUI API ile negative prompt testi
COMFY_URL="http://localhost:8188"
# Workflow JSON'ı hazırla
cat > /tmp/negative_workflow.json << 'WORKFLOW'
{
"6": {
"class_type": "CLIPTextEncode",
"inputs": {
"text": "beautiful landscape, mountains, sunset, photorealistic",
"clip": ["4", 1]
}
},
"7": {
"class_type": "CLIPTextEncode",
"inputs": {
"text": "ugly, deformed, blurry, watermark, text, bad quality, cartoon",
"clip": ["4", 1]
}
},
"3": {
"class_type": "KSampler",
"inputs": {
"seed": 42,
"steps": 30,
"cfg": 7.5,
"sampler_name": "dpmpp_2m",
"scheduler": "karras",
"denoise": 1.0,
"model": ["4", 0],
"positive": ["6", 0],
"negative": ["7", 0],
"latent_image": ["5", 0]
}
}
}
WORKFLOW
# Workflow'u kuyruğa ekle
curl -s -X POST "$COMFY_URL/prompt"
-H "Content-Type: application/json"
-d "{"prompt": $(cat /tmp/negative_workflow.json)}" |
python3 -m json.tool
echo "Workflow ComfyUI kuyruğuna eklendi"
Stil Bazlı Negatif Prompt Kütüphanesi
Farklı kullanım senaryoları için önceden hazırlanmış negative prompt setleri tutmak, ekip çalışmasında tutarlılık sağlar. Bunu bir konfigürasyon sistemi olarak yönetebilirsin.
#!/usr/bin/env python3
# negative_library.py - Negative prompt kütüphanesi yönetimi
import json
import os
LIBRARY_PATH = "/etc/sd_prompts/negative_library.json"
DEFAULT_LIBRARY = {
"universal": (
"ugly, deformed, disfigured, poor details, bad anatomy, "
"blurry, watermark, signature, text, jpeg artifacts, "
"low quality, worst quality, lowres"
),
"portrait": (
"ugly, deformed, bad anatomy, bad face, extra fingers, "
"fewer fingers, missing fingers, fused fingers, too many fingers, "
"bad proportions, poorly drawn face, poorly drawn hands, "
"mutation, deformed, watermark, text, signature, cloned face, "
"out of frame, duplicate, morbid, mutilated"
),
"landscape": (
"ugly, deformed, blurry, watermark, text, signature, "
"overexposed, underexposed, distorted, fisheye, "
"artificial, cartoon, illustration, painting, anime, "
"people, person, human figure, building in natural scenes"
),
"product": (
"ugly, deformed, blurry, watermark, text, signature, "
"shadow issues, bad lighting, overexposed, underexposed, "
"background clutter, multiple items, reflections, glare, "
"jpeg artifacts, low quality, distorted perspective"
),
"anime": (
"ugly, deformed, bad anatomy, extra fingers, fewer fingers, "
"bad proportions, poorly drawn, low quality, worst quality, "
"watermark, text, blurry, out of focus, nsfw, "
"western style, realistic, photographic"
)
}
def load_library():
if os.path.exists(LIBRARY_PATH):
with open(LIBRARY_PATH, "r") as f:
return json.load(f)
return DEFAULT_LIBRARY
def get_negative_prompt(style, custom_additions=""):
library = load_library()
base = library.get(style, library["universal"])
if custom_additions:
return f"{base}, {custom_additions}"
return base
def save_library(library):
os.makedirs(os.path.dirname(LIBRARY_PATH), exist_ok=True)
with open(LIBRARY_PATH, "w") as f:
json.dump(library, f, indent=2, ensure_ascii=False)
print(f"Kutuphane kaydedildi: {LIBRARY_PATH}")
if __name__ == "__main__":
# Test
for style in ["universal", "portrait", "landscape", "product"]:
prompt = get_negative_prompt(style)
print(f"n[{style.upper()}]")
print(prompt[:100] + "...")
save_library(DEFAULT_LIBRARY)
CFG Scale ile Negative Prompt Etkileşimi
Negative prompt’u kullanırken CFG scale değerini doğru ayarlamak kritik. Düşük CFG = zayıf negatif etki, yüksek CFG = aşırı kısıtlama.
#!/bin/bash
# cfg_test.sh - Farklı CFG değerleriyle negative prompt testi
API_URL="http://localhost:7860/sdapi/v1/txt2img"
POSITIVE="professional product photo, coffee mug, clean white background"
NEGATIVE="text, watermark, blurry, bad quality, ugly, deformed"
OUTPUT_DIR="/tmp/cfg_tests"
mkdir -p "$OUTPUT_DIR"
for CFG in 4 6 7.5 9 11 13; do
echo "CFG $CFG test ediliyor..."
curl -s -X POST "$API_URL"
-H "Content-Type: application/json"
-d "{
"prompt": "$POSITIVE",
"negative_prompt": "$NEGATIVE",
"steps": 25,
"cfg_scale": $CFG,
"width": 512,
"height": 512,
"seed": 12345
}" | python3 -c "
import sys, json, base64
data = json.load(sys.stdin)
img = base64.b64decode(data['images'][0])
with open('${OUTPUT_DIR}/cfg_${CFG/./p}.png', 'wb') as f:
f.write(img)
print('CFG ${CFG} kaydedildi')
"
done
echo "Tum CFG testleri tamamlandi: $OUTPUT_DIR"
CFG değerleri hakkında pratik bilgi:
- CFG 4-5: Negative prompt zayıf etki eder, model daha özgür
- CFG 6-7.5: Dengeli, çoğu senaryo için başlangıç noktası
- CFG 8-9: Negative prompt etkisi belirgin, önerilen portre ve ürün için
- CFG 10-12: Agresif bastırma, bazen renk doygunluğu artar
- CFG 13 ve üzeri: Genellikle görüntü kalitesini düşürür
Yaygın Hatalar ve Çözümleri
Negative prompt kullanırken sık yapılan hatalar var. Bunları bilmek zaman kazandırır.
Çelişkili negative prompt: Pozitif prompt’ta istediğin bir şeyi negatife de eklersen model kararsız kalır. “painting” istiyorsan negativede “illustration, painting” olmamalı.
Aşırı uzun negative prompt: 77 token sınırı var (CLIP tokenizer). Bunu aşarsan son kısımlar etkisiz kalır. Hangi unsurların gerçekten önemli olduğunu seç.
Yanlış ağırlıklandırma: Her şeye yüksek ağırlık vermek paradoksal sonuçlar üretir. Ağırlıkları seçici kullan.
# Token sayısını kontrol et
# AUTOMATIC1111 Web UI arayüzünde token sayacı var
# API üzerinden kontrol için:
curl -s -X POST "http://localhost:7860/sdapi/v1/tokencount"
-H "Content-Type: application/json"
-d '{
"prompt": "ugly, deformed, bad anatomy, watermark, text, signature, blurry"
}' | python3 -c "
import sys, json
data = json.load(sys.stdin)
print(f'Token sayisi: {data["count"]}')
"
Görüntü Analizi ile Negative Prompt Geliştirme
Üretilen görüntülerdeki sorunları otomatik tespit edip negative prompt’u iyileştiren basit bir sistem kurabilirsin.
#!/usr/bin/env python3
# analyze_and_improve.py - Görüntü analizi tabanlı negative prompt iyileştirme
import requests
import base64
import json
from pathlib import Path
def encode_image(image_path):
with open(image_path, "rb") as f:
return base64.b64encode(f.read()).decode()
def analyze_issues(image_path, api_url="http://localhost:7860"):
"""
img2img ile görüntüdeki sorunları tespit etmeye çalış
Gerçek uygulamada bir vision model kullanman daha iyi olur
"""
img_b64 = encode_image(image_path)
# Interrogate ile görüntüyü analiz et
response = requests.post(
f"{api_url}/sdapi/v1/interrogate",
json={
"image": img_b64,
"model": "clip"
}
)
if response.status_code == 200:
caption = response.json().get("caption", "")
print(f"Goruntu analizi: {caption}")
return caption
return ""
def suggest_negative_improvements(caption, current_negative):
"""Analiz sonucuna gore negative prompt onerisi uret"""
suggestions = []
problem_keywords = {
"blurry": "blurry, out of focus, soft focus",
"dark": "underexposed, dark, dimly lit",
"bright": "overexposed, blown out highlights",
"distorted": "distorted, warped, skewed",
"noisy": "noisy, grainy, film grain",
"cartoon": "cartoon, animated, illustrated"
}
for keyword, negative_addition in problem_keywords.items():
if keyword in caption.lower():
if negative_addition not in current_negative:
suggestions.append(negative_addition)
return suggestions
if __name__ == "__main__":
test_image = "/tmp/test_output.png"
current_neg = "ugly, deformed, watermark"
if Path(test_image).exists():
caption = analyze_issues(test_image)
improvements = suggest_negative_improvements(caption, current_neg)
if improvements:
print(f"nOnerilen eklemeler:")
for imp in improvements:
print(f" + {imp}")
updated_neg = current_neg + ", " + ", ".join(improvements)
print(f"nGuncel negative prompt:n{updated_neg}")
Sonuç
Negative prompt, Stable Diffusion iş akışının en hafife alınan ama en etkili parçalarından biri. Basit bir “ugly, deformed” listesiyle başlamak yeterli gibi görünse de, gerçek prodüksiyon ortamlarında durum çok daha nüanslı. Portre üretimi için farklı, mimari görsel için farklı, logo için farklı yaklaşımlar gerekiyor.
Bu yazıda anlattıklarımı özetlemek gerekirse: evrensel bir base negative prompt oluştur, bunu bir kütüphanede sakla, CFG scale ile ilişkisini anla, token limitini aşma ve ağırlıklandırmayı seçici kullan. Özellikle API entegrasyonu üzerinden çalışıyorsan, negative prompt’u hardcode etmek yerine konfigurasyon dosyasından çekmek uzun vadede bakım kolaylığı sağlıyor.
Pratik tavsiye: yeni bir model veya kullanım senaryosuyla çalışmaya başlarken önce negatif promptsuz bir görüntü üret, sorunları tespit et, sonra o sorunları hedefleyen negatif tokenlar ekle. Körü körüne kopyala yapıştır yaklaşımı yerine, üretim hedefine özel negatif prompt seti oluşturmak kaliteyi ciddi şekilde artırıyor.
