Spaces:
Sleeping
Sleeping
File size: 3,795 Bytes
e19f48f 347d1a8 e19f48f 347d1a8 e19f48f 347d1a8 e19f48f 347d1a8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
---
title: Ring Sizer
emoji: "\U0001F48D"
colorFrom: blue
colorTo: purple
sdk: docker
app_port: 7860
---
# Ring Sizer
Local computer-vision CLI tool that measures **finger outer diameter** from a single image using a **credit card** as scale reference.
## What it does
- Detects a credit card and computes `px/cm` scale.
- Detects hand/finger with MediaPipe.
- Measures finger width in the ring-wearing zone.
- Supports dual edge modes:
- `contour` (v0 baseline)
- `sobel` (v1 refinement)
- `auto` (default, Sobel with quality fallback)
- `compare` (returns both method stats)
- Writes JSON output and always writes a result PNG next to it.
## Install
```bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
## Run
```bash
python measure_finger.py --input input/test_image.jpg --output output/result.json
```
### Common options
```bash
# Enable intermediate debug folders (card/finger/edge stages)
python measure_finger.py --input image.jpg --output output/result.json --debug
# Finger selection
python measure_finger.py --input image.jpg --output output/result.json --finger-index ring
# Force method
python measure_finger.py --input image.jpg --output output/result.json --edge-method contour
python measure_finger.py --input image.jpg --output output/result.json --edge-method sobel
# Compare contour vs sobel
python measure_finger.py --input image.jpg --output output/result.json --edge-method compare
# Sobel tuning
python measure_finger.py --input image.jpg --output output/result.json \
--edge-method sobel --sobel-threshold 15 --sobel-kernel-size 3 --no-subpixel
```
## CLI flags (current)
- `--input` (required)
- `--output` (required)
- `--debug` (boolean; saves intermediate debug folders)
- `--save-intermediate`
- `--finger-index {auto,index,middle,ring,pinky}` (default `index`)
- `--confidence-threshold` (default `0.7`)
- `--edge-method {auto,contour,sobel,compare}` (default `auto`)
- `--sobel-threshold` (default `15.0`)
- `--sobel-kernel-size {3,5,7}` (default `3`)
- `--no-subpixel`
- `--skip-card-detection` (testing only)
## Output JSON
```json
{
"finger_outer_diameter_cm": 1.78,
"confidence": 0.91,
"scale_px_per_cm": 203.46,
"quality_flags": {
"card_detected": true,
"finger_detected": true,
"view_angle_ok": true
},
"fail_reason": null,
"edge_method_used": "contour_fallback",
"method_comparison": {
"contour": {
"width_cm": 1.82,
"width_px": 371.2,
"std_dev_px": 3.8,
"coefficient_variation": 0.01,
"num_samples": 20,
"method": "contour"
},
"sobel": {
"width_cm": 1.78,
"width_px": 362.0,
"std_dev_px": 3.1,
"coefficient_variation": 0.008,
"num_samples": 140,
"subpixel_used": true,
"success_rate": 0.42,
"edge_quality_score": 0.81,
"method": "sobel"
},
"difference": {
"absolute_cm": -0.04,
"absolute_px": -9.2,
"relative_pct": -2.2,
"precision_improvement": 0.7
},
"recommendation": {
"use_sobel": true,
"reason": "quality_acceptable",
"preferred_method": "sobel"
},
"quality_comparison": {
"contour_cv": 0.01,
"sobel_cv": 0.008,
"sobel_quality_score": 0.81,
"sobel_gradient_strength": 0.82,
"sobel_consistency": 0.42,
"sobel_smoothness": 0.91,
"sobel_symmetry": 0.95
}
}
}
```
Notes:
- `edge_method_used` and `method_comparison` are optional (present when relevant).
- Result image path is auto-derived: `output/result.json` -> `output/result.png`.
## Documentation map
- Requirement docs: `doc/v{i}/PRD.md`, `doc/v{i}/Plan.md`, `doc/v{i}/Progress.md`
- Algorithms index: `doc/algorithms/README.md`
- Scripts: `script/README.md`
- Web demo: `web_demo/README.md`
|