rawforge 0.1.0__tar.gz → 0.2.1__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.
Files changed (41) hide show
  1. {rawforge-0.1.0 → rawforge-0.2.1}/PKG-INFO +55 -2
  2. {rawforge-0.1.0 → rawforge-0.2.1}/README.md +38 -0
  3. rawforge-0.2.1/RawForge/application/ImageSaver.py +70 -0
  4. rawforge-0.2.1/RawForge/application/InferenceWorker.py +84 -0
  5. rawforge-0.2.1/RawForge/application/MODEL_REGISTRY.py +785 -0
  6. rawforge-0.2.1/RawForge/application/ModelHandler.py +134 -0
  7. rawforge-0.2.1/RawForge/application/ModelHandlerTorch.py +144 -0
  8. rawforge-0.2.1/RawForge/application/ONNXBackend.py +33 -0
  9. rawforge-0.2.1/RawForge/application/TorchBackend.py +36 -0
  10. {rawforge-0.1.0 → rawforge-0.2.1}/RawForge/application/dng_utils.py +104 -62
  11. rawforge-0.2.1/RawForge/application/helpers/censored_fit.py +102 -0
  12. rawforge-0.2.1/RawForge/application/helpers/exiftools.py +14 -0
  13. rawforge-0.2.1/RawForge/application/helpers/get_backend.py +27 -0
  14. rawforge-0.2.1/RawForge/application/helpers/get_image.py +64 -0
  15. rawforge-0.2.1/RawForge/application/helpers/subtract_blacklevel.py +8 -0
  16. rawforge-0.1.0/RawForge/application/utils.py → rawforge-0.2.1/RawForge/application/helpers/torchutils.py +2 -1
  17. rawforge-0.2.1/RawForge/application/helpers/utils.py +18 -0
  18. rawforge-0.2.1/RawForge/application/postprocessing.py +99 -0
  19. rawforge-0.2.1/RawForge/main.py +231 -0
  20. {rawforge-0.1.0 → rawforge-0.2.1}/RawForge/scripts/generate_keys.py +1 -1
  21. {rawforge-0.1.0 → rawforge-0.2.1}/RawForge/scripts/sign_models.py +4 -3
  22. rawforge-0.2.1/RawForge/sidecar.py +78 -0
  23. {rawforge-0.1.0 → rawforge-0.2.1}/pyproject.toml +14 -4
  24. {rawforge-0.1.0 → rawforge-0.2.1}/rawforge.egg-info/PKG-INFO +55 -2
  25. rawforge-0.2.1/rawforge.egg-info/SOURCES.txt +30 -0
  26. rawforge-0.2.1/rawforge.egg-info/entry_points.txt +3 -0
  27. rawforge-0.2.1/rawforge.egg-info/requires.txt +30 -0
  28. rawforge-0.1.0/RawForge/application/InferenceWorker.py +0 -98
  29. rawforge-0.1.0/RawForge/application/InferenceWorkerRawpy.py +0 -108
  30. rawforge-0.1.0/RawForge/application/MODEL_REGISTRY.py +0 -59
  31. rawforge-0.1.0/RawForge/application/ModelHandler.py +0 -209
  32. rawforge-0.1.0/RawForge/application/postprocessing.py +0 -87
  33. rawforge-0.1.0/RawForge/main.py +0 -62
  34. rawforge-0.1.0/rawforge.egg-info/SOURCES.txt +0 -20
  35. rawforge-0.1.0/rawforge.egg-info/entry_points.txt +0 -2
  36. rawforge-0.1.0/rawforge.egg-info/requires.txt +0 -9
  37. {rawforge-0.1.0 → rawforge-0.2.1}/LICENSE +0 -0
  38. {rawforge-0.1.0 → rawforge-0.2.1}/RawForge/__init__.py +0 -0
  39. {rawforge-0.1.0 → rawforge-0.2.1}/rawforge.egg-info/dependency_links.txt +0 -0
  40. {rawforge-0.1.0 → rawforge-0.2.1}/rawforge.egg-info/top_level.txt +0 -0
  41. {rawforge-0.1.0 → rawforge-0.2.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rawforge
3
- Version: 0.1.0
3
+ Version: 0.2.1
4
4
  Summary: A compute backend/CLI application for using machine learning models on raw images.
5
5
  Author: Ryan Mueller
6
6
  License: MIT License
@@ -40,12 +40,27 @@ License-File: LICENSE
40
40
  Requires-Dist: numpy>=2.2
41
41
  Requires-Dist: RawHandler~=0.2.0
42
42
  Requires-Dist: colour_demosaicing~=0.2.6
43
- Requires-Dist: blended_tiling>=0.0.1.dev7
43
+ Requires-Dist: blended-tiling-numpy
44
44
  Requires-Dist: requests~=2.32
45
45
  Requires-Dist: platformdirs~=4.5
46
46
  Requires-Dist: tqdm~=4.67
47
47
  Requires-Dist: cryptography>=46.0
48
48
  Requires-Dist: tifffile
49
+ Requires-Dist: pyexiftool
50
+ Provides-Extra: cpu
51
+ Requires-Dist: onnxruntime; extra == "cpu"
52
+ Provides-Extra: cuda
53
+ Requires-Dist: onnxruntime-gpu; extra == "cuda"
54
+ Provides-Extra: web
55
+ Requires-Dist: onnxruntime-webgpu; extra == "web"
56
+ Provides-Extra: directml
57
+ Requires-Dist: onnxruntime-directml; extra == "directml"
58
+ Provides-Extra: torch
59
+ Requires-Dist: torch; extra == "torch"
60
+ Provides-Extra: fastapi
61
+ Requires-Dist: fastapi; extra == "fastapi"
62
+ Requires-Dist: pydantic; extra == "fastapi"
63
+ Requires-Dist: uvicorn; extra == "fastapi"
49
64
  Dynamic: license-file
50
65
 
51
66
  # RawRefinery
@@ -65,6 +80,41 @@ Currently in **alpha release**.
65
80
  pip install rawforge
66
81
  ```
67
82
 
83
+
84
+ ## New: ONNX backend!
85
+
86
+ ### NVIDIA: For cuda (tested, must have CUDA installed):
87
+
88
+ ```bash
89
+ pip install rawforge[cuda]
90
+ ```
91
+
92
+ ### AMD and NVIDIA on Windows:
93
+
94
+ ```bash
95
+ pip install rawforge[directml]
96
+ ```
97
+
98
+
99
+ ### All others, including M1+ Macs (CoreML)
100
+
101
+ ```bash
102
+ pip install rawforge[cpu]
103
+ ```
104
+
105
+ ### For web:
106
+
107
+ ```bash
108
+ pip install rawforge[web]
109
+ ```
110
+
111
+ Useage is the same, but use the CLI "rawforgeonnx".
112
+
113
+
114
+ ```bash
115
+ rawforgeonnx TreeNetDenoiseHeavy test.CR2 test_heavy.dng --cfa
116
+ ```
117
+
68
118
  ---
69
119
  ## Example command line syntax:
70
120
 
@@ -97,6 +147,9 @@ options:
97
147
  --chroma CHROMA Chroma noise (0-1).
98
148
  ```
99
149
 
150
+
151
+
152
+
100
153
  ----
101
154
 
102
155
  ## Acknowledgments
@@ -15,6 +15,41 @@ Currently in **alpha release**.
15
15
  pip install rawforge
16
16
  ```
17
17
 
18
+
19
+ ## New: ONNX backend!
20
+
21
+ ### NVIDIA: For cuda (tested, must have CUDA installed):
22
+
23
+ ```bash
24
+ pip install rawforge[cuda]
25
+ ```
26
+
27
+ ### AMD and NVIDIA on Windows:
28
+
29
+ ```bash
30
+ pip install rawforge[directml]
31
+ ```
32
+
33
+
34
+ ### All others, including M1+ Macs (CoreML)
35
+
36
+ ```bash
37
+ pip install rawforge[cpu]
38
+ ```
39
+
40
+ ### For web:
41
+
42
+ ```bash
43
+ pip install rawforge[web]
44
+ ```
45
+
46
+ Useage is the same, but use the CLI "rawforgeonnx".
47
+
48
+
49
+ ```bash
50
+ rawforgeonnx TreeNetDenoiseHeavy test.CR2 test_heavy.dng --cfa
51
+ ```
52
+
18
53
  ---
19
54
  ## Example command line syntax:
20
55
 
@@ -47,6 +82,9 @@ options:
47
82
  --chroma CHROMA Chroma noise (0-1).
48
83
  ```
49
84
 
85
+
86
+
87
+
50
88
  ----
51
89
 
52
90
  ## Acknowledgments
@@ -0,0 +1,70 @@
1
+ import numpy as np
2
+ from RawForge.application.dng_utils import convert_color_matrix, to_dng
3
+ import tifffile
4
+
5
+
6
+ class ImageSaver:
7
+ def __init__(self, model_params, rh, dims=None):
8
+ self.rh = rh
9
+ self.model_params = model_params
10
+ self.dims = dims
11
+
12
+ def to_tiff(self, image, filename, apply_ccm=True):
13
+ image = image
14
+ if apply_ccm:
15
+ transform_matrix = self.rh.rgb_colorspace_transform(
16
+ colorspace="lin_rec2020"
17
+ )
18
+ image = image[0].transpose(1, 2, 0)
19
+ transformed = image @ transform_matrix.T
20
+ else:
21
+ transformed = image[0].transpose(1, 2, 0)
22
+
23
+ transformed = np.clip(transformed, 0, 1)
24
+ transformed = transformed ** (1 / 2.2)
25
+ transformed = transformed * (2**8 - 1)
26
+
27
+ uint_img = transformed.astype(np.uint8)
28
+
29
+ tifffile.imwrite(
30
+ filename,
31
+ uint_img,
32
+ photometric="rgb", # Explicitly define the color space
33
+ compression="deflate", # Optional: Lossless compression supported by darktable
34
+ )
35
+
36
+ def to_raw(self, denoised, filename, save_cfa):
37
+ # Compute CFA
38
+ if self.model_params["demosaicing"] == "rawpy" or self.model_params["demosaicing"] == "sixchan":
39
+ if self.dims is None:
40
+ self.dims = [0, 9999999, 0, 9999999]
41
+ _, mask = self.rh.compute_mask_and_sparse(dims=self.dims)
42
+ denoised = denoised[0]
43
+ denoised = denoised.clip(0, 1)
44
+
45
+ denoised = np.where(mask, denoised, 0)
46
+ denoised = denoised.sum(axis=0)
47
+ denoised = (
48
+ denoised * (self.rh.core_metadata.white_level)
49
+ + self.rh.core_metadata.black_level_per_channel[0]
50
+ )
51
+ self.rh.to_dng(filename, uint_img=denoised)
52
+ else:
53
+ transform_matrix = np.linalg.inv(
54
+ self.rh.rgb_colorspace_transform(colorspace=self.rh.colorspace)
55
+ )
56
+
57
+ CCM = self.rh.rgb_colorspace_transform(colorspace="XYZ")
58
+ CCM = np.linalg.inv(CCM)
59
+ denoised = denoised[0].transpose(1, 2, 0)
60
+ transformed = denoised @ transform_matrix.T
61
+ uint_img = np.clip(transformed * 2**16 - 1, 0, 2**16 - 1).astype(np.uint16)
62
+ ccm1 = convert_color_matrix(CCM)
63
+ to_dng(
64
+ uint_img,
65
+ self.rh,
66
+ filename,
67
+ ccm1,
68
+ save_cfa=save_cfa,
69
+ convert_to_cfa=True,
70
+ )
@@ -0,0 +1,84 @@
1
+ import numpy as np
2
+ from blended_tiling_numpy import TilingModule
3
+ from tqdm import tqdm
4
+
5
+
6
+ class InferenceWorker:
7
+ def __init__(
8
+ self,
9
+ backend,
10
+ model_params,
11
+ conditioning,
12
+ disable_tqdm=False,
13
+ ):
14
+ self.backend = backend
15
+ self.model_params = model_params
16
+ self.conditioning = conditioning
17
+
18
+ self.tile_size = model_params.get("tile_size", 256)
19
+ self.tile_overlap = model_params.get("tile_overlap", 0.25)
20
+ self.batch_size = model_params.get("batch_size", 2)
21
+
22
+ self.disable_tqdm = disable_tqdm
23
+ self._is_cancelled = False
24
+
25
+ def cancel(self):
26
+ self._is_cancelled = True
27
+
28
+ def _build_conditioning(self):
29
+ cond = np.array([self.conditioning], dtype=np.float32)
30
+
31
+ if "max_iso" in self.model_params:
32
+ cond[:, 0] = min(cond[:, 0], self.model_params["max_iso"])
33
+ cond[:, 0] /= 6400.0
34
+ cond[:, 1] = 0.0
35
+ cond = cond[:, :1].astype(np.float16)
36
+
37
+ if "cond_scale" in self.model_params:
38
+ cond *= cond * self.model_params["cond_scale"]
39
+
40
+ return self.backend.prepare_conditioning(cond)
41
+
42
+ def run(self, image_RGB, progress_callback=None):
43
+
44
+ full_size = image_RGB.shape[2:]
45
+
46
+ tiler = TilingModule(
47
+ tile_size=[self.tile_size] * 2,
48
+ tile_overlap=[self.tile_overlap] * 2,
49
+ base_size=list(full_size),
50
+ )
51
+
52
+ tiles = tiler.split_into_tiles(image_RGB)
53
+
54
+ batches = [
55
+ tiles[i:i+self.batch_size]
56
+ for i in range(0, len(tiles), self.batch_size)
57
+ ]
58
+
59
+ cond = self._build_conditioning()
60
+
61
+ outputs = []
62
+
63
+ for i, batch in tqdm(
64
+ enumerate(batches),
65
+ total=len(batches),
66
+ disable=self.disable_tqdm,
67
+ ):
68
+
69
+ if self._is_cancelled:
70
+ return None, None
71
+
72
+ outputs.append(
73
+ self.backend.infer(batch, cond)
74
+ )
75
+
76
+ if progress_callback:
77
+ progress_callback((i + 1) / len(batches))
78
+
79
+ stitched = tiler.rebuild_with_masks(
80
+ np.concatenate(outputs, axis=0)
81
+ )
82
+
83
+ return image_RGB, stitched
84
+