error_level_map — IMGFORENSICS compression op

• Data kinds: image2d → image2d

• Call: import fullseye as fs; fs.ledger.error_level_map(image, quality: 'int' = 90, normalize: 'bool' = True) -> 'np.ndarray' (implementation को सीधे call करना हो तो import imgforensics; imgforensics.error_level_map(image, quality: 'int' = 90, normalize: 'bool' = True) -> 'np.ndarray', registry से लेना हो तो opsimgforensics.get("error_level_map"))

उपयोग

ELA (error-level analysis)। दी गई quality पर दोबारा compress करने के अंतर का map लौटाता है। image2d।

Krawetz 2007। JPEG हर 8x8 block पर quantize करता है, इसलिए एक बार compress हो चुका region समान quality पर फिर से compress करने पर कम error दिखाता है, जबकि बाद में चिपकाया / बनाया गया region बड़ा error छोड़ता है; यही इसका आधारभूत विचार है।

normalize=True (default) होने पर इसे अधिकतम मान से भाग देकर [0, 1] में लाया जाता है (देखने के लिए)। False होने पर यह raw 8 bit levels में निरपेक्ष error है (गिनती के लिए)।

Pillow के बिना ImportError। यह किसी approximation पर fallback नहीं करता। numpy में केवल DCT quantization की नकल करने से *कुछ और* मिलता है, जिसमें encoder की rounding, colour-space conversion और chroma subsampling गायब हैं। उसे ELA कहना उसी "विश्वसनीय लगने वाली गलती" को स्वयं करना होगा जिसे यह family मिटाने के लिए बनी है।

यह map क्या नहीं बता सकता (tests/test_imgforensics.py इसे संख्याओं में पक्का करता है; 256x256 1/f^1.6 image के बीच के 64x64 में एक अलग image चिपकाई गई):

==================================== ================ ================ =========

मूल image चिपके भाग का ELA background का ELA अनुपात

==================================== ================ ================ =========

Uncompressed (कभी JPEG नहीं) 0.1966 0.1793 1.096

एक बार JPEG q75 से गुज़री 0.1966 0.0401 4.898

==================================== ================ ================ =========

• uncompressed PNG पर यह कुछ नहीं बता सकता। ऊपर का 1.096 गुना अर्थ है "चिपके और बिना चिपके क्षेत्र अलग नहीं पहचाने जा सकते"। ELA तभी सार्थक है जब "मूल एक JPEG हो", और तभी अंतर 4.898 गुना होता है।

• आम दावा "ELA केवल high frequencies का पीछा करता है" इस image पर भी सही नहीं बैठता —— ELA और Sobel gradient magnitude के बीच correlation 0.003 (uncompressed) / 0.057 (पहले से JPEG) है। ELA 8x8 blocks के quantization residual को देखता है, इसलिए यह gradient से अलग कुछ मापता है। फिर भी, जैसा table दिखाती है, uncompressed होने पर यह छेड़छाड़ को अलग नहीं करता। यह "gradient का दूसरा रूप होने के कारण" विफल नहीं होता, बल्कि इसलिए कि तुलना के reference के रूप में कोई quantization history नहीं है।

• सपाट regions compress होने पर भी error नहीं दिखाते, इसलिए छेड़छाड़ होने पर भी वे अंधेरे ही रहते हैं।

संदर्भ (sample data, साहित्य)

• Sample data catalog (DL URL / license) — 2-D के लिए skimage.data (BSD/public) + synthetic, 3-D के लिए real data sources (Stanford/PDS आदि) के DL URL।

• Operators का स्रोत और संदर्भ — इस op family के मूल research/methods के स्रोत।

• Algorithm का मानक स्रोत (लेखक, वर्ष) और उपयोग ऊपर की family usage guide में दिए गए हैं।

चलाए जा सकने वाले उदाहरण (verified samples जो सच में यह op call करते हैं)

• image_forensics_audit — py -3.11 examples/image_forensics_audit.py

• poc_forensics_roc — py -3.11 examples/poc_forensics_roc.py

वे अगले ops जिनसे type जुड़ता है (image2d को input के रूप में लेते हैं)

perceptual_hash · fingerprint_correlate · jpeg_quality_estimate · jpeg_ghost_map · noise_inconsistency_map · copy_move_regions · watermark_embed · watermark_extract

इसी category के (compression)

jpeg_quality_estimate · jpeg_ghost_map · jpeg_ghost_quality


*Provenance: imgforensics.py — IMGFORENSICS operator registry. यह per-op note tools/opdocs.py md से अपने-आप generate होता है (हाथ से edit न करें)।*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.