Update README.md
Browse files
README.md
CHANGED
|
@@ -1,3 +1,202 @@
|
|
| 1 |
-
---
|
| 2 |
-
license: cc-by-nc-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: cc-by-nc-4.0
|
| 3 |
+
tags:
|
| 4 |
+
- ruler-reading
|
| 5 |
+
- image-scale-estimation
|
| 6 |
+
- computer-vision
|
| 7 |
+
- onnx
|
| 8 |
+
- medical-imaging
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
+
# RulerNet
|
| 12 |
+
|
| 13 |
+
RulerNet estimates image scale from a visible ruler by detecting centimeter
|
| 14 |
+
marks and fitting them with a geometric progression. It is designed to remain
|
| 15 |
+
robust when a ruler is rotated, viewed in perspective, or partially occluded.
|
| 16 |
+
|
| 17 |
+
This repository accompanies **“RulerNet: Learning Perspective-Invariant Ruler
|
| 18 |
+
Representations for Robust Image Scale Estimation,”** published in
|
| 19 |
+
*Computerized Medical Imaging and Graphics*.
|
| 20 |
+
|
| 21 |
+
Try the interactive CPU demo: [RulerNet-Demo](https://huggingface.co/spaces/ymp5078/RulerNet-Demo).
|
| 22 |
+
For training and evaluation code, see the [GitHub repository](https://github.com/ymp5078/RulerNet).
|
| 23 |
+
|
| 24 |
+
## Repository contents
|
| 25 |
+
|
| 26 |
+
| Location | Contents | Use |
|
| 27 |
+
| --- | --- | --- |
|
| 28 |
+
| `data/AnyRuler.zip` | AnyRuler images and centimeter-mark annotations (998 MB) | Training and testing |
|
| 29 |
+
| `data/Rulers2023_scale.zip` | Rulers2023 images and centimeter-mark annotations (2.46 GB) | Evaluation |
|
| 30 |
+
| `weights/final_rulernet.zip` | Final RulerNet checkpoint (131 MB) | PyTorch inference, evaluation, or fine-tuning |
|
| 31 |
+
| `weights/final_deepgp.zip` | DeepGP solver checkpoint (112 MB) | Optional faster geometric-progression solving |
|
| 32 |
+
| `weights/pretrained_rulernet.zip` | Synthetic-data pretrained RulerNet checkpoint (158 MB) | Initialize training to reproduce the paper setup |
|
| 33 |
+
| `model.onnx` | CPU-ready ONNX export (57.1 MB) | Lightweight deployment and inference |
|
| 34 |
+
|
| 35 |
+
## Download files
|
| 36 |
+
|
| 37 |
+
Install the Hugging Face Hub client:
|
| 38 |
+
|
| 39 |
+
```bash
|
| 40 |
+
pip install -U huggingface_hub
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
Download individual archives with the CLI:
|
| 44 |
+
|
| 45 |
+
```bash
|
| 46 |
+
hf download ymp5078/RulerNet data/AnyRuler.zip --local-dir .
|
| 47 |
+
hf download ymp5078/RulerNet data/Rulers2023_scale.zip --local-dir .
|
| 48 |
+
hf download ymp5078/RulerNet weights/final_rulernet.zip --local-dir .
|
| 49 |
+
hf download ymp5078/RulerNet weights/final_deepgp.zip --local-dir .
|
| 50 |
+
hf download ymp5078/RulerNet weights/pretrained_rulernet.zip --local-dir .
|
| 51 |
+
hf download ymp5078/RulerNet model.onnx --local-dir .
|
| 52 |
+
```
|
| 53 |
+
|
| 54 |
+
Extract an archive before using it:
|
| 55 |
+
|
| 56 |
+
```bash
|
| 57 |
+
unzip data/AnyRuler.zip -d data/
|
| 58 |
+
unzip weights/final_rulernet.zip -d weights/
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
## Datasets
|
| 62 |
+
|
| 63 |
+
### AnyRuler
|
| 64 |
+
|
| 65 |
+
`AnyRuler.zip` contains 1,416 annotated ruler images. Use it for training or
|
| 66 |
+
for evaluating a model with centimeter-mark labels. After extraction, provide
|
| 67 |
+
the extracted directory to the code repository with `--data-dir`.
|
| 68 |
+
|
| 69 |
+
```text
|
| 70 |
+
<data-dir>/
|
| 71 |
+
├── ruler_image/ # input images
|
| 72 |
+
└── cm_marks/ # matching JSON centimeter-mark annotations
|
| 73 |
+
```
|
| 74 |
+
|
| 75 |
+
### Rulers2023
|
| 76 |
+
|
| 77 |
+
`Rulers2023_scale.zip` contains the Rulers2023 evaluation images together
|
| 78 |
+
with centimeter-mark annotations. Use it with `--test-dataset ruler2023`.
|
| 79 |
+
|
| 80 |
+
```text
|
| 81 |
+
<data-dir>/
|
| 82 |
+
├── real-test/images/ # evaluation images
|
| 83 |
+
└── real-test-marks/ # JSON centimeter-mark annotations
|
| 84 |
+
```
|
| 85 |
+
|
| 86 |
+
## PyTorch checkpoints
|
| 87 |
+
|
| 88 |
+
Clone the code repository and install its dependencies before using the
|
| 89 |
+
checkpoints:
|
| 90 |
+
|
| 91 |
+
```bash
|
| 92 |
+
git clone https://github.com/ymp5078/RulerNet.git
|
| 93 |
+
cd RulerNet
|
| 94 |
+
pip install -r requirements.txt
|
| 95 |
+
```
|
| 96 |
+
|
| 97 |
+
Use the final RulerNet checkpoint for inference:
|
| 98 |
+
|
| 99 |
+
```bash
|
| 100 |
+
python inference.py \
|
| 101 |
+
--config configs/config_graphic_gen.yaml \
|
| 102 |
+
--checkpoint <path-to-final_rulernet>/checkpoints/epoch=199-step=20000.ckpt \
|
| 103 |
+
--img-size 768 768 \
|
| 104 |
+
--ruler-mode optimize \
|
| 105 |
+
--image-path <image-or-directory> \
|
| 106 |
+
--result-dir <output-directory>
|
| 107 |
+
```
|
| 108 |
+
|
| 109 |
+
Append the following option to the inference or evaluation command to use the
|
| 110 |
+
optional learned DeepGP geometric-progression solver:
|
| 111 |
+
|
| 112 |
+
```bash
|
| 113 |
+
--gp-solver-path <path-to-final_deepgp>/checkpoints/epoch=999-step=1200000.ckpt
|
| 114 |
+
```
|
| 115 |
+
|
| 116 |
+
To reproduce the pretraining initialization used in the paper, start training
|
| 117 |
+
from the checkpoint in `pretrained_rulernet.zip`:
|
| 118 |
+
|
| 119 |
+
```bash
|
| 120 |
+
python main.py \
|
| 121 |
+
--config configs/config_pretrain.yaml \
|
| 122 |
+
--data-dir <anyruler-data-dir> \
|
| 123 |
+
--checkpoint <path-to-pretrained_rulernet>/checkpoints/epoch=79-step=128240.ckpt
|
| 124 |
+
```
|
| 125 |
+
|
| 126 |
+
The synthetic-ruler images used for pretraining are reproducible with
|
| 127 |
+
[`sdxl_inference.py`](https://github.com/ymp5078/RulerNet/blob/main/sdxl_inference.py);
|
| 128 |
+
they are not distributed as a separate archive.
|
| 129 |
+
|
| 130 |
+
## ONNX inference
|
| 131 |
+
|
| 132 |
+
`model.onnx` is the CPU-ready export used by the [interactive demo](https://huggingface.co/spaces/ymp5078/RulerNet-Demo).
|
| 133 |
+
It expects a float32 tensor named `input` with shape **`(1, 3, 768, 768)`**:
|
| 134 |
+
an RGB image scaled to `[0, 1]`, resized while preserving aspect ratio, and
|
| 135 |
+
zero-padded to 768 × 768.
|
| 136 |
+
|
| 137 |
+
Install the lightweight runtime:
|
| 138 |
+
|
| 139 |
+
```bash
|
| 140 |
+
pip install -U huggingface_hub onnxruntime numpy pillow
|
| 141 |
+
```
|
| 142 |
+
|
| 143 |
+
The following example downloads the model, prepares an image exactly as in the
|
| 144 |
+
demo, and runs inference on CPU:
|
| 145 |
+
|
| 146 |
+
```python
|
| 147 |
+
import numpy as np
|
| 148 |
+
import onnxruntime as ort
|
| 149 |
+
from huggingface_hub import hf_hub_download
|
| 150 |
+
from PIL import Image
|
| 151 |
+
|
| 152 |
+
model_path = hf_hub_download(repo_id="ymp5078/RulerNet", filename="model.onnx")
|
| 153 |
+
session = ort.InferenceSession(model_path, providers=["CPUExecutionProvider"])
|
| 154 |
+
|
| 155 |
+
def preprocess(image_path):
|
| 156 |
+
image = np.asarray(Image.open(image_path).convert("RGB"), dtype=np.float32) / 255.0
|
| 157 |
+
height, width = image.shape[:2]
|
| 158 |
+
scale = min(768 / width, 768 / height)
|
| 159 |
+
new_width, new_height = int(width * scale), int(height * scale)
|
| 160 |
+
|
| 161 |
+
resized = Image.fromarray((image * 255).astype(np.uint8)).resize((new_width, new_height))
|
| 162 |
+
canvas = np.zeros((768, 768, 3), dtype=np.float32)
|
| 163 |
+
top = (768 - new_height) // 2
|
| 164 |
+
left = (768 - new_width) // 2
|
| 165 |
+
canvas[top:top + new_height, left:left + new_width] = np.asarray(resized) / 255.0
|
| 166 |
+
|
| 167 |
+
return np.transpose(canvas, (2, 0, 1))[None].astype(np.float32), (scale, top, left)
|
| 168 |
+
|
| 169 |
+
input_tensor, transform = preprocess("ruler.jpg")
|
| 170 |
+
init_point, dist, ratio, direction, points_info = session.run(
|
| 171 |
+
None, {"input": input_tensor}
|
| 172 |
+
)
|
| 173 |
+
|
| 174 |
+
print("initial point:", init_point[0])
|
| 175 |
+
print("base distance:", dist[0])
|
| 176 |
+
print("geometric-progression ratio:", ratio[0])
|
| 177 |
+
print("ruler direction:", direction[0])
|
| 178 |
+
print("point count and bounds:", points_info[0])
|
| 179 |
+
```
|
| 180 |
+
|
| 181 |
+
The five outputs are:
|
| 182 |
+
|
| 183 |
+
| Output | Meaning |
|
| 184 |
+
| --- | --- |
|
| 185 |
+
| `init_point` | Predicted starting ruler-mark location in the 768 × 768 processed image |
|
| 186 |
+
| `dist` | Base distance between generated marks |
|
| 187 |
+
| `ratio` | Geometric-progression ratio between consecutive mark spacings |
|
| 188 |
+
| `direction` | Unit direction vector along the ruler |
|
| 189 |
+
| `points_info` | Number of generated points followed by `[min_x, min_y, max_x, max_y]` valid bounds |
|
| 190 |
+
|
| 191 |
+
To reconstruct the full set of ruler-mark positions and calculate the median
|
| 192 |
+
pixels-per-centimeter value, use the post-processing in the
|
| 193 |
+
[demo implementation](https://huggingface.co/spaces/ymp5078/RulerNet-Demo/blob/main/app.py).
|
| 194 |
+
The resulting coordinates are in the padded 768 × 768 image. To map a point
|
| 195 |
+
`(x, y)` back to the original image, use `(x - left) / scale` and
|
| 196 |
+
`(y - top) / scale`, where `scale`, `top`, and `left` are returned by
|
| 197 |
+
`preprocess`.
|
| 198 |
+
|
| 199 |
+
## License and commercial use
|
| 200 |
+
|
| 201 |
+
This material is licensed under [CC BY-NC 4.0](https://creativecommons.org/licenses/by-nc/4.0/).
|
| 202 |
+
For commercial-use licensing inquiries, contact [jwang@ist.psu.edu](mailto:jwang@ist.psu.edu).
|