compression op• Datenarten: image2d → table
• Aufruf: import fullseye as fs; fs.ledger.jpeg_quality_estimate(image, max_step: 'int' = 64, n_coeff: 'int' = 21) -> 'dict' (die Implementierung direkt: import imgforensics; imgforensics.jpeg_quality_estimate(image, max_step: 'int' = 64, n_coeff: 'int' = 21) -> 'dict'; aus dem Register: opsimgforensics.get("jpeg_quality_estimate"))
Blinde Schätzung der Quantisierungstabelle und der JPEG-Qualität aus einem decodierten Bild. table.
Es liest nicht die DQT der Datei, sondern schätzt allein aus den Pixeln (das ist der Kern:
selbst bei einem als PNG neu gespeicherten / eingefügten Bild wird "es war ursprünglich JPEG-Qualität N" sichtbar). Es nimmt 8x8-Block-DCTs, schätzt je Koeffizient den Kammabstand (Fan & de Queiroz 2003) und wählt aus der Familie von Standardtabellen, die mit der öffentlichen Skalierungsregel der IJG erzeugt sind, die am besten passende Qualität.
Rückgabe (dict):
jpeg_compressed bool, entschieden danach, wie viele der n_coeff Koeffizienten einen Kamm zeigten.
Kein Beweis, dass "es ein JPEG ist" (siehe caveats unten)
quality geschätzte Qualität 1..100 (None, wenn kein Kamm)
table geschätzte (8, 8)-Quantisierungsschritte (0 = nicht schätzbar)
n_quantized Anzahl der Koeffizienten mit Kamm / n_coeff
fit_error mittlere absolute Differenz zur Standardtabelle der gewählten Qualität
caveats was diese Zahl nicht aussagen kann
Gemessen (tests/test_imgforensics.py::test_jpeg_quality_estimate_recovers_quality, 256x256-Bilder mit 1/f^1.6 per Pillow kodiert → dekodiert, dann geschätzt):
======= ========= =============== ============
Wahr Q Schätz Q Kamm-Koeff. fit_error
======= ========= =============== ============
95 95 11/20 0.091
90 90 19/20 0.579
80 80 13/20 1.308
70 71 12/20 2.083
60 60 9/20 2.111
50 52 7/20 1.857
40 40 6/20 3.333
30 None 4/20 —
======= ========= =============== ============
Das Versagen auf der Seite niedriger Qualität ist eine prinzipielle Grenze. Je niedriger die Qualität, desto mehr hochfrequente Koeffizienten werden auf 0 quantisiert, und das Material zum Lesen des Kamms verschwindet selbst aus dem Bild (die Spalte "Kamm-Koeff." zeigt, wie es verschwindet). Bei Qualität 30 reicht das Material nicht, und es wird keine Schätzung zurückgegeben (quality=None). Hier keine Antwort zu erzwingen, ist die Designlinie dieses op.
Und bei unkomprimiertem PNG jpeg_compressed=False / quality=None (mit 4 seeds bestätigt, im selben Test fixiert). Entscheidend ist, hier nicht stillschweigend "Qualität 100" zu antworten; sonst ergäben "unkomprimiert" und "nahezu verlustfreies JPEG" dieselbe Antwort.
• Katalog der Beispieldaten (Download-URLs / Lizenzen) — 2-D nutzt skimage.data (BSD/Public Domain) plus synthetische Bilder, 3-D nennt Download-URLs echter Datenquellen (Stanford, PDS, …).
• Herkunft und Literatur der Operatoren — die Quellen der Forschung/Verfahren, auf denen diese Operatorfamilie beruht.
• Der kanonische Algorithmus (Autor, Jahr) und seine Anwendungen stehen im Familienleitfaden oben.
• image_forensics_audit — py -3.11 examples/image_forensics_audit.py
table als Eingabe)compression)error_level_map · jpeg_ghost_map · jpeg_ghost_quality
*Provenance: imgforensics.py — IMGFORENSICS Operator-Registry. Diese Notiz wird von tools/opdocs.py md erzeugt (nicht von Hand bearbeiten).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.