RulerNet / README.md
nielsr's picture
nielsr HF Staff
Add pipeline tag and paper link
3c2e84a verified
|
Raw
History Blame
7.32 kB
---
license: cc-by-nc-4.0
pipeline_tag: keypoint-detection
tags:
- ruler-reading
- image-scale-estimation
- computer-vision
- onnx
---
# RulerNet
RulerNet estimates image scale from a visible ruler by detecting centimeter
marks and fitting them with a geometric progression. It is designed to remain
robust when a ruler is rotated, viewed in perspective, or partially occluded.
This repository accompanies **β€œRulerNet: Learning Perspective-Invariant Ruler
Representations for Robust Image Scale Estimation,”** published in
*Computerized Medical Imaging and Graphics*. Paper: [RulerNet: Learning Perspective-Invariant Ruler Representations for Robust Image Scale Estimation](https://huggingface.co/papers/2507.07077).
Try the interactive CPU demo: [RulerNet-Demo](https://huggingface.co/spaces/ymp5078/RulerNet-Demo).
For training and evaluation code, see the [GitHub repository](https://github.com/ymp5078/RulerNet).
## Repository contents
| Location | Contents | Use |
| --- | --- | --- |
| `data/AnyRuler.zip` | AnyRuler images and centimeter-mark annotations (998 MB) | Training and testing |
| `data/Rulers2023_scale.zip` | Rulers2023 images and centimeter-mark annotations (2.46 GB) | Evaluation |
| `weights/final_rulernet.zip` | Final RulerNet checkpoint (131 MB) | PyTorch inference, evaluation, or fine-tuning |
| `weights/final_deepgp.zip` | DeepGP solver checkpoint (112 MB) | Optional faster geometric-progression solving |
| `weights/pretrained_rulernet.zip` | Synthetic-data pretrained RulerNet checkpoint (158 MB) | Initialize training to reproduce the paper setup |
| `model.onnx` | CPU-ready ONNX export (57.1 MB) | Lightweight deployment and inference |
## Download files
Install the Hugging Face Hub client:
```bash
pip install -U huggingface_hub
```
Download individual archives with the CLI:
```bash
hf download ymp5078/RulerNet data/AnyRuler.zip --local-dir .
hf download ymp5078/RulerNet data/Rulers2023_scale.zip --local-dir .
hf download ymp5078/RulerNet weights/final_rulernet.zip --local-dir .
hf download ymp5078/RulerNet weights/final_deepgp.zip --local-dir .
hf download ymp5078/RulerNet weights/pretrained_rulernet.zip --local-dir .
hf download ymp5078/RulerNet model.onnx --local-dir .
```
Extract an archive before using it:
```bash
unzip data/AnyRuler.zip -d data/
unzip weights/final_rulernet.zip -d weights/
```
## Datasets
### AnyRuler
`AnyRuler.zip` contains 1,416 annotated ruler images. Use it for training or
for evaluating a model with centimeter-mark labels. After extraction, provide
the extracted directory to the code repository with `--data-dir`.
```text
<data-dir>/
β”œβ”€β”€ ruler_image/ # input images
└── cm_marks/ # matching JSON centimeter-mark annotations
```
### Rulers2023
`Rulers2023_scale.zip` contains the Rulers2023 evaluation images together
with centimeter-mark annotations. Use it with `--test-dataset ruler2023`.
```text
<data-dir>/
β”œβ”€β”€ real-test/images/ # evaluation images
└── real-test-marks/ # JSON centimeter-mark annotations
```
## PyTorch checkpoints
Clone the code repository and install its dependencies before using the
checkpoints:
```bash
git clone https://github.com/ymp5078/RulerNet.git
cd RulerNet
pip install -r requirements.txt
```
Use the final RulerNet checkpoint for inference:
```bash
python inference.py \
--config configs/config_graphic_gen.yaml \
--checkpoint <path-to-final_rulernet>/checkpoints/epoch=199-step=20000.ckpt \
--img-size 768 768 \
--ruler-mode optimize \
--image-path <image-or-directory> \
--result-dir <output-directory>
```
Append the following option to the inference or evaluation command to use the
optional learned DeepGP geometric-progression solver:
```bash
--gp-solver-path <path-to-final_deepgp>/checkpoints/epoch=999-step=1200000.ckpt
```
To reproduce the pretraining initialization used in the paper, start training
from the checkpoint in `pretrained_rulernet.zip`:
```bash
python main.py \
--config configs/config_pretrain.yaml \
--data-dir <anyruler-data-dir> \
--checkpoint <path-to-pretrained_rulernet>/checkpoints/epoch=79-step=128240.ckpt
```
The synthetic-ruler images used for pretraining are reproducible with
[`sdxl_inference.py`](https://github.com/ymp5078/RulerNet/blob/main/sdxl_inference.py);
they are not distributed as a separate archive.
## ONNX inference
`model.onnx` is the CPU-ready export used by the [interactive demo](https://huggingface.co/spaces/ymp5078/RulerNet-Demo).
It expects a float32 tensor named `input` with shape **`(1, 3, 768, 768)`**:
an RGB image scaled to `[0, 1]`, resized while preserving aspect ratio, and
zero-padded to 768 Γ— 768.
Install the lightweight runtime:
```bash
pip install -U huggingface_hub onnxruntime numpy pillow
```
The following example downloads the model, prepares an image exactly as in the
demo, and runs inference on CPU:
```python
import numpy as np
import onnxruntime as ort
from huggingface_hub import hf_hub_download
from PIL import Image
model_path = hf_hub_download(repo_id="ymp5078/RulerNet", filename="model.onnx")
session = ort.InferenceSession(model_path, providers=["CPUExecutionProvider"])
def preprocess(image_path):
image = np.asarray(Image.open(image_path).convert("RGB"), dtype=np.float32) / 255.0
height, width = image.shape[:2]
scale = min(768 / width, 768 / height)
new_width, new_height = int(width * scale), int(height * scale)
resized = Image.fromarray((image * 255).astype(np.uint8)).resize((new_width, new_height))
canvas = np.zeros((768, 768, 3), dtype=np.float32)
top = (768 - new_height) // 2
left = (768 - new_width) // 2
canvas[top:top + new_height, left:left + new_width] = np.asarray(resized) / 255.0
return np.transpose(canvas, (2, 0, 1))[None].astype(np.float32), (scale, top, left)
input_tensor, transform = preprocess("ruler.jpg")
init_point, dist, ratio, direction, points_info = session.run(
None, {"input": input_tensor}
)
print("initial point:", init_point[0])
print("base distance:", dist[0])
print("geometric-progression ratio:", ratio[0])
print("ruler direction:", direction[0])
print("point count and bounds:", points_info[0])
```
The five outputs are:
| Output | Meaning |
| --- | --- |
| `init_point` | Predicted starting ruler-mark location in the 768 Γ— 768 processed image |
| `dist` | Base distance between generated marks |
| `ratio` | Geometric-progression ratio between consecutive mark spacings |
| `direction` | Unit direction vector along the ruler |
| `points_info` | Number of generated points followed by `[min_x, min_y, max_x, max_y]` valid bounds |
To reconstruct the full set of ruler-mark positions and calculate the median
pixels-per-centimeter value, use the post-processing in the
[demo implementation](https://huggingface.co/spaces/ymp5078/RulerNet-Demo/blob/main/app.py).
The resulting coordinates are in the padded 768 Γ— 768 image. To map a point
`(x, y)` back to the original image, use `(x - left) / scale` and
`(y - top) / scale`, where `scale`, `top`, and `left` are returned by
`preprocess`.
## License and commercial use
This material is licensed under [CC BY-NC 4.0](https://creativecommons.org/licenses/by-nc/4.0/).
For commercial-use licensing inquiries, contact [jwang@ist.psu.edu](mailto:jwang@ist.psu.edu).