KI-Bildqualitätsmetriken LPIPS・SSIM Praktischer Leitfaden 2025
Veröffentlicht: 26. Sept. 2025 · Lesezeit: 15 Min. · Von Unified Image Tools Redaktion
Die Bewertung der Bildverarbeitungsqualität entwickelt sich von traditionellen numerischen Metriken zu KI-basierten Bewertungen, die auf menschlicher Wahrnehmung beruhen. Dieser Artikel bietet detaillierte Erklärungen auf Implementierungsebene für die neuesten Bewertungsmethoden einschließlich LPIPS (Learned Perceptual Image Patch Similarity) und SSIM (Structural Similarity Index Measure).
Evolution der KI-Bildqualitätsbewertung
Grenzen traditioneller Methoden
Probleme mit PSNR (Peak Signal-to-Noise Ratio)
- Bewertet nur Unterschiede auf Pixelebene
- Große Abweichung von der menschlichen Wahrnehmung
- Ignoriert strukturelle Ähnlichkeit
- Kann Komprimierungsartefakte nicht angemessen bewerten
Bedarf für neue Ansätze
- Das menschliche Sehsystem nachahmen
- Merkmalsextraktion durch tiefes Lernen
- Quantifizierung der perzeptuellen Ähnlichkeit
- Inhaltsadaptive Bewertung
Interne Links: Bildqualitäts-Budgets und CI-Gates 2025 — Betrieb zur proaktiven Störungsverhinderung, Ultimative Bildkomprimierung-Strategie 2025 — Praktischer Leitfaden zur Performance-Optimierung bei Qualitätserhalt
LPIPS: Lernbasierte Perzeptuelle Metriken
Theoretische Grundlage von LPIPS
LPIPS (Learned Perceptual Image Patch Similarity) ist eine perzeptuelle Ähnlichkeitsmetrik, die Merkmalsrepräsentationen aus tiefen neuronalen Netzen nutzt.
import torch
import torch.nn as nn
import lpips
from torchvision import models, transforms
class LPIPSEvaluator:
def __init__(self, net='alex', use_gpu=True):
"""
LPIPS-Modell-Initialisierung
net: Wählen Sie aus 'alex', 'vgg', 'squeeze'
"""
self.loss_fn = lpips.LPIPS(net=net)
self.device = torch.device('cuda' if use_gpu and torch.cuda.is_available() else 'cpu')
self.loss_fn.to(self.device)
# Vorverarbeitungs-Pipeline
self.transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
def calculate_lpips(self, img1, img2):
"""
LPIPS-Distanz zwischen zwei Bildern berechnen
"""
# Vorverarbeitung
tensor1 = self.transform(img1).unsqueeze(0).to(self.device)
tensor2 = self.transform(img2).unsqueeze(0).to(self.device)
# LPIPS-Berechnung
with torch.no_grad():
distance = self.loss_fn(tensor1, tensor2)
return distance.item()
def batch_evaluate(self, image_pairs):
"""
LPIPS-Bewertung mit Batch-Verarbeitung
"""
results = []
for img1, img2 in image_pairs:
lpips_score = self.calculate_lpips(img1, img2)
results.append({
'lpips_distance': lpips_score,
'perceptual_similarity': 1 - lpips_score, # Als Ähnlichkeit ausdrücken
'quality_category': self.categorize_quality(lpips_score)
})
return results
def categorize_quality(self, lpips_score):
"""
Qualitätskategorie-Klassifizierung basierend auf LPIPS-Score
"""
if lpips_score < 0.1:
return 'excellent'
elif lpips_score < 0.2:
return 'good'
elif lpips_score < 0.4:
return 'acceptable'
else:
return 'poor'
Benutzerdefinierte LPIPS-Netzwerkkonstruktion
class CustomLPIPSNetwork(nn.Module):
def __init__(self, backbone='resnet50'):
super().__init__()
# Backbone-Netzwerk-Auswahl
if backbone == 'resnet50':
self.features = models.resnet50(pretrained=True)
self.features = nn.Sequential(*list(self.features.children())[:-2])
elif backbone == 'efficientnet':
self.features = models.efficientnet_b0(pretrained=True).features
# Merkmalsextraktions-Schichten
self.feature_layers = [1, 4, 8, 12, 16] # Schichtindizes zum Extrahieren
# Lineare Transformationsschichten
self.linear_layers = nn.ModuleList([
nn.Sequential(
nn.Conv2d(64, 1, 1, bias=False),
nn.GroupNorm(1, 1, affine=False)
),
nn.Sequential(
nn.Conv2d(256, 1, 1, bias=False),
nn.GroupNorm(1, 1, affine=False)
),
nn.Sequential(
nn.Conv2d(512, 1, 1, bias=False),
nn.GroupNorm(1, 1, affine=False)
)
])
def forward(self, x1, x2):
# Merkmalsextraktion
features1 = self.extract_features(x1)
features2 = self.extract_features(x2)
# Distanzberechnung in jeder Schicht
distances = []
for i, (f1, f2) in enumerate(zip(features1, features2)):
# L2-Normalisierung
f1_norm = f1 / (torch.norm(f1, dim=1, keepdim=True) + 1e-8)
f2_norm = f2 / (torch.norm(f2, dim=1, keepdim=True) + 1e-8)
# Distanzberechnung
diff = (f1_norm - f2_norm) ** 2
# Lineare Transformation
if i < len(self.linear_layers):
diff = self.linear_layers[i](diff)
# Räumliche Mittelung
distance = torch.mean(diff, dim=[2, 3])
distances.append(distance)
# Gewichteter Durchschnitt
total_distance = sum(distances) / len(distances)
return total_distance
SSIM: Struktureller Ähnlichkeitsindex
Mathematische Definition von SSIM
import numpy as np
from skimage.metrics import structural_similarity
from scipy.ndimage import gaussian_filter
class SSIMEvaluator:
def __init__(self, window_size=11, k1=0.01, k2=0.03, sigma=1.5):
self.window_size = window_size
self.k1 = k1
self.k2 = k2
self.sigma = sigma
def calculate_ssim(self, img1, img2, data_range=1.0):
"""
Grundlegende SSIM-Berechnung
"""
return structural_similarity(
img1, img2,
data_range=data_range,
multichannel=True,
gaussian_weights=True,
sigma=self.sigma,
use_sample_covariance=False
)
def calculate_ms_ssim(self, img1, img2, weights=None):
"""
Multi-Scale SSIM (MS-SSIM) Implementierung
"""
if weights is None:
weights = [0.0448, 0.2856, 0.3001, 0.2363, 0.1333]
levels = len(weights)
mssim = 1.0
for i in range(levels):
ssim_val = self.calculate_ssim(img1, img2)
if i < levels - 1:
# Downsampling
img1 = self.downsample(img1)
img2 = self.downsample(img2)
mssim *= ssim_val ** weights[i]
else:
mssim *= ssim_val ** weights[i]
return mssim
def downsample(self, img):
"""
Gaußsche Filterung + Downsampling
"""
filtered = gaussian_filter(img, sigma=1.0, axes=[0, 1])
return filtered[::2, ::2]
def ssim_map(self, img1, img2):
"""
SSIM-Karte generieren
"""
# In Graustufen umwandeln
if len(img1.shape) == 3:
img1_gray = np.mean(img1, axis=2)
img2_gray = np.mean(img2, axis=2)
else:
img1_gray = img1
img2_gray = img2
# Mittelwert
mu1 = gaussian_filter(img1_gray, self.sigma)
mu2 = gaussian_filter(img2_gray, self.sigma)
mu1_sq = mu1 ** 2
mu2_sq = mu2 ** 2
mu1_mu2 = mu1 * mu2
# Varianz und Kovarianz
sigma1_sq = gaussian_filter(img1_gray ** 2, self.sigma) - mu1_sq
sigma2_sq = gaussian_filter(img2_gray ** 2, self.sigma) - mu2_sq
sigma12 = gaussian_filter(img1_gray * img2_gray, self.sigma) - mu1_mu2
# SSIM-Berechnung
c1 = (self.k1 * 1.0) ** 2
c2 = (self.k2 * 1.0) ** 2
ssim_map = ((2 * mu1_mu2 + c1) * (2 * sigma12 + c2)) / \
((mu1_sq + mu2_sq + c1) * (sigma1_sq + sigma2_sq + c2))
return ssim_map
Erweiterte Bewertungsmetriken
DISTS: Tiefe Bild-Struktur- und Texturähnlichkeit
import torch
import torchvision.models as models
class DISTSEvaluator:
def __init__(self, use_gpu=True):
self.device = torch.device('cuda' if use_gpu and torch.cuda.is_available() else 'cpu')
# VGG-Merkmalsextraktionsteil verwenden
vgg = models.vgg16(pretrained=True).features
self.stages = nn.ModuleList([
vgg[:4], # conv1_2
vgg[:9], # conv2_2
vgg[:16], # conv3_3
vgg[:23], # conv4_3
vgg[:30] # conv5_3
]).to(self.device)
for param in self.stages.parameters():
param.requires_grad = False
def extract_features(self, x):
features = []
for stage in self.stages:
x = stage(x)
features.append(x)
return features
def calculate_dists(self, img1, img2):
"""
DISTS (Deep Image Structure and Texture Similarity) berechnen
"""
# Vorverarbeitung
tensor1 = self.preprocess(img1).to(self.device)
tensor2 = self.preprocess(img2).to(self.device)
# Merkmalsextraktion
feats1 = self.extract_features(tensor1)
feats2 = self.extract_features(tensor2)
structure_score = 0
texture_score = 0
for f1, f2 in zip(feats1, feats2):
# Strukturähnlichkeit (Mittelwert-Ähnlichkeit)
struct_sim = self.structure_similarity(f1, f2)
structure_score += struct_sim
# Texturähnlichkeit (Kovarianz-Ähnlichkeit)
texture_sim = self.texture_similarity(f1, f2)
texture_score += texture_sim
# Gewichtete Zusammensetzung
alpha = 0.8 # Strukturgewicht
beta = 0.2 # Texturgewicht
dists_score = alpha * structure_score + beta * texture_score
return dists_score.item()
def structure_similarity(self, feat1, feat2):
"""
Strukturähnlichkeit berechnen
"""
# Mittelwert über Kanalrichtung
mean1 = torch.mean(feat1, dim=1, keepdim=True)
mean2 = torch.mean(feat2, dim=1, keepdim=True)
# Strukturelle Ähnlichkeit
numerator = 2 * mean1 * mean2
denominator = mean1 ** 2 + mean2 ** 2
structure_map = numerator / (denominator + 1e-8)
return torch.mean(structure_map)
def texture_similarity(self, feat1, feat2):
"""
Texturähnlichkeit berechnen
"""
# Kovarianzmatrix der Merkmalskarten berechnen
b, c, h, w = feat1.shape
feat1_flat = feat1.view(b, c, -1)
feat2_flat = feat2.view(b, c, -1)
# Kovarianzberechnung
cov1 = torch.bmm(feat1_flat, feat1_flat.transpose(1, 2)) / (h * w - 1)
cov2 = torch.bmm(feat2_flat, feat2_flat.transpose(1, 2)) / (h * w - 1)
# Ähnlichkeit durch Frobenius-Norm
diff_norm = torch.norm(cov1 - cov2, 'fro', dim=[1, 2])
max_norm = torch.maximum(torch.norm(cov1, 'fro', dim=[1, 2]),
torch.norm(cov2, 'fro', dim=[1, 2]))
texture_sim = 1 - diff_norm / (max_norm + 1e-8)
return torch.mean(texture_sim)
FID: Fréchet Inception Distance
from scipy.linalg import sqrtm
import numpy as np
class FIDEvaluator:
def __init__(self):
# Inception v3-Modell (für Merkmalsextraktion)
self.inception = models.inception_v3(pretrained=True, transform_input=False)
self.inception.fc = nn.Identity() # Klassifikationsschicht entfernen
self.inception.eval()
for param in self.inception.parameters():
param.requires_grad = False
def extract_features(self, images):
"""
Merkmalsextraktion mit Inception v3
"""
features = []
with torch.no_grad():
for img in images:
# Auf angemessene Größe skalieren (299x299)
img_resized = F.interpolate(img.unsqueeze(0),
size=(299, 299),
mode='bilinear')
feat = self.inception(img_resized)
features.append(feat.cpu().numpy())
return np.concatenate(features, axis=0)
def calculate_fid(self, real_images, generated_images):
"""
FID (Fréchet Inception Distance) berechnen
"""
# Merkmalsextraktion
real_features = self.extract_features(real_images)
gen_features = self.extract_features(generated_images)
# Statistikberechnung
mu_real = np.mean(real_features, axis=0)
sigma_real = np.cov(real_features, rowvar=False)
mu_gen = np.mean(gen_features, axis=0)
sigma_gen = np.cov(gen_features, rowvar=False)
# Fréchet-Distanzberechnung
diff = mu_real - mu_gen
covmean = sqrtm(sigma_real.dot(sigma_gen))
# Imaginäre Komponenten aufgrund numerischer Fehler entfernen
if np.iscomplexobj(covmean):
covmean = covmean.real
fid = diff.dot(diff) + np.trace(sigma_real + sigma_gen - 2 * covmean)
return fid
Umfassende Bewertungssystem-Konstruktion
Multi-Metrik-Bewertungsgerät
class ComprehensiveQualityEvaluator:
def __init__(self):
self.lpips_evaluator = LPIPSEvaluator()
self.ssim_evaluator = SSIMEvaluator()
self.dists_evaluator = DISTSEvaluator()
self.fid_evaluator = FIDEvaluator()
# Gewichtskonfiguration
self.weights = {
'lpips': 0.3,
'ssim': 0.3,
'dists': 0.2,
'psnr': 0.1,
'fid': 0.1
}
def evaluate_single_pair(self, img1, img2):
"""
Umfassende Qualitätsbewertung eines Bildpaares
"""
results = {}
# LPIPS
results['lpips'] = self.lpips_evaluator.calculate_lpips(img1, img2)
# SSIM
results['ssim'] = self.ssim_evaluator.calculate_ssim(img1, img2)
# DISTS
results['dists'] = self.dists_evaluator.calculate_dists(img1, img2)
# PSNR (Referenzwert)
results['psnr'] = self.calculate_psnr(img1, img2)
# Zusammengesetzten Score berechnen
composite_score = self.calculate_composite_score(results)
results['composite_score'] = composite_score
# Qualitätsniveau bestimmen
results['quality_level'] = self.determine_quality_level(composite_score)
return results
def calculate_psnr(self, img1, img2):
"""
PSNR-Berechnung
"""
mse = np.mean((img1 - img2) ** 2)
if mse == 0:
return float('inf')
return 20 * np.log10(1.0 / np.sqrt(mse))
def calculate_composite_score(self, metrics):
"""
Zusammengesetzter Score aus mehreren Metriken
"""
# Jede Metrik auf 0-1 Bereich normalisieren
normalized_scores = {
'lpips': 1 - min(metrics['lpips'], 1.0), # Niedriger ist besser
'ssim': metrics['ssim'], # Höher ist besser
'dists': metrics['dists'], # Höher ist besser
'psnr': min(metrics['psnr'] / 50, 1.0), # Normalisierung
}
# Gewichtete Zusammensetzung
composite = sum(
self.weights[metric] * score
for metric, score in normalized_scores.items()
if metric in self.weights
)
return composite
def determine_quality_level(self, score):
"""
Qualitätsniveau-Bestimmung basierend auf Score
"""
if score >= 0.9:
return 'excellent'
elif score >= 0.8:
return 'very_good'
elif score >= 0.7:
return 'good'
elif score >= 0.6:
return 'acceptable'
elif score >= 0.5:
return 'poor'
else:
return 'very_poor'
Batch-Verarbeitungssystem
import asyncio
import aiofiles
from pathlib import Path
class BatchQualityEvaluator:
def __init__(self, evaluator, max_workers=4):
self.evaluator = evaluator
self.max_workers = max_workers
self.semaphore = asyncio.Semaphore(max_workers)
async def evaluate_directory(self, original_dir, processed_dir, output_file):
"""
Verzeichnis-Batch-Bewertung
"""
original_path = Path(original_dir)
processed_path = Path(processed_dir)
# Bilddateipaare erhalten
image_pairs = self.get_image_pairs(original_path, processed_path)
# Batch-Bewertung mit paralleler Verarbeitung
tasks = [
self.evaluate_pair_async(orig, proc)
for orig, proc in image_pairs
]
results = await asyncio.gather(*tasks, return_exceptions=True)
# Bericht generieren
report = self.generate_report(image_pairs, results)
# Ergebnisse speichern
await self.save_report(report, output_file)
return report
async def evaluate_pair_async(self, original_path, processed_path):
"""
Asynchrone Bewertung eines Bildpaares
"""
async with self.semaphore:
# Bilder laden
img1 = await self.load_image_async(original_path)
img2 = await self.load_image_async(processed_path)
# Bewertung ausführen
result = self.evaluator.evaluate_single_pair(img1, img2)
result['original_path'] = str(original_path)
result['processed_path'] = str(processed_path)
return result
async def load_image_async(self, path):
"""
Asynchrones Bildladen
"""
async with aiofiles.open(path, 'rb') as f:
data = await f.read()
# Bild mit PIL dekodieren
from PIL import Image
import io
img = Image.open(io.BytesIO(data))
return np.array(img) / 255.0
def generate_report(self, image_pairs, results):
"""
Bewertungsbericht generieren
"""
successful_results = [r for r in results if not isinstance(r, Exception)]
# Statistikberechnung
stats = {
'total_images': len(image_pairs),
'successful_evaluations': len(successful_results),
'average_composite_score': np.mean([r['composite_score'] for r in successful_results]),
'average_lpips': np.mean([r['lpips'] for r in successful_results]),
'average_ssim': np.mean([r['ssim'] for r in successful_results]),
'quality_distribution': self.calculate_quality_distribution(successful_results)
}
report = {
'summary': stats,
'detailed_results': successful_results,
'failed_evaluations': [r for r in results if isinstance(r, Exception)]
}
return report
async def save_report(self, report, output_file):
"""
Bericht als JSON speichern
"""
import json
async with aiofiles.open(output_file, 'w') as f:
await f.write(json.dumps(report, indent=2, default=str))
Echtzeit-Qualitätsüberwachung
Echtzeit-Qualitätsmonitor
import threading
import queue
from collections import deque
class RealTimeQualityMonitor:
def __init__(self, evaluator, window_size=100):
self.evaluator = evaluator
self.window_size = window_size
self.quality_history = deque(maxlen=window_size)
self.alert_queue = queue.Queue()
self.is_running = False
# Alarmschwellenwerte
self.thresholds = {
'composite_score': {
'warning': 0.6,
'critical': 0.4
},
'lpips': {
'warning': 0.3,
'critical': 0.5
}
}
def start_monitoring(self, input_queue):
"""
Echtzeit-Überwachung starten
"""
self.is_running = True
monitor_thread = threading.Thread(
target=self.monitor_loop,
args=(input_queue,)
)
monitor_thread.start()
return monitor_thread
def monitor_loop(self, input_queue):
"""
Hauptüberwachungsschleife
"""
while self.is_running:
try:
# Bildpaar aus der Warteschlange holen
img_pair = input_queue.get(timeout=1.0)
if img_pair is None: # Beendigungssignal
break
# Qualitätsbewertung
result = self.evaluator.evaluate_single_pair(*img_pair)
# Zur Historie hinzufügen
self.quality_history.append(result)
# Alarme prüfen
self.check_alerts(result)
# Statistiken aktualisieren
self.update_statistics()
except queue.Empty:
continue
except Exception as e:
print(f"Überwachungsfehler: {e}")
def check_alerts(self, result):
"""
Alarmbedingungen prüfen
"""
for metric, thresholds in self.thresholds.items():
if metric in result:
value = result[metric]
if value < thresholds['critical']:
self.alert_queue.put({
'level': 'critical',
'metric': metric,
'value': value,
'threshold': thresholds['critical'],
'timestamp': time.time()
})
elif value < thresholds['warning']:
self.alert_queue.put({
'level': 'warning',
'metric': metric,
'value': value,
'threshold': thresholds['warning'],
'timestamp': time.time()
})
def get_current_statistics(self):
"""
Aktuelle Statistiken erhalten
"""
if not self.quality_history:
return {}
recent_scores = [r['composite_score'] for r in self.quality_history]
recent_lpips = [r['lpips'] for r in self.quality_history]
return {
'window_size': len(self.quality_history),
'average_quality': np.mean(recent_scores),
'quality_trend': self.calculate_trend(recent_scores),
'average_lpips': np.mean(recent_lpips),
'quality_stability': np.std(recent_scores)
}
Automatisierte Qualitätsoptimierung
Dynamische Parameteranpassung
class AdaptiveQualityOptimizer:
def __init__(self, evaluator, target_quality=0.8):
self.evaluator = evaluator
self.target_quality = target_quality
self.parameter_history = []
# Zielparameter für Optimierung
self.parameters = {
'compression_quality': {'min': 50, 'max': 100, 'current': 85},
'resize_algorithm': {'options': ['lanczos', 'bicubic', 'bilinear'], 'current': 'lanczos'},
'sharpening_strength': {'min': 0.0, 'max': 2.0, 'current': 1.0}
}
def optimize_parameters(self, test_images, max_iterations=50):
"""
Parameteroptimierung zum Qualitätsziel
"""
best_params = self.parameters.copy()
best_quality = 0
for iteration in range(max_iterations):
# Mit aktuellen Parametern verarbeiten
processed_images = self.process_with_parameters(
test_images, self.parameters
)
# Qualitätsbewertung
avg_quality = self.evaluate_batch_quality(
test_images, processed_images
)
print(f"Iteration {iteration + 1}: Qualität = {avg_quality:.3f}")
# Bestes Ergebnis aktualisieren
if avg_quality > best_quality:
best_quality = avg_quality
best_params = self.parameters.copy()
# Zielerreichung prüfen
if avg_quality >= self.target_quality:
print(f"Zielqualität {self.target_quality} erreicht!")
break
# Parameter aktualisieren
self.update_parameters(avg_quality)
# Historie aufzeichnen
self.parameter_history.append({
'iteration': iteration,
'parameters': self.parameters.copy(),
'quality': avg_quality
})
return best_params, best_quality
def update_parameters(self, current_quality):
"""
Parameterupdates basierend auf aktueller Qualität
"""
quality_gap = self.target_quality - current_quality
# Konservativere Einstellungen verwenden, wenn Qualität niedrig ist
if quality_gap > 0.1:
# Kompressionsqualität erhöhen
self.parameters['compression_quality']['current'] = min(
100,
self.parameters['compression_quality']['current'] + 5
)
# Schärfung reduzieren
self.parameters['sharpening_strength']['current'] = max(
0.0,
self.parameters['sharpening_strength']['current'] - 0.1
)
# Auf Effizienz fokussieren, wenn Qualität ausreichend hoch ist
elif quality_gap < -0.05:
self.parameters['compression_quality']['current'] = max(
50,
self.parameters['compression_quality']['current'] - 2
)
Implementierung und Bereitstellung
Dockerisierter Bewertungsservice
FROM pytorch/pytorch:1.9.0-cuda10.2-cudnn7-runtime
WORKDIR /app
# Abhängigkeiten installieren
COPY requirements.txt .
RUN pip install -r requirements.txt
# Anwendungscode
COPY src/ ./src/
COPY models/ ./models/
# Einstiegspunkt
COPY entrypoint.sh .
RUN chmod +x entrypoint.sh
EXPOSE 8080
ENTRYPOINT ["./entrypoint.sh"]
Web-API-Implementierung
from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.responses import JSONResponse
import uvicorn
app = FastAPI(title="Bildqualitätsbewertungs-API")
# Globaler Bewertungsgerät
quality_evaluator = ComprehensiveQualityEvaluator()
@app.post("/evaluate/single")
async def evaluate_single_image(
original: UploadFile = File(...),
processed: UploadFile = File(...)
):
"""
Einzelbildpaar-Bewertung
"""
try:
# Bilder laden
original_img = await load_upload_image(original)
processed_img = await load_upload_image(processed)
# Bewertung ausführen
result = quality_evaluator.evaluate_single_pair(
original_img, processed_img
)
return JSONResponse(content=result)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/evaluate/batch")
async def evaluate_batch_images(
files: List[UploadFile] = File(...)
):
"""
Batch-Bewertung
"""
if len(files) % 2 != 0:
raise HTTPException(
status_code=400,
detail="Gerade Anzahl von Dateien erforderlich (Original + verarbeitet Paare)"
)
results = []
for i in range(0, len(files), 2):
original_img = await load_upload_image(files[i])
processed_img = await load_upload_image(files[i + 1])
result = quality_evaluator.evaluate_single_pair(
original_img, processed_img
)
results.append(result)
# Statistikberechnung
summary = {
'total_pairs': len(results),
'average_quality': np.mean([r['composite_score'] for r in results]),
'quality_distribution': calculate_quality_distribution(results)
}
return JSONResponse(content={
'summary': summary,
'results': results
})
@app.get("/health")
async def health_check():
return {"status": "healthy"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8080)
Zusammenfassung
KI-Bildqualitätsbewertungsmetriken ermöglichen eine Bewertung, die traditionelle numerische Indikatoren bei weitem übertrifft in der genauen Widerspiegelung menschlicher Wahrnehmung. Die in diesem Artikel eingeführten Techniken können das Qualitätsmanagement für Bildverarbeitungssysteme erheblich verbessern.
Schlüsselpunkte:
- Multifacettierte Bewertung: Umfassende Qualitätsbewertung durch Kombinationen von LPIPS, SSIM und DISTS
- Echtzeit-Überwachung: Früherkennung von Problemen durch Echtzeit-Qualitätsüberwachung
- Automatisierte Optimierung: Dynamische Parameteranpassung zu Qualitätszielen
- Skalierbarkeit: Unterstützung für großmaßstäblichen Betrieb durch Batch-Verarbeitung und API-Entwicklung
Interne Links: Bildqualitäts-Budgets und CI-Gates 2025 — Betrieb zur proaktiven Störungsverhinderung, Ultimative Bildkomprimierung-Strategie 2025 — Praktischer Leitfaden zur Performance-Optimierung bei Qualitätserhalt, Formatkonvertierungsstrategien 2025 — Leitfaden für die Auswahl von WebP/AVIF/JPEG/PNG
Verwandte Werkzeuge
Verwandte Artikel
Bildqualitäts-Budgets und CI-Gates 2025 — Betrieb zur proaktiven Störungsverhinderung
SSIM/LPIPS/Butteraugli und menschliche Augen beide Räder nutzen, um Qualitätsverschlechterung/Farbverschiebung/Volumenzunahme durch CI-automatische Inspektion zu verhindern.
Bildqualitätsmetriken SSIM/PSNR/Butteraugli Praxisleitfaden 2025
Praktische Verfahren zur effektiven Nutzung mechanischer numerischer Indikatoren für objektiven Vergleich und Verifikation der Bildqualität nach Kompression und Größenänderung. Nutzungsmuster und Vorsichtsmaßnahmen für SSIM/PSNR/Butteraugli, mit Beispielen für Workflow-Integration.