feat: Claude Vision AI analysis integration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ferdinand
2026-04-07 13:43:02 +02:00
parent 2ed2ae3d16
commit 00f3aeb008

View File

@@ -3,6 +3,7 @@ import numpy as np
from PIL import Image from PIL import Image
import imagehash import imagehash
import os import os
import base64
from typing import List, Optional from typing import List, Optional
@@ -69,6 +70,58 @@ def find_duplicates(paths: List[str], threshold: int = 8) -> List[List[str]]:
SUPPORTED_EXTENSIONS = {".jpg", ".jpeg", ".png"} SUPPORTED_EXTENSIONS = {".jpg", ".jpeg", ".png"}
def _analyze_with_ai(paths: List[str], api_key: str) -> dict:
"""
Sendet Bilder an Claude Vision API zur Qualitaetsanalyse.
Gibt {path: [reasons]} zurueck. Bei Fehler wird der Pfad uebersprungen.
"""
import anthropic
client = anthropic.Anthropic(api_key=api_key)
ai_results: dict = {path: [] for path in paths}
PROMPT = (
"Analysiere dieses Foto auf Qualitaetsprobleme fuer einen professionellen Fotografen. "
"Antworte NUR mit einer kommagetrennten Liste von Problemen aus diesen Kategorien: "
"unscharf, ueberbelichtet, unterbelichtet, schlechter Bildausschnitt, stoerende Elemente, "
"schlechter Weissabgleich. Wenn das Bild in Ordnung ist, antworte mit 'ok'."
)
for path in paths:
try:
with open(path, "rb") as f:
img_data = base64.standard_b64encode(f.read()).decode("utf-8")
ext = os.path.splitext(path)[1].lower().lstrip(".")
media_type = "image/jpeg" if ext in ("jpg", "jpeg") else "image/png"
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=100,
messages=[{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": media_type,
"data": img_data,
},
},
{"type": "text", "text": PROMPT},
],
}],
)
answer = response.content[0].text.strip().lower()
if answer != "ok":
reasons = [r.strip() for r in answer.split(",") if r.strip()]
ai_results[path].extend(reasons)
except Exception:
continue
return ai_results
def analyze_folder( def analyze_folder(
folder: str, folder: str,
blur_threshold: float = 100.0, blur_threshold: float = 100.0,