(
normal_map: np.ndarray,
mask: Union[np.ndarray, None] = None,
height_divisor: float = 1,
target_iteration_count: int = 250,
thread_count: int = cpu_count(),
raw_values: bool = False,
)
| 165 | |
| 166 | |
| 167 | def estimate_height_map( |
| 168 | normal_map: np.ndarray, |
| 169 | mask: Union[np.ndarray, None] = None, |
| 170 | height_divisor: float = 1, |
| 171 | target_iteration_count: int = 250, |
| 172 | thread_count: int = cpu_count(), |
| 173 | raw_values: bool = False, |
| 174 | ) -> np.ndarray: |
| 175 | if mask is None: |
| 176 | if normal_map.shape[-1] == 4: |
| 177 | mask = normal_map[:, :, 3] / 255 |
| 178 | mask[mask < 0.5] = 0 |
| 179 | mask[mask >= 0.5] = 1 |
| 180 | else: |
| 181 | mask = np.ones(normal_map.shape[:2], dtype=np.uint8) |
| 182 | |
| 183 | normals = ((normal_map[:, :, :3].astype(np.float64) / 255) - 0.5) * 2 |
| 184 | heights = integrate_vector_field( |
| 185 | normals, mask, target_iteration_count, thread_count |
| 186 | ) |
| 187 | |
| 188 | if raw_values: |
| 189 | return heights |
| 190 | |
| 191 | heights /= height_divisor |
| 192 | heights[mask > 0] += 1 / 2 |
| 193 | heights[mask == 0] = 1 / 2 |
| 194 | |
| 195 | heights *= 2**16 - 1 |
| 196 | |
| 197 | if np.min(heights) < 0 or np.max(heights) > 2**16 - 1: |
| 198 | raise OverflowError("Height values are clipping.") |
| 199 | |
| 200 | heights = np.clip(heights, 0, 2**16 - 1) |
| 201 | heights = heights.astype(np.uint16) |
| 202 | |
| 203 | return heights |
no test coverage detected