copy_move op• Data kinds: image2d → table
• Call: import fullseye as fs; fs.ledger.copy_move_regions(image, method: 'str' = 'keypoint', min_matches: 'int' = 4, min_offset: 'float' = 16.0, offset_tol: 'float' = 2.0, ratio: 'float' = 0.6, patch: 'int' = 11, block: 'int' = 8, step: 'int' = 1, n_dct: 'int' = 10, min_variance: 'float' = 0.0001, max_feature_dist: 'float' = 0.02, neighbours: 'int' = 2, ransac_thresh: 'float' = 3.0, ransac_iters: 'int' = 300, seed: 'int' = 0) -> 'list' (implementation को सीधे call करना हो तो import imgforensics; imgforensics.copy_move_regions(image, method: 'str' = 'keypoint', min_matches: 'int' = 4, min_offset: 'float' = 16.0, offset_tol: 'float' = 2.0, ratio: 'float' = 0.6, patch: 'int' = 11, block: 'int' = 8, step: 'int' = 1, n_dct: 'int' = 10, min_variance: 'float' = 0.0001, max_feature_dist: 'float' = 0.02, neighbours: 'int' = 2, ransac_thresh: 'float' = 3.0, ransac_iters: 'int' = 300, seed: 'int' = 0) -> 'list', registry से लेना हो तो opsimgforensics.get("copy_move_regions"))
1 image के अंदर copy-move (स्व-दोहराए गए) region के जोड़े लौटाता है। table।
method="keypoint" (default)
features.harris_corners से corners लेता है,
features.describe_patches से normalized patch descriptors बनाता है,
और स्वयं से कम से कम min_offset px दूर nearest neighbour तथा Lowe के ratio test से matches बनाता है
(_self_match)। matches को shift vector के अनुसार समूहित किया जाता है, और हर group के लिए
mosaic.proj_match_points_ransac से geometric consistency जाँची जाती है।
fit_transform.vector_to_similarity (Umeyama) से एक similarity transform fit किया जाता है और
similarity में रखा जाता है।
method="block"
Fridrich, Soukal & Lukáš 2003। overlapping block-वर्ग blocks step px के
अंतराल पर लिए जाते हैं (default step=1 —— यह सजावट नहीं है; नीचे "stride" देखें),
हर block के low-frequency n_dct DCT coefficients को feature के रूप में लेकर lexicographic क्रम में sort किया जाता है,
lexicographic क्रम में पास-पास की अधिकतम neighbours entries candidates बनती हैं, और केवल वे जिनकी feature distance
अधिकतम max_feature_dist है, shift vector के अनुसार गिनी जाती हैं।
यह rotation या scaling को नहीं संभालता, लेकिन कम corners वाली images पर keypoint method से अधिक पकड़ता है।
min_variance से कम variance वाले blocks हटा दिए जाते हैं (uniform आकाश को आकाश पर copy करने से समान features मिलते हैं = detector द्वारा अनिवार्य रूप से पैदा होने वाले false positives का मुख्य कारण)।
stride (step) 1 क्यों है (माप से तय किया गया): block method "समान features" तभी पा सकता है जब copy का स्रोत और गंतव्य एक ही grid पर हों। step=4 के साथ, ऐसी copy जिसका shift 4 का गुणज नहीं है (उदा. (110, 128)) सिद्धांततः कभी match नहीं होती। मापों में step=4 ने 1 भी सही shift नहीं लौटाया, और उसकी जगह 60 गलत groups लौटाए। step=1 के साथ सही shift group 1 के रूप में आता है। बड़ी images भारी हों तो आप step बढ़ा सकते हैं, लेकिन यह जानते हुए बढ़ाएँ कि तब केवल बढ़ाए गए stride के गुणज वाले shifts ही मिल सकते हैं।
आउटपुट region pairs की list है (match count के घटते क्रम में)। हर element:
offset shift (dy, dx) (row, col)। इसका चिह्न स्थिति के अनुसार normalize किया जाता है
(वह दिशा जो lexicographic क्रम में धनात्मक है) —— index से तय करने पर वही copy
(110, 128) और (-110, -128) दोनों बन जाती (मापकर ठीक किया गया)
n_matches उस group में matches की संख्या
n_inliers RANSAC inliers की संख्या (method="block" के लिए n_matches के समान)
inlier_ratio inlier अनुपात src_bbox / dst_bbox (r0, c0, r1, c1) src_points / dst_points shape (N, 2) के (row, col)
similarity Umeyama से fit किया गया 3x3 (केवल method="keypoint"; अन्यथा None)
method उपयोग की गई method
caveats वह जो यह परिणाम नहीं बता सकता
क्योंकि उत्तर हाथ में है, सही पकड़ने की बात संख्याओं में पक्की की गई है (tests/test_imgforensics.py::test_copy_move_finds_the_known_offset, 256x256 texture image के (40, 32) पर 64x64 patch को (150, 160) पर copy किया गया = सही shift (110, 128)):
============ ================= ============ ========= ==============
method Group 1 offset n_matches Groups Error
============ ================= ============ ========= ==============
keypoint (110.0, 128.0) 15 1 0 px
block (110.0, 128.0) 3249 1 0 px
============ ================= ============ ========= ==============
False positives भी मापे गए हैं: उसी प्रकार की 3 बिना छेड़छाड़ वाली images पर, keypoint और block method दोनों 0 groups देते हैं (seeds 4/5/6)।
यह क्या नहीं बता सकता (सब उसी test में मापा गया):
• Uniform regions (आकाश, दीवारें) में copy किए बिना भी समान features होते हैं। ऐसी (बिना छेड़छाड़ वाली) image पर जिसका ऊपरी आधा एक uniform "आकाश" है, min_variance=1e-4 और 1e-6 दोनों 0 groups देते हैं, लेकिन min_variance=0 के साथ 264 pairs का 1 गलत group दिखता है (shift (1, -247) = आकाश के भीतर मनमाने matches)।
• method="keypoint" normalized patch descriptors उपयोग करता है, इसलिए यह rotation को नहीं संभालता। चिपकाने से पहले copy को घुमाने पर group counts 0 deg: 1 → 5 deg: 0 → 15 deg: 0 → 30 deg: 0। व्यवहार में similarity कभी rotation के साथ वापस नहीं आता।
• method="block" भी rotation को बिल्कुल नहीं संभालता (5 deg पर 0)।
• शून्य detections का अर्थ यह नहीं कि कोई copy नहीं है। बीच में recompression वाली copy के लिए feature distance बढ़ती है और max_feature_dist से अधिक हो जाती है। मापा गया (वही copy की गई image detection से पहले JPEG से गुज़ारी गई):
========== ============================ ==========================
Quality keypoint group 1 n_matches block group 1 n_matches
========== ============================ ==========================
Uncompr. 15 3249
95 10 138
85 7 10
75 7 0 (कोई group नहीं)
========== ============================ ==========================
हर quality पर shift (110.0, 128.0) पर सही रहता है। जो टूटता है वह "यह मिलता है या नहीं" है, मिलने पर उत्तर नहीं।
• 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 में दिए गए हैं।
• image_forensics_audit — py -3.11 examples/image_forensics_audit.py
• poc_forensics_roc — py -3.11 examples/poc_forensics_roc.py
table को input के रूप में लेते हैं)copy_move)—
*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.