img-phy-sim 0.4__tar.gz → 0.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {img_phy_sim-0.4 → img_phy_sim-0.8}/PKG-INFO +196 -19
- {img_phy_sim-0.4 → img_phy_sim-0.8}/README.md +186 -17
- {img_phy_sim-0.4 → img_phy_sim-0.8}/img_phy_sim/__init__.py +16 -0
- img_phy_sim-0.8/img_phy_sim/data.py +417 -0
- img_phy_sim-0.8/img_phy_sim/eval.py +146 -0
- {img_phy_sim-0.4 → img_phy_sim-0.8}/img_phy_sim/img.py +35 -8
- img_phy_sim-0.8/img_phy_sim/ism.py +828 -0
- img_phy_sim-0.8/img_phy_sim/ism_slow.py +498 -0
- img_phy_sim-0.8/img_phy_sim/math.py +185 -0
- {img_phy_sim-0.4 → img_phy_sim-0.8}/img_phy_sim/ray_tracing.py +59 -54
- {img_phy_sim-0.4 → img_phy_sim-0.8}/img_phy_sim.egg-info/PKG-INFO +196 -19
- {img_phy_sim-0.4 → img_phy_sim-0.8}/img_phy_sim.egg-info/SOURCES.txt +4 -0
- img_phy_sim-0.8/img_phy_sim.egg-info/requires.txt +12 -0
- {img_phy_sim-0.4 → img_phy_sim-0.8}/pyproject.toml +1 -1
- {img_phy_sim-0.4 → img_phy_sim-0.8}/setup.py +47 -4
- img_phy_sim-0.4/img_phy_sim/math.py +0 -154
- img_phy_sim-0.4/img_phy_sim.egg-info/requires.txt +0 -4
- {img_phy_sim-0.4 → img_phy_sim-0.8}/img_phy_sim.egg-info/dependency_links.txt +0 -0
- {img_phy_sim-0.4 → img_phy_sim-0.8}/img_phy_sim.egg-info/top_level.txt +0 -0
- {img_phy_sim-0.4 → img_phy_sim-0.8}/setup.cfg +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: img-phy-sim
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8
|
|
4
4
|
Summary: Physical Simulations on Images.
|
|
5
5
|
Home-page: https://github.com/M-106/Image-Physics-Simulation
|
|
6
|
-
Download-URL: https://github.com/M-106/Image-Physics-Simulation/archive/
|
|
6
|
+
Download-URL: https://github.com/M-106/Image-Physics-Simulation/archive/v_04.tar.gz
|
|
7
7
|
Author: Tobia Ippolito
|
|
8
8
|
Project-URL: Documentation, https://M-106.github.io/Image-Physics-Simulation/img_phy_sim
|
|
9
9
|
Project-URL: Source, https://github.com/M-106/Image-Physics-Simulation
|
|
@@ -21,6 +21,13 @@ Requires-Dist: numpy
|
|
|
21
21
|
Requires-Dist: opencv-python
|
|
22
22
|
Requires-Dist: matplotlib
|
|
23
23
|
Requires-Dist: scikit-image
|
|
24
|
+
Requires-Dist: joblib
|
|
25
|
+
Requires-Dist: shapely
|
|
26
|
+
Provides-Extra: full
|
|
27
|
+
Requires-Dist: torch; extra == "full"
|
|
28
|
+
Requires-Dist: torchvision; extra == "full"
|
|
29
|
+
Requires-Dist: datasets==3.6.0; extra == "full"
|
|
30
|
+
Requires-Dist: prime_printer; extra == "full"
|
|
24
31
|
Dynamic: author
|
|
25
32
|
Dynamic: classifier
|
|
26
33
|
Dynamic: description
|
|
@@ -29,6 +36,7 @@ Dynamic: download-url
|
|
|
29
36
|
Dynamic: home-page
|
|
30
37
|
Dynamic: keywords
|
|
31
38
|
Dynamic: project-url
|
|
39
|
+
Dynamic: provides-extra
|
|
32
40
|
Dynamic: requires-dist
|
|
33
41
|
Dynamic: summary
|
|
34
42
|
|
|
@@ -44,10 +52,14 @@ Contents:
|
|
|
44
52
|
- [Raytracing Computation](#raytracing-computation)
|
|
45
53
|
- [Raytracing Tutorial](#raytracing-tutorial)
|
|
46
54
|
- [Performance Test](#performance-test)
|
|
55
|
+
- [Ray-Tracing Formats](#ray-tracing-formats)
|
|
47
56
|
|
|
48
57
|
[> Documentation <](https://M-106.github.io/Image-Physics-Simulation/img_phy_sim.html)
|
|
49
58
|
|
|
50
|
-
<img src="https://github.com/M-106/Image-Physics-Simulation/raw/main/img_phy_sim/raytracing_example.png"></img>
|
|
59
|
+
<img src="https://github.com/M-106/Image-Physics-Simulation/raw/main/img_phy_sim/raytracing_example.png" width="46%"></img>
|
|
60
|
+
<img src="https://github.com/M-106/Image-Physics-Simulation/raw/main/img_phy_sim/ism_example.png" width="46%"></img>
|
|
61
|
+
|
|
62
|
+
> Ray-Beams and ISM
|
|
51
63
|
|
|
52
64
|
<br><br>
|
|
53
65
|
|
|
@@ -58,18 +70,27 @@ This repo only need some basic libraries:
|
|
|
58
70
|
- `matplotlib`
|
|
59
71
|
- `opencv-python`
|
|
60
72
|
- `scikit-image`
|
|
73
|
+
- `joblib`
|
|
74
|
+
|
|
75
|
+
If you want to use the `data` module then this package needs also:
|
|
76
|
+
- `torch`
|
|
77
|
+
- `torchvision`
|
|
78
|
+
- `datasets`
|
|
79
|
+
- `prime_printer`
|
|
61
80
|
|
|
62
81
|
You can download / clone this repo and run the example notebook via following Python/Anaconda setup:
|
|
63
82
|
```bash
|
|
64
83
|
conda create -n img-phy-sim python=3.13 pip -y
|
|
65
84
|
conda activate img-phy-sim
|
|
66
|
-
pip install numpy matplotlib opencv-python ipython jupyter shapely prime_printer datasets==3.6.0 scikit-image
|
|
85
|
+
pip install numpy matplotlib opencv-python ipython jupyter shapely prime_printer datasets==3.6.0 scikit-image joblib shapely
|
|
67
86
|
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
|
|
68
87
|
```
|
|
69
88
|
|
|
70
89
|
You can also use this repo via [Python Package Index (PyPI)](https://pypi.org/) as a package:
|
|
71
90
|
```bash
|
|
72
91
|
pip install img-phy-sim
|
|
92
|
+
# or for using `data` module:
|
|
93
|
+
pip install img-phy-sim[full]
|
|
73
94
|
```
|
|
74
95
|
|
|
75
96
|
Here the instructions to use the package version of `ips` and an anconda setup:
|
|
@@ -77,11 +98,13 @@ Here the instructions to use the package version of `ips` and an anconda setup:
|
|
|
77
98
|
conda create -n img-phy-sim python=3.13 pip -y
|
|
78
99
|
conda activate img-phy-sim
|
|
79
100
|
pip install img-phy-sim
|
|
101
|
+
# or for using `data` module:
|
|
102
|
+
pip install img-phy-sim[full]
|
|
80
103
|
```
|
|
81
104
|
|
|
82
|
-
To run the example code you
|
|
105
|
+
To run the example code you also need (this is included in `img-phy-sim[full]`):
|
|
83
106
|
```bash
|
|
84
|
-
pip install prime_printer
|
|
107
|
+
pip install prime_printer datasets==3.6.0
|
|
85
108
|
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
|
|
86
109
|
```
|
|
87
110
|
|
|
@@ -89,20 +112,20 @@ pip install torch torchvision torchaudio --index-url https://download.pytorch.or
|
|
|
89
112
|
|
|
90
113
|
### Download Example Data
|
|
91
114
|
|
|
92
|
-
You can download Physgen data if wanted via the `
|
|
115
|
+
You can download Physgen data if wanted via the `data.py` using following commands:
|
|
93
116
|
|
|
94
117
|
```bash
|
|
95
118
|
conda activate img-phy-sim
|
|
96
|
-
cd "D:\Informatik\Projekte\Image-Physics-Simulation" && D:
|
|
97
|
-
python
|
|
119
|
+
cd "D:\Informatik\Projekte\Image-Physics-Simulation\img_phy_sim" && D:
|
|
120
|
+
python data.py --output_real_path ./datasets/physgen_train_raw/real --output_osm_path ./datasets/physgen_train_raw/osm --variation sound_reflection --input_type osm --output_type standard --data_mode train
|
|
98
121
|
```
|
|
99
122
|
|
|
100
123
|
```bash
|
|
101
|
-
python
|
|
124
|
+
python data.py --output_real_path ./datasets/physgen_test_raw/real --output_osm_path ./datasets/physgen_test_raw/osm --variation sound_reflection --input_type osm --output_type standard --data_mode test
|
|
102
125
|
```
|
|
103
126
|
|
|
104
127
|
```bash
|
|
105
|
-
python
|
|
128
|
+
python data.py --output_real_path ./datasets/physgen_val_raw/real --output_osm_path ./datasets/physgen_val_raw/osm --variation sound_reflection --input_type osm --output_type standard --data_mode validation
|
|
106
129
|
```
|
|
107
130
|
|
|
108
131
|
<br><br>
|
|
@@ -196,6 +219,23 @@ class PhysGenDataset(Dataset):
|
|
|
196
219
|
- `open`: load your saved rays txt file
|
|
197
220
|
- `get_linear_degree_range`: get a range for your beam-directions -> example beams between 0-360 with stepsize 10
|
|
198
221
|
- `merge_rays`: merge 2 rays to one 'object'
|
|
222
|
+
- `ism`
|
|
223
|
+
- `reflect_point_across_infinite_line`: Reflects a point across the infinite line defined by two endpoints
|
|
224
|
+
- `paths_to_rays`: Converts polyline paths into your ray/segment representation, optionally normalizing points to ([0,1]) image space
|
|
225
|
+
- `reflection_map_to_img`: Normalizes a float reflection/energy map to a uint8 visualization image in ([0,255])
|
|
226
|
+
- `Segment`: Immutable dataclass representing a 2D line segment with convenience access to its endpoints
|
|
227
|
+
- `_seg_seg_intersection`: Computes the unique intersection point of two finite 2D segments, returning None for parallel/colinear/no-hit cases
|
|
228
|
+
- `_bresenham_points`: Generates all integer grid points along a line between two pixels using Bresenham’s algorithm
|
|
229
|
+
- `is_visible_raster`: Tests line-of-sight between two points by checking whether Bresenham-sampled pixels hit an occlusion raster
|
|
230
|
+
- `build_wall_mask`: Builds a binary 0/255 wall mask from an input image using explicit wall labels or mask-like heuristics
|
|
231
|
+
- `get_wall_segments_from_mask`: Extracts wall boundary contours from a binary mask and converts them into geometric Segment primitives
|
|
232
|
+
- `build_occlusion_from_wallmask`: Produces a binary occlusion raster (optionally dilated) used for fast visibility checks
|
|
233
|
+
- `enumerate_wall_sequences_indices`: Enumerates all reflection sequences (as wall-index tuples) up to a maximum reflection order
|
|
234
|
+
- `precompute_image_sources`: Computes image-source positions for each reflection sequence by iteratively mirroring the source across the corresponding walls
|
|
235
|
+
- `build_path_for_sequence`: Reconstructs the specular reflection polyline for a given wall sequence by backtracking virtual receivers and segment intersections
|
|
236
|
+
- `path_energy`: Computes a simple physically-inspired path contribution based on total path length and per-reflection losses
|
|
237
|
+
- `check_path_visibility_raster`: Verifies that every segment of a candidate path is unobstructed using raster line-of-sight tests
|
|
238
|
+
- `compute_reflection_map`: Evaluates all valid ISM paths from one source to a receiver grid and accumulates path counts
|
|
199
239
|
- `img`
|
|
200
240
|
- `open`: load an image via Open-CV
|
|
201
241
|
- `save`: save an image
|
|
@@ -203,6 +243,21 @@ class PhysGenDataset(Dataset):
|
|
|
203
243
|
- `advanced_imshow`: show multiple images with many options
|
|
204
244
|
- `show_image_with_line_and_profile`: show an image with a red line + the values of the image on this line
|
|
205
245
|
- `plot_image_with_values`: plot an image with it's value plotted and averaged to see your image in values
|
|
246
|
+
- `math`
|
|
247
|
+
- `get_linear_degree_range`: generate evenly spaced degrees within a range
|
|
248
|
+
- `degree_to_vector`: convert a degree angle to a 2D unit vector
|
|
249
|
+
- `vector_to_degree`: convert a 2D vector into its corresponding degree
|
|
250
|
+
- `normalize_point`: Normalize a 2D point to [0, 1] range
|
|
251
|
+
- `denormalize_point`: Denormalize a 2D point to pixel coordinates
|
|
252
|
+
- `numpy_info`: Get statistics about an numpy array
|
|
253
|
+
- `eval`
|
|
254
|
+
- `calc_metrices`: calculate F1, Recall and Precision between rays (or optinal an image) and an image
|
|
255
|
+
- `data`
|
|
256
|
+
- `PhysGenDataset()`: PyTorch dataset wrapper for PhysGen with flexible input/output configuration
|
|
257
|
+
- `resize_tensor_to_divisible_by_14`: resize tensors so height and width are divisible by 14
|
|
258
|
+
- `get_dataloader`: create a PyTorch DataLoader for the PhysGen dataset
|
|
259
|
+
- `get_image`: retrieve a single dataset sample (optionally as NumPy arrays)
|
|
260
|
+
- `save_dataset`: export PhysGen inputs and targets as PNG images to disk
|
|
206
261
|
|
|
207
262
|
|
|
208
263
|
That are not all functions but the ones which should be most useful. Check out the documentation for all functions.
|
|
@@ -225,14 +280,9 @@ That are not all functions but the ones which should be most useful. Check out t
|
|
|
225
280
|
[See also the example notebook 👀](./example/physgen.ipynb)
|
|
226
281
|
|
|
227
282
|
In general you need to do:
|
|
228
|
-
1.
|
|
229
|
-
2. **
|
|
230
|
-
3. **Calculate the Beams** -> using `ips.img.open`
|
|
231
|
-
4. **Draw (Export) the Beams** -> using `ips.img.open`
|
|
283
|
+
1. Load your Image + Calculate the Wall-Map + **Calculate the Beams** -> using `ips.ray_tracing.trace_beams`
|
|
284
|
+
2. **Draw (Export) the Beams on a image** -> using `ips.ray_tracing.draw_rays`
|
|
232
285
|
|
|
233
|
-
Using this lib, this is reduced to:
|
|
234
|
-
1. **Calculate the Beams** (including Wall-Map and loading your Image) -> using `ips.img.open`
|
|
235
|
-
2. **Draw (Export) the Beams** -> using `ips.img.open`
|
|
236
286
|
|
|
237
287
|
See this example:
|
|
238
288
|
|
|
@@ -361,7 +411,17 @@ I hope this little tutorial could be helpful. Good luck with your project <3
|
|
|
361
411
|
|
|
362
412
|
<br>
|
|
363
413
|
|
|
364
|
-
[> See the notebook/code <](./example/physgen_performance.ipynb)
|
|
414
|
+
[> See the notebook/code <](./example/physgen_performance.ipynb) [(or parallel notebook)](./example/physgen_parallel_performance.ipynb)
|
|
415
|
+
|
|
416
|
+
<br><br>
|
|
417
|
+
|
|
418
|
+
Comparison no parallel vs parallel computing:
|
|
419
|
+
- Parallel Mean Experiment time: 3.48 seconds (mean first experiment: 8.85 seconds)
|
|
420
|
+
- Standard Mean Experiment time: 4.53 seconds (mean first experiment: 16.00 seconds)
|
|
421
|
+
|
|
422
|
+
<br><br>
|
|
423
|
+
|
|
424
|
+
Parameter Experiments:
|
|
365
425
|
|
|
366
426
|
Executed with 50 random images.
|
|
367
427
|
|
|
@@ -481,6 +541,123 @@ The Stepsize/amount of rays have the biggest impact on the performance. The othe
|
|
|
481
541
|
| **3. Reflection Order** | 6 | 0.93 ± 0.74 s | 0.90 ± 0.72 s | 0.029 ± 0.016 s | **227.71 %** | Increasing (+0.37 s/exp) | Performance changes **significantly** |
|
|
482
542
|
| **4. Detail Draw** | 2 | 0.63 ± 0.05 s | 0.56 ± 0.00 s | 0.071 ± 0.050 s | **16.39 %** | Increasing (+0.10 s/exp) | Performance changes **slightly** |
|
|
483
543
|
|
|
544
|
+
<!--
|
|
545
|
+
<br><br>
|
|
546
|
+
|
|
547
|
+
### Optimization
|
|
548
|
+
|
|
549
|
+
<br>
|
|
550
|
+
|
|
551
|
+
Speed comparison between `standard`, `with joblib` and `joblib + CPython`.
|
|
552
|
+
|
|
553
|
+
FIXME -> table
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
<br>
|
|
557
|
+
|
|
558
|
+
Cython is Pyhon code which is closer to C. Instead of compiling to Python-Bytecode (`.pyc`), your code will be compiled as C-Extension (`.so`/`.pyd`).
|
|
559
|
+
|
|
560
|
+
There are 3 layers of Cython optimization:
|
|
561
|
+
1. Writing in `.pyx` files not `.py` files -> you can just rename your file<br>
|
|
562
|
+
- +5% to +30% speedup
|
|
563
|
+
2. Set `cdef` for local variables + helper-functions + `cpdef` for API-functions -> add types<br>
|
|
564
|
+
Example:
|
|
565
|
+
```python
|
|
566
|
+
cdef double x0, y0, dx, dy
|
|
567
|
+
cdef int cell_x, cell_y, steps
|
|
568
|
+
```
|
|
569
|
+
- +5x to +50x speedup
|
|
570
|
+
3. Add types everywhere, especially in numpy arrays. <br>
|
|
571
|
+
Example:
|
|
572
|
+
```python
|
|
573
|
+
cimport numpy as cnp
|
|
574
|
+
|
|
575
|
+
def trace(..., cnp.ndarray[double, ndim=2] img):
|
|
576
|
+
cdef double value = img[y, x]
|
|
577
|
+
```
|
|
578
|
+
- +20× to +500×
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
| **Optimization Layer** | **Effort** | **Speedup** | **What It Does** |
|
|
583
|
+
|---|---|---|---|
|
|
584
|
+
| **1. `.py` → `.pyx`** | minimal | **+5–30%** | Reduces Python interpreter overhead and applies basic Cython optimizations |
|
|
585
|
+
| **2. `cdef` variables & `cpdef` functions** | medium | **+5×–50×** | Moves loops and math into pure C, eliminating Python object overhead |
|
|
586
|
+
| **3. `cimport numpy` + typed NumPy arrays** | high | **+20×–500×** | Enables direct C‑level memory access with zero Python indexing overhead |
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
> Use `pip install cypthon` to install it.
|
|
591
|
+
|
|
592
|
+
In `setup.py` you need following changes:
|
|
593
|
+
```python
|
|
594
|
+
from setuptools import setup, find_packages, Extension
|
|
595
|
+
from Cython.Build import cythonize
|
|
596
|
+
|
|
597
|
+
...
|
|
598
|
+
|
|
599
|
+
ext_1 = Extension(
|
|
600
|
+
name="img_phy_sim.ray_tracing",
|
|
601
|
+
sources=["img_phy_sim/ray_tracing.pyx"],
|
|
602
|
+
include_dirs=[],
|
|
603
|
+
extra_compile_args=["-O3"],
|
|
604
|
+
)
|
|
605
|
+
|
|
606
|
+
ext_2 = Extension(
|
|
607
|
+
name="img_phy_sim.math",
|
|
608
|
+
sources=["img_phy_sim/math.pyx"],
|
|
609
|
+
include_dirs=[],
|
|
610
|
+
extra_compile_args=["-O3"],
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
setup(
|
|
614
|
+
ext_modules=cythonize(
|
|
615
|
+
[ext_1, ext_2],
|
|
616
|
+
compiler_directives={
|
|
617
|
+
"language_level": "3",
|
|
618
|
+
"boundscheck": False,
|
|
619
|
+
"wraparound": False,
|
|
620
|
+
"initializedcheck": False,
|
|
621
|
+
"nonecheck": False,
|
|
622
|
+
"cdivision": True,
|
|
623
|
+
},
|
|
624
|
+
annotate=True,
|
|
625
|
+
),
|
|
626
|
+
...
|
|
627
|
+
)
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
-->
|
|
631
|
+
|
|
632
|
+
<br><br>
|
|
633
|
+
|
|
634
|
+
### Ray-Tracing Formats
|
|
635
|
+
|
|
636
|
+
<br>
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
**Your current approach (DDA / Pixel Ray Marching)**
|
|
640
|
+
* **Forward integration**: Ray is propagated step by step through a **discrete grid** (pixel/grid).
|
|
641
|
+
* **Collision model**: A "hit" occurs when the ray enters a **wall cell** (quantization).
|
|
642
|
+
* **Reflection**: Occurs **locally at the collision pixel** with a (often quantized) normal/orientation.
|
|
643
|
+
* Result: good for "many rays" / field of view, but **not deterministic with regard to reflection paths** (you need directions/sampling).
|
|
644
|
+
|
|
645
|
+
**Noise modeling style (image source method / geometric acoustics)**
|
|
646
|
+
* **Path construction**: Reflection paths are constructed **deterministically** via **mirror sources** (virtual sources).
|
|
647
|
+
* **Continuous geometry**: works in $\mathbb{R}^2 / \mathbb{R}^3$ with lines/segments/polygons ("infinity-based" in the sense of *continuous space*, not raster).
|
|
648
|
+
* **Validation**: Path is then accepted/rejected via **visibility/occlusion checks**.
|
|
649
|
+
* Result: Delivers **all specular paths up to order N** without angle sampling.
|
|
650
|
+
|
|
651
|
+
Short form:
|
|
652
|
+
|
|
653
|
+
* **Pixel-based + stochastic/directed** (original approach here) vs. **continuous + deterministically constructed** (noise modelling).
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
<br>
|
|
657
|
+
|
|
658
|
+
How to use which of them in `img-phy-sim`:
|
|
659
|
+
|
|
660
|
+
FIXME
|
|
484
661
|
|
|
485
662
|
|
|
486
663
|
|
|
@@ -10,10 +10,14 @@ Contents:
|
|
|
10
10
|
- [Raytracing Computation](#raytracing-computation)
|
|
11
11
|
- [Raytracing Tutorial](#raytracing-tutorial)
|
|
12
12
|
- [Performance Test](#performance-test)
|
|
13
|
+
- [Ray-Tracing Formats](#ray-tracing-formats)
|
|
13
14
|
|
|
14
15
|
[> Documentation <](https://M-106.github.io/Image-Physics-Simulation/img_phy_sim.html)
|
|
15
16
|
|
|
16
|
-
<img src="./img_phy_sim/raytracing_example.png"></img>
|
|
17
|
+
<img src="./img_phy_sim/raytracing_example.png" width="46%"></img>
|
|
18
|
+
<img src="./img_phy_sim/ism_example.png" width="46%"></img>
|
|
19
|
+
|
|
20
|
+
> Ray-Beams and ISM
|
|
17
21
|
|
|
18
22
|
<br><br>
|
|
19
23
|
|
|
@@ -24,18 +28,27 @@ This repo only need some basic libraries:
|
|
|
24
28
|
- `matplotlib`
|
|
25
29
|
- `opencv-python`
|
|
26
30
|
- `scikit-image`
|
|
31
|
+
- `joblib`
|
|
32
|
+
|
|
33
|
+
If you want to use the `data` module then this package needs also:
|
|
34
|
+
- `torch`
|
|
35
|
+
- `torchvision`
|
|
36
|
+
- `datasets`
|
|
37
|
+
- `prime_printer`
|
|
27
38
|
|
|
28
39
|
You can download / clone this repo and run the example notebook via following Python/Anaconda setup:
|
|
29
40
|
```bash
|
|
30
41
|
conda create -n img-phy-sim python=3.13 pip -y
|
|
31
42
|
conda activate img-phy-sim
|
|
32
|
-
pip install numpy matplotlib opencv-python ipython jupyter shapely prime_printer datasets==3.6.0 scikit-image
|
|
43
|
+
pip install numpy matplotlib opencv-python ipython jupyter shapely prime_printer datasets==3.6.0 scikit-image joblib shapely
|
|
33
44
|
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
|
|
34
45
|
```
|
|
35
46
|
|
|
36
47
|
You can also use this repo via [Python Package Index (PyPI)](https://pypi.org/) as a package:
|
|
37
48
|
```bash
|
|
38
49
|
pip install img-phy-sim
|
|
50
|
+
# or for using `data` module:
|
|
51
|
+
pip install img-phy-sim[full]
|
|
39
52
|
```
|
|
40
53
|
|
|
41
54
|
Here the instructions to use the package version of `ips` and an anconda setup:
|
|
@@ -43,11 +56,13 @@ Here the instructions to use the package version of `ips` and an anconda setup:
|
|
|
43
56
|
conda create -n img-phy-sim python=3.13 pip -y
|
|
44
57
|
conda activate img-phy-sim
|
|
45
58
|
pip install img-phy-sim
|
|
59
|
+
# or for using `data` module:
|
|
60
|
+
pip install img-phy-sim[full]
|
|
46
61
|
```
|
|
47
62
|
|
|
48
|
-
To run the example code you
|
|
63
|
+
To run the example code you also need (this is included in `img-phy-sim[full]`):
|
|
49
64
|
```bash
|
|
50
|
-
pip install prime_printer
|
|
65
|
+
pip install prime_printer datasets==3.6.0
|
|
51
66
|
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
|
|
52
67
|
```
|
|
53
68
|
|
|
@@ -55,20 +70,20 @@ pip install torch torchvision torchaudio --index-url https://download.pytorch.or
|
|
|
55
70
|
|
|
56
71
|
### Download Example Data
|
|
57
72
|
|
|
58
|
-
You can download Physgen data if wanted via the `
|
|
73
|
+
You can download Physgen data if wanted via the `data.py` using following commands:
|
|
59
74
|
|
|
60
75
|
```bash
|
|
61
76
|
conda activate img-phy-sim
|
|
62
|
-
cd "D:\Informatik\Projekte\Image-Physics-Simulation" && D:
|
|
63
|
-
python
|
|
77
|
+
cd "D:\Informatik\Projekte\Image-Physics-Simulation\img_phy_sim" && D:
|
|
78
|
+
python data.py --output_real_path ./datasets/physgen_train_raw/real --output_osm_path ./datasets/physgen_train_raw/osm --variation sound_reflection --input_type osm --output_type standard --data_mode train
|
|
64
79
|
```
|
|
65
80
|
|
|
66
81
|
```bash
|
|
67
|
-
python
|
|
82
|
+
python data.py --output_real_path ./datasets/physgen_test_raw/real --output_osm_path ./datasets/physgen_test_raw/osm --variation sound_reflection --input_type osm --output_type standard --data_mode test
|
|
68
83
|
```
|
|
69
84
|
|
|
70
85
|
```bash
|
|
71
|
-
python
|
|
86
|
+
python data.py --output_real_path ./datasets/physgen_val_raw/real --output_osm_path ./datasets/physgen_val_raw/osm --variation sound_reflection --input_type osm --output_type standard --data_mode validation
|
|
72
87
|
```
|
|
73
88
|
|
|
74
89
|
<br><br>
|
|
@@ -162,6 +177,23 @@ class PhysGenDataset(Dataset):
|
|
|
162
177
|
- `open`: load your saved rays txt file
|
|
163
178
|
- `get_linear_degree_range`: get a range for your beam-directions -> example beams between 0-360 with stepsize 10
|
|
164
179
|
- `merge_rays`: merge 2 rays to one 'object'
|
|
180
|
+
- `ism`
|
|
181
|
+
- `reflect_point_across_infinite_line`: Reflects a point across the infinite line defined by two endpoints
|
|
182
|
+
- `paths_to_rays`: Converts polyline paths into your ray/segment representation, optionally normalizing points to ([0,1]) image space
|
|
183
|
+
- `reflection_map_to_img`: Normalizes a float reflection/energy map to a uint8 visualization image in ([0,255])
|
|
184
|
+
- `Segment`: Immutable dataclass representing a 2D line segment with convenience access to its endpoints
|
|
185
|
+
- `_seg_seg_intersection`: Computes the unique intersection point of two finite 2D segments, returning None for parallel/colinear/no-hit cases
|
|
186
|
+
- `_bresenham_points`: Generates all integer grid points along a line between two pixels using Bresenham’s algorithm
|
|
187
|
+
- `is_visible_raster`: Tests line-of-sight between two points by checking whether Bresenham-sampled pixels hit an occlusion raster
|
|
188
|
+
- `build_wall_mask`: Builds a binary 0/255 wall mask from an input image using explicit wall labels or mask-like heuristics
|
|
189
|
+
- `get_wall_segments_from_mask`: Extracts wall boundary contours from a binary mask and converts them into geometric Segment primitives
|
|
190
|
+
- `build_occlusion_from_wallmask`: Produces a binary occlusion raster (optionally dilated) used for fast visibility checks
|
|
191
|
+
- `enumerate_wall_sequences_indices`: Enumerates all reflection sequences (as wall-index tuples) up to a maximum reflection order
|
|
192
|
+
- `precompute_image_sources`: Computes image-source positions for each reflection sequence by iteratively mirroring the source across the corresponding walls
|
|
193
|
+
- `build_path_for_sequence`: Reconstructs the specular reflection polyline for a given wall sequence by backtracking virtual receivers and segment intersections
|
|
194
|
+
- `path_energy`: Computes a simple physically-inspired path contribution based on total path length and per-reflection losses
|
|
195
|
+
- `check_path_visibility_raster`: Verifies that every segment of a candidate path is unobstructed using raster line-of-sight tests
|
|
196
|
+
- `compute_reflection_map`: Evaluates all valid ISM paths from one source to a receiver grid and accumulates path counts
|
|
165
197
|
- `img`
|
|
166
198
|
- `open`: load an image via Open-CV
|
|
167
199
|
- `save`: save an image
|
|
@@ -169,6 +201,21 @@ class PhysGenDataset(Dataset):
|
|
|
169
201
|
- `advanced_imshow`: show multiple images with many options
|
|
170
202
|
- `show_image_with_line_and_profile`: show an image with a red line + the values of the image on this line
|
|
171
203
|
- `plot_image_with_values`: plot an image with it's value plotted and averaged to see your image in values
|
|
204
|
+
- `math`
|
|
205
|
+
- `get_linear_degree_range`: generate evenly spaced degrees within a range
|
|
206
|
+
- `degree_to_vector`: convert a degree angle to a 2D unit vector
|
|
207
|
+
- `vector_to_degree`: convert a 2D vector into its corresponding degree
|
|
208
|
+
- `normalize_point`: Normalize a 2D point to [0, 1] range
|
|
209
|
+
- `denormalize_point`: Denormalize a 2D point to pixel coordinates
|
|
210
|
+
- `numpy_info`: Get statistics about an numpy array
|
|
211
|
+
- `eval`
|
|
212
|
+
- `calc_metrices`: calculate F1, Recall and Precision between rays (or optinal an image) and an image
|
|
213
|
+
- `data`
|
|
214
|
+
- `PhysGenDataset()`: PyTorch dataset wrapper for PhysGen with flexible input/output configuration
|
|
215
|
+
- `resize_tensor_to_divisible_by_14`: resize tensors so height and width are divisible by 14
|
|
216
|
+
- `get_dataloader`: create a PyTorch DataLoader for the PhysGen dataset
|
|
217
|
+
- `get_image`: retrieve a single dataset sample (optionally as NumPy arrays)
|
|
218
|
+
- `save_dataset`: export PhysGen inputs and targets as PNG images to disk
|
|
172
219
|
|
|
173
220
|
|
|
174
221
|
That are not all functions but the ones which should be most useful. Check out the documentation for all functions.
|
|
@@ -191,14 +238,9 @@ That are not all functions but the ones which should be most useful. Check out t
|
|
|
191
238
|
[See also the example notebook 👀](./example/physgen.ipynb)
|
|
192
239
|
|
|
193
240
|
In general you need to do:
|
|
194
|
-
1.
|
|
195
|
-
2. **
|
|
196
|
-
3. **Calculate the Beams** -> using `ips.img.open`
|
|
197
|
-
4. **Draw (Export) the Beams** -> using `ips.img.open`
|
|
241
|
+
1. Load your Image + Calculate the Wall-Map + **Calculate the Beams** -> using `ips.ray_tracing.trace_beams`
|
|
242
|
+
2. **Draw (Export) the Beams on a image** -> using `ips.ray_tracing.draw_rays`
|
|
198
243
|
|
|
199
|
-
Using this lib, this is reduced to:
|
|
200
|
-
1. **Calculate the Beams** (including Wall-Map and loading your Image) -> using `ips.img.open`
|
|
201
|
-
2. **Draw (Export) the Beams** -> using `ips.img.open`
|
|
202
244
|
|
|
203
245
|
See this example:
|
|
204
246
|
|
|
@@ -327,7 +369,17 @@ I hope this little tutorial could be helpful. Good luck with your project <3
|
|
|
327
369
|
|
|
328
370
|
<br>
|
|
329
371
|
|
|
330
|
-
[> See the notebook/code <](./example/physgen_performance.ipynb)
|
|
372
|
+
[> See the notebook/code <](./example/physgen_performance.ipynb) [(or parallel notebook)](./example/physgen_parallel_performance.ipynb)
|
|
373
|
+
|
|
374
|
+
<br><br>
|
|
375
|
+
|
|
376
|
+
Comparison no parallel vs parallel computing:
|
|
377
|
+
- Parallel Mean Experiment time: 3.48 seconds (mean first experiment: 8.85 seconds)
|
|
378
|
+
- Standard Mean Experiment time: 4.53 seconds (mean first experiment: 16.00 seconds)
|
|
379
|
+
|
|
380
|
+
<br><br>
|
|
381
|
+
|
|
382
|
+
Parameter Experiments:
|
|
331
383
|
|
|
332
384
|
Executed with 50 random images.
|
|
333
385
|
|
|
@@ -447,6 +499,123 @@ The Stepsize/amount of rays have the biggest impact on the performance. The othe
|
|
|
447
499
|
| **3. Reflection Order** | 6 | 0.93 ± 0.74 s | 0.90 ± 0.72 s | 0.029 ± 0.016 s | **227.71 %** | Increasing (+0.37 s/exp) | Performance changes **significantly** |
|
|
448
500
|
| **4. Detail Draw** | 2 | 0.63 ± 0.05 s | 0.56 ± 0.00 s | 0.071 ± 0.050 s | **16.39 %** | Increasing (+0.10 s/exp) | Performance changes **slightly** |
|
|
449
501
|
|
|
502
|
+
<!--
|
|
503
|
+
<br><br>
|
|
504
|
+
|
|
505
|
+
### Optimization
|
|
506
|
+
|
|
507
|
+
<br>
|
|
508
|
+
|
|
509
|
+
Speed comparison between `standard`, `with joblib` and `joblib + CPython`.
|
|
510
|
+
|
|
511
|
+
FIXME -> table
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
<br>
|
|
515
|
+
|
|
516
|
+
Cython is Pyhon code which is closer to C. Instead of compiling to Python-Bytecode (`.pyc`), your code will be compiled as C-Extension (`.so`/`.pyd`).
|
|
517
|
+
|
|
518
|
+
There are 3 layers of Cython optimization:
|
|
519
|
+
1. Writing in `.pyx` files not `.py` files -> you can just rename your file<br>
|
|
520
|
+
- +5% to +30% speedup
|
|
521
|
+
2. Set `cdef` for local variables + helper-functions + `cpdef` for API-functions -> add types<br>
|
|
522
|
+
Example:
|
|
523
|
+
```python
|
|
524
|
+
cdef double x0, y0, dx, dy
|
|
525
|
+
cdef int cell_x, cell_y, steps
|
|
526
|
+
```
|
|
527
|
+
- +5x to +50x speedup
|
|
528
|
+
3. Add types everywhere, especially in numpy arrays. <br>
|
|
529
|
+
Example:
|
|
530
|
+
```python
|
|
531
|
+
cimport numpy as cnp
|
|
532
|
+
|
|
533
|
+
def trace(..., cnp.ndarray[double, ndim=2] img):
|
|
534
|
+
cdef double value = img[y, x]
|
|
535
|
+
```
|
|
536
|
+
- +20× to +500×
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
| **Optimization Layer** | **Effort** | **Speedup** | **What It Does** |
|
|
541
|
+
|---|---|---|---|
|
|
542
|
+
| **1. `.py` → `.pyx`** | minimal | **+5–30%** | Reduces Python interpreter overhead and applies basic Cython optimizations |
|
|
543
|
+
| **2. `cdef` variables & `cpdef` functions** | medium | **+5×–50×** | Moves loops and math into pure C, eliminating Python object overhead |
|
|
544
|
+
| **3. `cimport numpy` + typed NumPy arrays** | high | **+20×–500×** | Enables direct C‑level memory access with zero Python indexing overhead |
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
> Use `pip install cypthon` to install it.
|
|
549
|
+
|
|
550
|
+
In `setup.py` you need following changes:
|
|
551
|
+
```python
|
|
552
|
+
from setuptools import setup, find_packages, Extension
|
|
553
|
+
from Cython.Build import cythonize
|
|
554
|
+
|
|
555
|
+
...
|
|
556
|
+
|
|
557
|
+
ext_1 = Extension(
|
|
558
|
+
name="img_phy_sim.ray_tracing",
|
|
559
|
+
sources=["img_phy_sim/ray_tracing.pyx"],
|
|
560
|
+
include_dirs=[],
|
|
561
|
+
extra_compile_args=["-O3"],
|
|
562
|
+
)
|
|
563
|
+
|
|
564
|
+
ext_2 = Extension(
|
|
565
|
+
name="img_phy_sim.math",
|
|
566
|
+
sources=["img_phy_sim/math.pyx"],
|
|
567
|
+
include_dirs=[],
|
|
568
|
+
extra_compile_args=["-O3"],
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
setup(
|
|
572
|
+
ext_modules=cythonize(
|
|
573
|
+
[ext_1, ext_2],
|
|
574
|
+
compiler_directives={
|
|
575
|
+
"language_level": "3",
|
|
576
|
+
"boundscheck": False,
|
|
577
|
+
"wraparound": False,
|
|
578
|
+
"initializedcheck": False,
|
|
579
|
+
"nonecheck": False,
|
|
580
|
+
"cdivision": True,
|
|
581
|
+
},
|
|
582
|
+
annotate=True,
|
|
583
|
+
),
|
|
584
|
+
...
|
|
585
|
+
)
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
-->
|
|
589
|
+
|
|
590
|
+
<br><br>
|
|
591
|
+
|
|
592
|
+
### Ray-Tracing Formats
|
|
593
|
+
|
|
594
|
+
<br>
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
**Your current approach (DDA / Pixel Ray Marching)**
|
|
598
|
+
* **Forward integration**: Ray is propagated step by step through a **discrete grid** (pixel/grid).
|
|
599
|
+
* **Collision model**: A "hit" occurs when the ray enters a **wall cell** (quantization).
|
|
600
|
+
* **Reflection**: Occurs **locally at the collision pixel** with a (often quantized) normal/orientation.
|
|
601
|
+
* Result: good for "many rays" / field of view, but **not deterministic with regard to reflection paths** (you need directions/sampling).
|
|
602
|
+
|
|
603
|
+
**Noise modeling style (image source method / geometric acoustics)**
|
|
604
|
+
* **Path construction**: Reflection paths are constructed **deterministically** via **mirror sources** (virtual sources).
|
|
605
|
+
* **Continuous geometry**: works in $\mathbb{R}^2 / \mathbb{R}^3$ with lines/segments/polygons ("infinity-based" in the sense of *continuous space*, not raster).
|
|
606
|
+
* **Validation**: Path is then accepted/rejected via **visibility/occlusion checks**.
|
|
607
|
+
* Result: Delivers **all specular paths up to order N** without angle sampling.
|
|
608
|
+
|
|
609
|
+
Short form:
|
|
610
|
+
|
|
611
|
+
* **Pixel-based + stochastic/directed** (original approach here) vs. **continuous + deterministically constructed** (noise modelling).
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
<br>
|
|
615
|
+
|
|
616
|
+
How to use which of them in `img-phy-sim`:
|
|
617
|
+
|
|
618
|
+
FIXME
|
|
450
619
|
|
|
451
620
|
|
|
452
621
|
|
|
@@ -38,6 +38,19 @@ Submodules:
|
|
|
38
38
|
- plot_image_with_values / show_image_with_line_and_profile
|
|
39
39
|
- get_width_height / get_bit_depth
|
|
40
40
|
|
|
41
|
+
- `eval`<br>
|
|
42
|
+
Accuracy measurement utilities.<br>
|
|
43
|
+
Key functionalities:
|
|
44
|
+
- calc_metrices
|
|
45
|
+
|
|
46
|
+
- `data`<br>
|
|
47
|
+
Loading utilities for PhysGen Dataset.<br>
|
|
48
|
+
Key functionalities:
|
|
49
|
+
- PhysGenDataset()
|
|
50
|
+
- get_dataloader
|
|
51
|
+
- save_dataset
|
|
52
|
+
|
|
53
|
+
|
|
41
54
|
Typical workflow:
|
|
42
55
|
1. Prepare an environment image using `img.open()` or generate it programmatically.
|
|
43
56
|
2. Trace beams using `ray_tracing.trace_beams()` with specified start positions,
|
|
@@ -81,6 +94,9 @@ Tobia Ippolito, 2025
|
|
|
81
94
|
|
|
82
95
|
from . import img
|
|
83
96
|
from . import ray_tracing
|
|
97
|
+
from . import ism
|
|
84
98
|
from . import math
|
|
99
|
+
from . import eval
|
|
100
|
+
from . import data
|
|
85
101
|
# from . import data
|
|
86
102
|
|