Metadata-Version: 2.4
Name: shape-matcher
Version: 3.0.0
Summary: Edge-based object matching using Chamfer distance for CAPTCHA solving
License: MIT
Project-URL: Homepage, https://github.com/your-org/captcha_same_object
Project-URL: Repository, https://github.com/your-org/captcha_same_object
Keywords: captcha,shape-matching,chamfer-distance,computer-vision,tiktok
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Image Processing
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: opencv-python>=4.5.0
Requires-Dist: numpy>=1.19.0
Provides-Extra: ai
Requires-Dist: ultralytics>=8.0.0; extra == "ai"

# Shape Matcher

Edge-based object matching using Chamfer distance. Finds the most similar pair of objects in an image.

## Algorithm

1. **LAB Chroma Mask** - Separates colored objects from background (catches faint colors, ignores shadows)
2. **Binary Patch Normalization** - Converts each object contour to a square binary patch
3. **Edge Extraction** - Gets silhouette edge from binary patch (no fake edges from shading)
4. **Chamfer Distance** - Compares edges with rotation sweep for rotation invariance

## Installation

```bash
pip install -r requirements.txt
```

## Usage

### CLI

```bash
# Basic usage
python -m shape_matcher --image examples/image.png --out result.png

# With options
python -m shape_matcher -i examples/image.png -o result.png --chroma_thr 5.0 --angles_step 10 --debug
```

### Python API

```python
from shape_matcher import Config, MatcherFactory
import cv2

# Load image
img = cv2.imread("examples/image.png")

# Create matcher
config = Config.default()
matcher = MatcherFactory.create(config)

# Process
objects, best_match, result_img = matcher.process(img)

if best_match:
    print(f"Best match: Object {best_match.idx1} <-> Object {best_match.idx2}")
    print(f"Chamfer distance: {best_match.chamfer_distance:.4f}")
```

## Options

| Option | Default | Description |
|--------|---------|-------------|
| `--chroma_thr` | 6.0 | LAB chroma threshold (lower = catch fainter colors) |
| `--min_area` | 300 | Minimum contour area |
| `--min_wh` | 20 | Minimum bbox width/height |
| `--min_hole_area_ratio` | 0.02 | Minimum hole area ratio vs parent contour |
| `--hole_mismatch_penalty` | 2.0 | Penalty per hole-count mismatch |
| `--hole_area_weight` | 1.0 | Weight for hole area ratio difference |
| `--hu_weight` | 0.6 | Weight for Hu moment distance |
| `--angles_step` | 15 | Rotation step in degrees (smaller = more accurate) |
| `--patch` | 96 | Normalized patch size |
| `--debug` | False | Enable debug logging |

## Project Structure

```
TikTok-Captcha-Solver/
├── shape_matcher/          # Main package
│   ├── __init__.py         # Package exports
│   ├── __main__.py         # CLI runner
│   ├── config.py           # Configuration classes
│   ├── models.py           # DetectedObject, MatchResult
│   ├── protocols.py        # Abstract interfaces
│   ├── mask.py             # LABChromaMaskGenerator
│   ├── patch.py            # PatchProcessor
│   ├── chamfer.py          # ChamferDistance
│   ├── extractor.py        # ContourObjectExtractor
│   ├── similarity.py       # EdgeChamferSimilarity
│   ├── renderer.py         # DefaultResultRenderer
│   ├── factory.py          # MatcherFactory
│   └── service.py          # MatcherService
├── examples/               # Test images
├── requirements.txt
└── README.md
```

## License

MIT
