| """
|
| Inference Script for Document Forgery Detection
|
|
|
| Run inference on single images or entire directories.
|
|
|
| Usage:
|
| python scripts/run_inference.py --input path/to/image.jpg --model outputs/checkpoints/best_doctamper.pth
|
| python scripts/run_inference.py --input path/to/folder/ --model outputs/checkpoints/best_doctamper.pth
|
| """
|
|
|
| import argparse
|
| import sys
|
| from pathlib import Path
|
| import json
|
|
|
|
|
| sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
| from src.config import get_config
|
| from src.inference import get_pipeline
|
|
|
|
|
| def parse_args():
|
| parser = argparse.ArgumentParser(description="Run forgery detection inference")
|
|
|
| parser.add_argument('--input', type=str, required=True,
|
| help='Input image or directory path')
|
|
|
| parser.add_argument('--model', type=str, required=True,
|
| help='Path to localization model checkpoint')
|
|
|
| parser.add_argument('--classifier', type=str, default=None,
|
| help='Path to classifier directory (optional)')
|
|
|
| parser.add_argument('--output', type=str, default='outputs/results',
|
| help='Output directory')
|
|
|
| parser.add_argument('--is_text', action='store_true',
|
| help='Enable OCR features for text documents')
|
|
|
| parser.add_argument('--config', type=str, default='config.yaml',
|
| help='Path to config file')
|
|
|
| return parser.parse_args()
|
|
|
|
|
| def process_file(pipeline, input_path: str, output_dir: str):
|
| """Process a single file"""
|
| try:
|
| result = pipeline.run(input_path, output_dir)
|
| return result
|
| except Exception as e:
|
| print(f"Error processing {input_path}: {e}")
|
| return None
|
|
|
|
|
| def main():
|
| args = parse_args()
|
|
|
|
|
| config = get_config(args.config)
|
|
|
| print("\n" + "="*60)
|
| print("Hybrid Document Forgery Detection - Inference")
|
| print("="*60)
|
| print(f"Input: {args.input}")
|
| print(f"Model: {args.model}")
|
| print(f"Classifier: {args.classifier or 'None'}")
|
| print(f"Output: {args.output}")
|
| print("="*60)
|
|
|
|
|
| pipeline = get_pipeline(
|
| config,
|
| model_path=args.model,
|
| classifier_path=args.classifier,
|
| is_text_document=args.is_text
|
| )
|
|
|
|
|
| output_dir = Path(args.output)
|
| output_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
| input_path = Path(args.input)
|
|
|
| if input_path.is_file():
|
| files = [input_path]
|
| elif input_path.is_dir():
|
| extensions = ['.jpg', '.jpeg', '.png', '.pdf', '.bmp', '.tiff']
|
| files = [f for f in input_path.iterdir()
|
| if f.suffix.lower() in extensions]
|
| else:
|
| print(f"Invalid input path: {input_path}")
|
| return
|
|
|
| print(f"\nProcessing {len(files)} file(s)...")
|
|
|
|
|
| all_results = []
|
|
|
| for file_path in files:
|
| result = process_file(pipeline, str(file_path), str(output_dir))
|
| if result:
|
| all_results.append(result)
|
|
|
|
|
| status = "TAMPERED" if result['is_tampered'] else "AUTHENTIC"
|
| print(f"\n {file_path.name}: {status}")
|
| if result['is_tampered']:
|
| print(f" Regions detected: {result['num_regions']}")
|
| for region in result['regions'][:3]:
|
| print(f" - {region['forgery_type']} (conf: {region['confidence']:.2f})")
|
|
|
|
|
| summary_path = output_dir / 'inference_summary.json'
|
| summary = {
|
| 'total_files': len(files),
|
| 'processed': len(all_results),
|
| 'tampered': sum(1 for r in all_results if r['is_tampered']),
|
| 'authentic': sum(1 for r in all_results if not r['is_tampered']),
|
| 'results': all_results
|
| }
|
|
|
| with open(summary_path, 'w') as f:
|
| json.dump(summary, f, indent=2, default=str)
|
|
|
| print("\n" + "="*60)
|
| print("Inference Complete!")
|
| print(f"Total: {summary['total_files']}, "
|
| f"Tampered: {summary['tampered']}, "
|
| f"Authentic: {summary['authentic']}")
|
| print(f"Results saved to: {output_dir}")
|
| print("="*60)
|
|
|
|
|
| if __name__ == '__main__':
|
| main()
|
|
|