$ cd ~/projects
Block Rev Image
// how it works
> Verify where a face photo appears online, then stamp the evidence immutably on Polygon Amoy.
---
## What It Does
Given a photo containing a face, this system:
1. **Detects the face** and generates a 512-dimensional ArcFace embedding
2. **Searches the web** using reverse image search (Google Lens via SerpApi)
3. **Verifies candidates** by comparing image similarity (pHash) and face similarity (ArcFace cosine)
4. **Records evidence** on Polygon Amoy testnet — a SHA-256 hash of all findings stored in a smart contract
5. **Produces a transaction** anyone can verify on [Amoy Polygonscan](htt
Verify where a face photo appears online, then stamp the evidence immutably on Polygon Amoy.
What It Does
Given a photo containing a face, this system:
- Detects the face and generates a 512-dimensional ArcFace embedding
- Searches the web using reverse image search (Google Lens via SerpApi)
- Verifies candidates by comparing image similarity (pHash) and face similarity (ArcFace cosine)
- Records evidence on Polygon Amoy testnet — a SHA-256 hash of all findings stored in a smart contract
- Produces a transaction anyone can verify on Amoy Polygonscan
Architecture
INPUT PHOTO
|
+---------------+---------------+
| | |
v v v
[Strategy A] [Strategy B] [Strategy C]
Single Search Cascaded Search Dual-Engine +
(direct match) (5 query forms) ArcFace gate
All 3 run in parallel via orchestrator.py
| | |
v v v
evidence_a.json evidence_b.json evidence_c.json
| | |
+---------------+---------------+
|
v
consensus check
|
v
final_report.json
|
v
Polygon Amoy TX
Strategy Comparison
| Property | Strategy A | Strategy B | Strategy C |
|---|---|---|---|
| Approach | Direct match | Multi-form cascade | Dual-engine + two-gate |
| Query forms | 1 (original) | 5 (orig, face, 2x, ctx, norm) | 1 (original) |
| Search engines | Google Lens | Google Lens (cascaded) | Google Lens + TinEye |
| Verification gates | 1 (image sim) | 1 (image sim) | 2 (image + face) |
| Best for | Clean demo | Hard-to-find images | Most defensible result |
| Runtime | ~10s | ~15-40s | ~20-30s |
Quick Start
Prerequisites
- Python 3.10+
- A SerpApi API key (free: 100 searches/month)
- MetaMask wallet on Polygon Amoy testnet (free test POL from faucet)
1. Clone & Install
git clone https://github.com/vaibhav7087/block_rev_image.git
cd block_rev_image
pip install -r requirements.txt
2. Configure
cp .env.example .env
Edit .env with your keys:
SERPAPI_KEY=your_serpapi_key_here
WALLET_PRIVATE_KEY=0xYOUR_PRIVATE_KEY_HERE
POLYGON_AMOY_RPC=https://polygon-amoy.g.alchemy.com/v2/YOUR_KEY
3. Deploy Contract
python -c "from src.blockchain.contract import deploy_contract; print(deploy_contract())"
Copy the contract_address into your .env:
CONTRACT_ADDRESS=0x...
4. Run
# Single strategy
python src/main.py --image samples/test.jpg --strategy A
# All 3 strategies in parallel
python src/main.py --image samples/test.jpg --strategy ALL
Or use the one-click demo:
bash run_demo.sh
Project Structure
reverse_face/
├── src/
│ ├── main.py # CLI entry point
│ ├── orchestrator.py # Parallel strategy launcher
│ ├── strategy_a.py # Strategy A pipeline
│ ├── strategy_b.py # Strategy B pipeline
│ ├── strategy_c.py # Strategy C pipeline
│ ├── face/
│ │ ├── detector.py # InsightFace face detection
│ │ ├── embedding.py # ArcFace 512-dim embedding
│ │ └── multi_crop.py # 5 query form generator
│ ├── reverse_search/
│ │ ├── google_lens.py # SerpApi Google Lens
│ │ ├── tineye.py # TinEye API
│ │ ├── cascade.py # Multi-form cascade engine
│ │ └── dual_search.py # Parallel Lens + TinEye
│ ├── verification/
│ │ ├── similarity.py # pHash image similarity
│ │ ├── candidate_ranker.py # Composite scoring
│ │ ├── parallel_verifier.py # Async multi-candidate
│ │ └── two_gate.py # Dual-gate decision logic
│ ├── evidence/
│ │ ├── canonicalize.py # Deterministic JSON
│ │ └── hashing.py # SHA-256
│ ├── blockchain/
│ │ ├── contract.py # Web3.py, deploy + register
│ │ └── registry_abi.json # Contract ABI
│ └── utils/
│ ├── image_io.py # Image load/save
│ └── logging.py # Structured logging
├── contracts/
│ └── VerificationRegistry.sol
├── strategies/ # Architecture documentation
├── samples/ # Test images
├── output/ # Evidence JSONs + reports
├── requirements.txt
├── .env.example
└── run_demo.sh
Smart Contract
The VerificationRegistry contract on Polygon Amoy stores SHA-256 hashes of evidence:
function register(bytes32 evidenceHash, string calldata pipelineVersion) external
function verify(bytes32 evidenceHash) external view returns (Record memory)
Each registration is:
- Immutable — cannot be overwritten
- Timestamped — block timestamp proves sequence
- Auditable — compute SHA-256 of evidence JSON and compare to on-chain hash
Environment Variables
| Variable | Required | Description |
|---|---|---|
SERPAPI_KEY |
Yes | SerpApi API key for Google Lens |
TINEYE_API_KEY |
No | TinEye API key (Strategy C) |
WALLET_PRIVATE_KEY |
Yes | MetaMask private key for Polygon Amoy |
CONTRACT_ADDRESS |
Yes | Deployed VerificationRegistry address |
POLYGON_AMOY_RPC |
Yes | Polygon Amoy RPC endpoint |
INSIGHTFACE_MODEL |
No | Face model (default: buffalo_l) |
USE_GPU |
No | Set 1 for GPU acceleration |
DEFAULT_STRATEGY |
No | A, B, C, or ALL (default: ALL) |
Evidence Format
Each strategy produces a canonical JSON:
{
"schema_version": "1.0",
"strategy": "A_exact_provenance",
"case_id": "CASE-a1b2c3d4e5f6",
"query_image_sha256": "...",
"face_detected": true,
"face_embedding_model": "ArcFace-R100 (buffalo_l)",
"match_found": true,
"matched_url": "https://instagram.com/p/...",
"image_similarity": 0.93,
"face_similarity": 0.91,
"combined_score": 0.922,
"retrieved_at": "2026-09-07T18:30:00+00:00",
"pipeline_version": "strategy_a_v1.0"
}
The SHA-256 of this canonical JSON is what gets stored on-chain.
Limitations
| Limitation | Mitigation |
|---|---|
| Reverse search only finds indexed images | Works best for publicly indexed social media |
| Face similarity ≠ identity proof | Output says "visually similar face", never "this is this person" |
| SerpApi has rate limits (100/month free) | Mock mode available for testing |
| Blockchain timestamp is not legal proof | Documents sequence, not legal identity |
Demo Output
$ python src/main.py --image samples/test.jpg --strategy ALL
[ORCH] Spawning 3 strategy worker(s): A, B, C
==================================================
STRATEGY A — Exact / Near-Exact Provenance
==================================================
[STRAT-A] [1/6] Loading image OK (400x400)
[STRAT-A] [2/6] Detecting face OK (score=0.897)
[STRAT-A] [3/6] Generating ArcFace embedding OK (512-dim)
[STRAT-A] [4/6] Reverse image search (Google Lens) OK (5 candidates)
[STRAT-A] [5/6] Candidate verification OK (score=1.000)
[STRAT-A] [6/6] Blockchain registration OK
Strategy A completed in 15.3s
--- Strategy A ---
Match Found : YES
Image Sim : 1.0
Face Sim : 1.0
Combined : 1.0
TX Hash : 0xc9ecda780fbbedb6...
Explorer : https://amoy.polygonscan.com/tx/0xc9ecda780fbbedb6...
License
MIT
Acknowledgments
- InsightFace — ArcFace R100 face recognition
- Polygon — Amoy testnet infrastructure
- SerpApi — Google Lens reverse image search
- imagehash — Perceptual hashing
// stack
Python