# Palmistry CV/ML — reference microservice (optional)

**Reference only. Not part of the Laravel app and not required to run VPandit.**

The VPandit palmistry module works out-of-the-box with an on-device (browser
Canvas) heuristic for line scoring, and lets an analyst place mounts and special
signs by hand. This folder is the *optional* external CV/ML service that an admin
can point the app at to get automated line geometry, mount segmentation and
sign detection.

## Files

| File | Purpose |
|------|---------|
| `cv_service.py` | FastAPI service implementing the app's CV contract: MediaPipe hand-landmark mount segmentation, Frangi-ridge line scoring, and STAR/CROSS/GRILLE/ISLAND heuristics. Returns `scores`, `features`, `mounts`. |
| `schema_postgres.sql` | Normalized PostgreSQL schema (core lines/characteristics/predictions + mounts + special signs + sign predictions + client readings/detected features). For teams standing up a dedicated CV store. The live app self-provisions the equivalent MySQL tables. |

## Run the service

```bash
pip install fastapi uvicorn mediapipe opencv-python numpy scikit-image pillow
uvicorn cv_service:app --host 0.0.0.0 --port 8099
# optional: set a shared secret
#   edit API_KEY in cv_service.py (or wrap with your own auth)
```

## Wire it into VPandit

1. Sign in as an admin.
2. Go to **Palmistry → CV Service** (the `PalmCvSettings` page).
3. Set **Endpoint** to `http://<host>:8099/score`, **Enabled** on, and a **Key**
   matching `API_KEY` (leave blank if you left `API_KEY = None`).
4. In the Palm Reader, click **🤖 Score with AI CV**. The service's line scores,
   detected polylines, and any special signs/mounts flow straight into the tool;
   the analyst reviews and Analyzes as usual.

## Contract

Request (POSTed by `PalmistryController::cv`):

```json
{ "left_image": "data:image/...", "right_image": "data:image/...",
  "dominant_hand": "RIGHT", "lines": ["life_line","head_line","heart_line","fate_line","sun_line"] }
```

Response:

```json
{
  "scores":   [{ "hand_side":"RIGHT","line_key":"life_line","presence":0.8,"depth":0.6,"continuity":0.7,"vector":[[0.32,0.31],...] }],
  "features": [{ "hand_side":"RIGHT","feature_key":"GRILLE","mount_key":"VENUS","line_key":null,"confidence":0.6,"box":{"x":0.28,"y":0.72} }],
  "mounts":   [{ "hand_side":"RIGHT","mount_key":"JUPITER","box":[0.22,0.31,0.38,0.47] }]
}
```

The Laravel proxy clamps scores to 0–1, normalises hand sides, and passes
`features`/`mounts` through to the analyzer, which combines them with the line
reading (island degrades a line, square protects it, star/trishul on
Jupiter/Apollo amplifies) and returns the compiled `special_features`.

## Notes

- The heuristics in `cv_service.py` are deliberately simple and meant as a
  starting scaffold; replace `_ridge`, `_line_signs` and `_mount_signs` with a
  trained U-Net / classifier for production accuracy.
- All coordinates may be returned as pixels or 0–1 fractions — the app
  normalises either against each image's natural size.
