ScreenshotScanner 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- screenshotscanner-0.1.0/.github/workflows/codeql.yml +42 -0
- screenshotscanner-0.1.0/.gitignore +59 -0
- screenshotscanner-0.1.0/CONTRIBUTING.md +119 -0
- screenshotscanner-0.1.0/LICENSE +21 -0
- screenshotscanner-0.1.0/MANIFEST.in +7 -0
- screenshotscanner-0.1.0/PKG-INFO +215 -0
- screenshotscanner-0.1.0/README.md +178 -0
- screenshotscanner-0.1.0/ScreenshotScanner.egg-info/PKG-INFO +215 -0
- screenshotscanner-0.1.0/ScreenshotScanner.egg-info/SOURCES.txt +28 -0
- screenshotscanner-0.1.0/ScreenshotScanner.egg-info/dependency_links.txt +1 -0
- screenshotscanner-0.1.0/ScreenshotScanner.egg-info/requires.txt +5 -0
- screenshotscanner-0.1.0/ScreenshotScanner.egg-info/top_level.txt +1 -0
- screenshotscanner-0.1.0/ScreenshotScanner.png +0 -0
- screenshotscanner-0.1.0/pyproject.toml +45 -0
- screenshotscanner-0.1.0/requirements.txt +5 -0
- screenshotscanner-0.1.0/screenshot_scanner/__init__.py +13 -0
- screenshotscanner-0.1.0/screenshot_scanner/scanner.py +419 -0
- screenshotscanner-0.1.0/setup.cfg +4 -0
- screenshotscanner-0.1.0/setup.py +46 -0
- screenshotscanner-0.1.0/simple_demo.py +11 -0
- screenshotscanner-0.1.0/test_data/False/20260115_153409.jpg +0 -0
- screenshotscanner-0.1.0/test_data/False/20260115_163007.jpg +0 -0
- screenshotscanner-0.1.0/test_data/False/20260120_155705.jpg +0 -0
- screenshotscanner-0.1.0/test_data/False/20260120_155751.jpg +0 -0
- screenshotscanner-0.1.0/test_data/True/Screenshot 2026-01-20 162653.jpg +0 -0
- screenshotscanner-0.1.0/test_data/True/Screenshot 2026-01-20 162715.jpg +0 -0
- screenshotscanner-0.1.0/test_data/True/Screenshot 2026-01-20 162752.jpg +0 -0
- screenshotscanner-0.1.0/test_data/True/Screenshot 2026-01-20 162848.jpg +0 -0
- screenshotscanner-0.1.0/tests/__init__.py +1 -0
- screenshotscanner-0.1.0/tests/test_detector.py +89 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: "CodeQL"
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ "main" ]
|
|
6
|
+
pull_request:
|
|
7
|
+
# The branches below must be a subset of the branches above
|
|
8
|
+
branches: [ "main" ]
|
|
9
|
+
schedule:
|
|
10
|
+
- cron: '29 18 * * 3'
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
analyze:
|
|
14
|
+
name: Analyze
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
permissions:
|
|
17
|
+
actions: read
|
|
18
|
+
contents: read
|
|
19
|
+
security-events: write
|
|
20
|
+
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
language: [ 'python' ]
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- name: Checkout repository
|
|
28
|
+
uses: actions/checkout@v3
|
|
29
|
+
|
|
30
|
+
# Initializes the CodeQL tools for scanning.
|
|
31
|
+
- name: Initialize CodeQL
|
|
32
|
+
uses: github/codeql-action/init@v2
|
|
33
|
+
with:
|
|
34
|
+
languages: ${{ matrix.language }}
|
|
35
|
+
|
|
36
|
+
- name: Autobuild
|
|
37
|
+
uses: github/codeql-action/autobuild@v2
|
|
38
|
+
|
|
39
|
+
- name: Perform CodeQL Analysis
|
|
40
|
+
uses: github/codeql-action/analyze@v2
|
|
41
|
+
with:
|
|
42
|
+
category: "/language:${{ matrix.language }}"
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Jupyter Notebook (DO NOT UPLOAD)
|
|
2
|
+
Screenshot_detection_newst_combined.ipynb
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*$py.class
|
|
8
|
+
*.so
|
|
9
|
+
.Python
|
|
10
|
+
build/
|
|
11
|
+
develop-eggs/
|
|
12
|
+
dist/
|
|
13
|
+
downloads/
|
|
14
|
+
eggs/
|
|
15
|
+
.eggs/
|
|
16
|
+
lib/
|
|
17
|
+
lib64/
|
|
18
|
+
parts/
|
|
19
|
+
sdist/
|
|
20
|
+
var/
|
|
21
|
+
wheels/
|
|
22
|
+
pip-wheel-metadata/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# Jupyter Notebook checkpoints
|
|
30
|
+
.ipynb_checkpoints
|
|
31
|
+
|
|
32
|
+
# Virtual Environment
|
|
33
|
+
venv/
|
|
34
|
+
ENV/
|
|
35
|
+
env/
|
|
36
|
+
.venv
|
|
37
|
+
|
|
38
|
+
# IDE
|
|
39
|
+
.vscode/
|
|
40
|
+
.idea/
|
|
41
|
+
*.swp
|
|
42
|
+
*.swo
|
|
43
|
+
*~
|
|
44
|
+
.DS_Store
|
|
45
|
+
|
|
46
|
+
# Testing
|
|
47
|
+
.pytest_cache/
|
|
48
|
+
.coverage
|
|
49
|
+
htmlcov/
|
|
50
|
+
.tox/
|
|
51
|
+
|
|
52
|
+
# Temporary files
|
|
53
|
+
*.temp.jpg
|
|
54
|
+
*.tmp
|
|
55
|
+
.cache/
|
|
56
|
+
|
|
57
|
+
# OS
|
|
58
|
+
Thumbs.db
|
|
59
|
+
.DS_Store
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Contributing to ScreenshotScanner
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to ScreenshotScanner! This document provides guidelines for contributing to the project.
|
|
4
|
+
|
|
5
|
+
## Code of Conduct
|
|
6
|
+
|
|
7
|
+
Be respectful and constructive in all interactions. We're all here to make this project better!
|
|
8
|
+
|
|
9
|
+
## How to Contribute
|
|
10
|
+
|
|
11
|
+
### Reporting Bugs
|
|
12
|
+
|
|
13
|
+
If you find a bug, please create an issue on GitHub with:
|
|
14
|
+
|
|
15
|
+
- A clear, descriptive title
|
|
16
|
+
- Steps to reproduce the bug
|
|
17
|
+
- Expected behavior vs. actual behavior
|
|
18
|
+
- Screenshots or code samples if applicable
|
|
19
|
+
- Your environment (OS, Python version, package version)
|
|
20
|
+
|
|
21
|
+
### Suggesting Enhancements
|
|
22
|
+
|
|
23
|
+
We welcome suggestions for new features or improvements! Please create an issue with:
|
|
24
|
+
|
|
25
|
+
- A clear description of the enhancement
|
|
26
|
+
- Use cases and benefits
|
|
27
|
+
- Any implementation ideas you have
|
|
28
|
+
|
|
29
|
+
### Pull Requests
|
|
30
|
+
|
|
31
|
+
1. **Fork the repository** and create your branch from `main`
|
|
32
|
+
2. **Make your changes** with clear, descriptive commits
|
|
33
|
+
3. **Add tests** for new functionality
|
|
34
|
+
4. **Update documentation** if needed
|
|
35
|
+
5. **Ensure tests pass** before submitting
|
|
36
|
+
6. **Submit a pull request** with a clear description
|
|
37
|
+
|
|
38
|
+
## Development Setup
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Clone your fork
|
|
42
|
+
git clone https://github.com/YOUR_USERNAME/ScreenshotScanner.git
|
|
43
|
+
cd ScreenshotScanner
|
|
44
|
+
|
|
45
|
+
# Create a virtual environment
|
|
46
|
+
python -m venv venv
|
|
47
|
+
source venv/bin/activate # On Windows: venv\Scripts\activate
|
|
48
|
+
|
|
49
|
+
# Install in development mode
|
|
50
|
+
pip install -e .
|
|
51
|
+
|
|
52
|
+
# Install development dependencies
|
|
53
|
+
pip install pytest black flake8
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Code Style
|
|
57
|
+
|
|
58
|
+
- Follow PEP 8 guidelines
|
|
59
|
+
- Use meaningful variable and function names
|
|
60
|
+
- Add docstrings to all functions and classes
|
|
61
|
+
- Keep functions focused and modular
|
|
62
|
+
|
|
63
|
+
### Running Code Formatters
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Format code with black
|
|
67
|
+
black screenshot_scanner/
|
|
68
|
+
|
|
69
|
+
# Check code style
|
|
70
|
+
flake8 screenshot_scanner/
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Testing
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Run all tests
|
|
77
|
+
python -m pytest tests/
|
|
78
|
+
|
|
79
|
+
# Run with coverage
|
|
80
|
+
python -m pytest --cov=screenshot_scanner tests/
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Writing Tests
|
|
84
|
+
|
|
85
|
+
- Add tests for all new features
|
|
86
|
+
- Ensure edge cases are covered
|
|
87
|
+
- Use descriptive test names
|
|
88
|
+
- Keep tests independent and isolated
|
|
89
|
+
|
|
90
|
+
## Commit Messages
|
|
91
|
+
|
|
92
|
+
- Use clear, descriptive commit messages
|
|
93
|
+
- Start with a verb (Add, Fix, Update, Remove, etc.)
|
|
94
|
+
- Keep the first line under 50 characters
|
|
95
|
+
- Add detailed description if needed
|
|
96
|
+
|
|
97
|
+
Example:
|
|
98
|
+
```
|
|
99
|
+
Add support for PNG alpha channel detection
|
|
100
|
+
|
|
101
|
+
- Implement alpha channel check in detector
|
|
102
|
+
- Add test cases for RGBA images
|
|
103
|
+
- Update documentation
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Documentation
|
|
107
|
+
|
|
108
|
+
- Update README.md for user-facing changes
|
|
109
|
+
- Add docstrings for new functions/classes
|
|
110
|
+
- Include usage examples for new features
|
|
111
|
+
- Keep documentation clear and concise
|
|
112
|
+
|
|
113
|
+
## Questions?
|
|
114
|
+
|
|
115
|
+
Feel free to open an issue for any questions about contributing!
|
|
116
|
+
|
|
117
|
+
## License
|
|
118
|
+
|
|
119
|
+
By contributing, you agree that your contributions will be licensed under the MIT License.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AzwadFawadHasan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ScreenshotScanner
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A heuristic-based tool to detect whether an image is a screenshot
|
|
5
|
+
Home-page: https://github.com/AzwadFawadHasan/ScreenshotScanner
|
|
6
|
+
Author: AzwadFawadHasan
|
|
7
|
+
Author-email: AzwadFawadHasan <azwadfawadhasan@gmail.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/AzwadFawadHasan/ScreenshotScanner
|
|
10
|
+
Project-URL: Documentation, https://github.com/AzwadFawadHasan/ScreenshotScanner#readme
|
|
11
|
+
Project-URL: Repository, https://github.com/AzwadFawadHasan/ScreenshotScanner
|
|
12
|
+
Project-URL: Bug Tracker, https://github.com/AzwadFawadHasan/ScreenshotScanner/issues
|
|
13
|
+
Keywords: screenshot,detection,image-processing,document-verification,kyc
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Image Recognition
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: numpy>=1.20.0
|
|
29
|
+
Requires-Dist: Pillow>=8.0.0
|
|
30
|
+
Requires-Dist: scipy>=1.6.0
|
|
31
|
+
Requires-Dist: opencv-python>=4.5.0
|
|
32
|
+
Requires-Dist: pytesseract>=0.3.8
|
|
33
|
+
Dynamic: author
|
|
34
|
+
Dynamic: home-page
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
Dynamic: requires-python
|
|
37
|
+
|
|
38
|
+
<p align="center">
|
|
39
|
+
<img src="ScreenshotScanner.png" alt="ScreenshotScanner Logo" width="250">
|
|
40
|
+
</p>
|
|
41
|
+
|
|
42
|
+
<h1 align="center">ScreenshotScanner</h1>
|
|
43
|
+
|
|
44
|
+
<p align="center">
|
|
45
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
|
46
|
+
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.8+-blue.svg" alt="Python 3.8+"></a>
|
|
47
|
+
<a href="https://pypi.org/project/ScreenshotScanner/"><img src="https://img.shields.io/pypi/v/ScreenshotScanner.svg?logo=pypi&logoColor=959DA5&color=blue" alt="PyPI"></a>
|
|
48
|
+
<a href="https://pypistats.org/packages/screenshotscanner"><img src="https://static.pepy.tech/badge/ScreenshotScanner" alt="Downloads"></a>
|
|
49
|
+
<a href="https://github.com/AzwadFawadHasan/ScreenshotScanner/actions/workflows/codeql.yml"><img src="https://github.com/AzwadFawadHasan/ScreenshotScanner/actions/workflows/codeql.yml/badge.svg" alt="CodeQL"></a>
|
|
50
|
+
</p>
|
|
51
|
+
|
|
52
|
+
<p align="center">
|
|
53
|
+
A heuristic-based tool to detect whether an image is a screenshot or a photo of a physical document.
|
|
54
|
+
<br>
|
|
55
|
+
<b>Star this repo if it helped you!</b>
|
|
56
|
+
</p>
|
|
57
|
+
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
- **13 Heuristic Checks** - Multiple detection methods for high accuracy
|
|
61
|
+
- **Simple API** - Easy to integrate into existing workflows
|
|
62
|
+
- **Detailed Metrics** - Optional verbose mode for debugging
|
|
63
|
+
- **No Training Required** - Rule-based system, no ML models needed
|
|
64
|
+
- **Fast Processing** - Analyze images in milliseconds
|
|
65
|
+
|
|
66
|
+
## Installation
|
|
67
|
+
|
|
68
|
+
### Basic Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install ScreenshotScanner
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
## Quick Start
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from screenshot_scanner import ScreenshotScanner
|
|
79
|
+
|
|
80
|
+
# Initialize scanner
|
|
81
|
+
scanner = ScreenshotScanner()
|
|
82
|
+
|
|
83
|
+
# Process an image (simple one-liner)
|
|
84
|
+
result = scanner.process("path/to/image.jpg")
|
|
85
|
+
|
|
86
|
+
print(result)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Example Output
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
{
|
|
93
|
+
'is_screenshot': True,
|
|
94
|
+
'score': 8,
|
|
95
|
+
'confidence': 80.0,
|
|
96
|
+
'reasons': ['Has alpha channel', 'Common aspect ratio: 1.78', 'Low ELA: 45.32', 'No EXIF data', 'High sharpness: 156.23']
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**That's it!** Just 3 lines of code to detect screenshots.
|
|
101
|
+
|
|
102
|
+
<!--
|
|
103
|
+
## đź“– Advanced Usage
|
|
104
|
+
|
|
105
|
+
### Accessing Detailed Information
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
result = scanner.process("image.jpg")
|
|
109
|
+
|
|
110
|
+
# Access individual fields
|
|
111
|
+
if result['is_screenshot']:
|
|
112
|
+
print(f"Screenshot detected with {result['confidence']:.1f}% confidence")
|
|
113
|
+
print(f"Detection score: {result['score']}/10")
|
|
114
|
+
print("Reasons:")
|
|
115
|
+
for reason in result['reasons']:
|
|
116
|
+
print(f" - {reason}")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Verbose Mode (All Metrics)
|
|
120
|
+
|
|
121
|
+
For debugging or detailed analysis, use `is_screenshot()` with `verbose=True`:
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
result = scanner.is_screenshot("image.jpg", verbose=True)
|
|
125
|
+
|
|
126
|
+
# Access detailed metrics
|
|
127
|
+
metrics = result['metrics']
|
|
128
|
+
print(f"Alpha channel: {metrics['alpha']}")
|
|
129
|
+
print(f"Aspect ratio: {metrics['aspect_ratio']}")
|
|
130
|
+
print(f"ELA std: {metrics['ela_std']}")
|
|
131
|
+
print(f"Sharpness: {metrics['sharpness']}")
|
|
132
|
+
# ... and 9 more metrics
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Custom Threshold
|
|
136
|
+
|
|
137
|
+
Adjust the detection sensitivity:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
# More strict (fewer false positives)
|
|
141
|
+
strict_scanner = ScreenshotScanner(threshold=7)
|
|
142
|
+
|
|
143
|
+
# More lenient (fewer false negatives)
|
|
144
|
+
lenient_scanner = ScreenshotScanner(threshold=3)
|
|
145
|
+
|
|
146
|
+
result = strict_scanner.process("image.jpg")
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Batch Processing
|
|
150
|
+
|
|
151
|
+
Process multiple images:
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
import os
|
|
155
|
+
from screenshot_scanner import ScreenshotScanner
|
|
156
|
+
|
|
157
|
+
scanner = ScreenshotScanner()
|
|
158
|
+
image_folder = "path/to/images"
|
|
159
|
+
|
|
160
|
+
for filename in os.listdir(image_folder):
|
|
161
|
+
if filename.endswith(('.jpg', '.png', '.jpeg')):
|
|
162
|
+
image_path = os.path.join(image_folder, filename)
|
|
163
|
+
result = scanner.process(image_path)
|
|
164
|
+
print(f"{filename}: {result['is_screenshot']} (score: {result['score']})")
|
|
165
|
+
``` -->
|
|
166
|
+
|
|
167
|
+
## How It Works
|
|
168
|
+
|
|
169
|
+
ScreenshotScanner uses 13 different heuristic checks to determine if an image is a screenshot:
|
|
170
|
+
|
|
171
|
+
1. **Alpha Channel** - Screenshots often have transparency
|
|
172
|
+
2. **Aspect Ratio** - Common screen ratios (16:9, 4:3, etc.)
|
|
173
|
+
3. **Border Variance** - Uniform borders indicate screenshots
|
|
174
|
+
4. **ELA (Error Level Analysis)** - Lower compression artifacts in screenshots
|
|
175
|
+
5. **EXIF Data** - Screenshots typically lack camera metadata
|
|
176
|
+
6. **Horizontal Edges** - UI elements create horizontal patterns
|
|
177
|
+
7. **Moiré Patterns** - Photos of screens show moiré, screenshots don't
|
|
178
|
+
8. **Noise Analysis** - Screenshots have less sensor noise
|
|
179
|
+
9. **Sharpness** - Screenshots are typically sharper
|
|
180
|
+
10. **Solid Color Ratio** - UI elements have more solid colors
|
|
181
|
+
11. **Status Bar Detection** - Mobile screenshots often have status bars
|
|
182
|
+
12. **Text Confidence** - OCR works better on screenshot text
|
|
183
|
+
13. **Vertical Symmetry** - UI layouts are often symmetric
|
|
184
|
+
|
|
185
|
+
Each check contributes to a final score. A score ≥ 5 (default threshold) indicates a screenshot.
|
|
186
|
+
|
|
187
|
+
## Contributing
|
|
188
|
+
|
|
189
|
+
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
## License
|
|
194
|
+
|
|
195
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
196
|
+
|
|
197
|
+
## Motivation
|
|
198
|
+
|
|
199
|
+
- There is no good tool without ML to detect screenshots. So i decided to come up with this.
|
|
200
|
+
|
|
201
|
+
## Contact
|
|
202
|
+
|
|
203
|
+
- **Author**: AzwadFawadHasan
|
|
204
|
+
- **GitHub**: [@AzwadFawadHasan](https://github.com/AzwadFawadHasan)
|
|
205
|
+
- **Issues**: [GitHub Issues](https://github.com/AzwadFawadHasan/ScreenshotScanner/issues)
|
|
206
|
+
|
|
207
|
+
## Star
|
|
208
|
+
|
|
209
|
+
If you find this project useful, please consider giving it a star on GitHub!
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
Made with ❤️ for better document verification by AzwadFawadHasan
|
|
214
|
+
|
|
215
|
+

|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="ScreenshotScanner.png" alt="ScreenshotScanner Logo" width="250">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">ScreenshotScanner</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
|
9
|
+
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.8+-blue.svg" alt="Python 3.8+"></a>
|
|
10
|
+
<a href="https://pypi.org/project/ScreenshotScanner/"><img src="https://img.shields.io/pypi/v/ScreenshotScanner.svg?logo=pypi&logoColor=959DA5&color=blue" alt="PyPI"></a>
|
|
11
|
+
<a href="https://pypistats.org/packages/screenshotscanner"><img src="https://static.pepy.tech/badge/ScreenshotScanner" alt="Downloads"></a>
|
|
12
|
+
<a href="https://github.com/AzwadFawadHasan/ScreenshotScanner/actions/workflows/codeql.yml"><img src="https://github.com/AzwadFawadHasan/ScreenshotScanner/actions/workflows/codeql.yml/badge.svg" alt="CodeQL"></a>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
A heuristic-based tool to detect whether an image is a screenshot or a photo of a physical document.
|
|
17
|
+
<br>
|
|
18
|
+
<b>Star this repo if it helped you!</b>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- **13 Heuristic Checks** - Multiple detection methods for high accuracy
|
|
24
|
+
- **Simple API** - Easy to integrate into existing workflows
|
|
25
|
+
- **Detailed Metrics** - Optional verbose mode for debugging
|
|
26
|
+
- **No Training Required** - Rule-based system, no ML models needed
|
|
27
|
+
- **Fast Processing** - Analyze images in milliseconds
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
### Basic Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install ScreenshotScanner
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from screenshot_scanner import ScreenshotScanner
|
|
42
|
+
|
|
43
|
+
# Initialize scanner
|
|
44
|
+
scanner = ScreenshotScanner()
|
|
45
|
+
|
|
46
|
+
# Process an image (simple one-liner)
|
|
47
|
+
result = scanner.process("path/to/image.jpg")
|
|
48
|
+
|
|
49
|
+
print(result)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Example Output
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
{
|
|
56
|
+
'is_screenshot': True,
|
|
57
|
+
'score': 8,
|
|
58
|
+
'confidence': 80.0,
|
|
59
|
+
'reasons': ['Has alpha channel', 'Common aspect ratio: 1.78', 'Low ELA: 45.32', 'No EXIF data', 'High sharpness: 156.23']
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**That's it!** Just 3 lines of code to detect screenshots.
|
|
64
|
+
|
|
65
|
+
<!--
|
|
66
|
+
## đź“– Advanced Usage
|
|
67
|
+
|
|
68
|
+
### Accessing Detailed Information
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
result = scanner.process("image.jpg")
|
|
72
|
+
|
|
73
|
+
# Access individual fields
|
|
74
|
+
if result['is_screenshot']:
|
|
75
|
+
print(f"Screenshot detected with {result['confidence']:.1f}% confidence")
|
|
76
|
+
print(f"Detection score: {result['score']}/10")
|
|
77
|
+
print("Reasons:")
|
|
78
|
+
for reason in result['reasons']:
|
|
79
|
+
print(f" - {reason}")
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Verbose Mode (All Metrics)
|
|
83
|
+
|
|
84
|
+
For debugging or detailed analysis, use `is_screenshot()` with `verbose=True`:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
result = scanner.is_screenshot("image.jpg", verbose=True)
|
|
88
|
+
|
|
89
|
+
# Access detailed metrics
|
|
90
|
+
metrics = result['metrics']
|
|
91
|
+
print(f"Alpha channel: {metrics['alpha']}")
|
|
92
|
+
print(f"Aspect ratio: {metrics['aspect_ratio']}")
|
|
93
|
+
print(f"ELA std: {metrics['ela_std']}")
|
|
94
|
+
print(f"Sharpness: {metrics['sharpness']}")
|
|
95
|
+
# ... and 9 more metrics
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Custom Threshold
|
|
99
|
+
|
|
100
|
+
Adjust the detection sensitivity:
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
# More strict (fewer false positives)
|
|
104
|
+
strict_scanner = ScreenshotScanner(threshold=7)
|
|
105
|
+
|
|
106
|
+
# More lenient (fewer false negatives)
|
|
107
|
+
lenient_scanner = ScreenshotScanner(threshold=3)
|
|
108
|
+
|
|
109
|
+
result = strict_scanner.process("image.jpg")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Batch Processing
|
|
113
|
+
|
|
114
|
+
Process multiple images:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
import os
|
|
118
|
+
from screenshot_scanner import ScreenshotScanner
|
|
119
|
+
|
|
120
|
+
scanner = ScreenshotScanner()
|
|
121
|
+
image_folder = "path/to/images"
|
|
122
|
+
|
|
123
|
+
for filename in os.listdir(image_folder):
|
|
124
|
+
if filename.endswith(('.jpg', '.png', '.jpeg')):
|
|
125
|
+
image_path = os.path.join(image_folder, filename)
|
|
126
|
+
result = scanner.process(image_path)
|
|
127
|
+
print(f"{filename}: {result['is_screenshot']} (score: {result['score']})")
|
|
128
|
+
``` -->
|
|
129
|
+
|
|
130
|
+
## How It Works
|
|
131
|
+
|
|
132
|
+
ScreenshotScanner uses 13 different heuristic checks to determine if an image is a screenshot:
|
|
133
|
+
|
|
134
|
+
1. **Alpha Channel** - Screenshots often have transparency
|
|
135
|
+
2. **Aspect Ratio** - Common screen ratios (16:9, 4:3, etc.)
|
|
136
|
+
3. **Border Variance** - Uniform borders indicate screenshots
|
|
137
|
+
4. **ELA (Error Level Analysis)** - Lower compression artifacts in screenshots
|
|
138
|
+
5. **EXIF Data** - Screenshots typically lack camera metadata
|
|
139
|
+
6. **Horizontal Edges** - UI elements create horizontal patterns
|
|
140
|
+
7. **Moiré Patterns** - Photos of screens show moiré, screenshots don't
|
|
141
|
+
8. **Noise Analysis** - Screenshots have less sensor noise
|
|
142
|
+
9. **Sharpness** - Screenshots are typically sharper
|
|
143
|
+
10. **Solid Color Ratio** - UI elements have more solid colors
|
|
144
|
+
11. **Status Bar Detection** - Mobile screenshots often have status bars
|
|
145
|
+
12. **Text Confidence** - OCR works better on screenshot text
|
|
146
|
+
13. **Vertical Symmetry** - UI layouts are often symmetric
|
|
147
|
+
|
|
148
|
+
Each check contributes to a final score. A score ≥ 5 (default threshold) indicates a screenshot.
|
|
149
|
+
|
|
150
|
+
## Contributing
|
|
151
|
+
|
|
152
|
+
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
159
|
+
|
|
160
|
+
## Motivation
|
|
161
|
+
|
|
162
|
+
- There is no good tool without ML to detect screenshots. So i decided to come up with this.
|
|
163
|
+
|
|
164
|
+
## Contact
|
|
165
|
+
|
|
166
|
+
- **Author**: AzwadFawadHasan
|
|
167
|
+
- **GitHub**: [@AzwadFawadHasan](https://github.com/AzwadFawadHasan)
|
|
168
|
+
- **Issues**: [GitHub Issues](https://github.com/AzwadFawadHasan/ScreenshotScanner/issues)
|
|
169
|
+
|
|
170
|
+
## Star
|
|
171
|
+
|
|
172
|
+
If you find this project useful, please consider giving it a star on GitHub!
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
Made with ❤️ for better document verification by AzwadFawadHasan
|
|
177
|
+
|
|
178
|
+

|