Skip to content

Commit

Permalink
erode nodata blurring from ortho boundary for full_remap=False
Browse files Browse the repository at this point in the history
  • Loading branch information
dugalh committed Sep 29, 2023
1 parent a9e8a49 commit bf3f467
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 3 deletions.
20 changes: 18 additions & 2 deletions simple_ortho/ortho.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@ def area_poly(coords: np.array) -> float:
pixel_area = np.array(self._camera._im_size).prod()
world_area = area_poly(world_xy)
res = np.sqrt(world_area / pixel_area)
logger.debug(f'Using auto resolution: {res:.4f}')
return (res, ) * 2

def _reproject_dem(self, dem_interp: Interp, resolution: Tuple[float, float]) -> Tuple[np.ndarray, rio.Affine]:
Expand Down Expand Up @@ -446,6 +445,21 @@ def _remap_tile(
# mask of invalid ortho pixels
tile_mask = np.all(nan_equals(tile_array, dtype_nodata), axis=0)

# remove undistort cv2.remap blurring with nodata at the nodata boundary when full_remap=False...
if (
not full_remap and interp != Interp.nearest and not np.isnan(dtype_nodata) and
self._camera._undistort_maps is not None
):
# TODO: to avoid these nodata boundary issues entirely, use dtype=float and
# nodata=nan internally, then convert to config dtype and nodata on writing.
src_res = np.array(self._get_auto_res())
ortho_res = np.abs((tile_transform.a, tile_transform.e))
kernel_size = np.maximum(np.ceil(5 * src_res / ortho_res).astype('int'), (3, 3))
kernel = np.ones(kernel_size[::-1], np.uint8)
tile_mask = cv2.dilate(tile_mask.astype(np.uint8, copy=False), kernel)
tile_mask = tile_mask.astype(bool, copy=False)
tile_array[:, tile_mask] = dtype_nodata

# write tile_array to the ortho image
with self._write_lock:
ortho_im.write(tile_array, indexes, window=tile_win)
Expand Down Expand Up @@ -598,7 +612,9 @@ def process(
ortho_filename.with_suffix(ortho_filename.suffix + '.aux.xml').unlink(missing_ok=True)

# get an auto resolution if resolution not provided
resolution = resolution or self._get_auto_res()
if not resolution:
resolution = self._get_auto_res()
logger.debug(f'Using auto resolution: {resolution[0]:.4f}')

env = rio.Env(
GDAL_NUM_THREADS='ALL_CPUS', GTIFF_FORCE_RGBA=False, GDAL_TIFF_INTERNAL_MASK=True,
Expand Down
3 changes: 2 additions & 1 deletion tests/test_ortho.py
Original file line number Diff line number Diff line change
Expand Up @@ -714,8 +714,9 @@ def test_process_full_remap(

assert test_array.shape == ref_array.shape
assert ref_bounds == pytest.approx(test_bounds, abs=resolution[0])
assert ref_mask[test_mask].sum() / test_mask.sum() > 0.99
cc = np.corrcoef(ref_mask.flatten(), test_mask.flatten())
assert cc[0, 1] > 0.95
assert cc[0, 1] > 0.9
assert cc[0, 1] == pytest.approx(1., abs=1e-3) if isinstance(camera, PinholeCamera) else cc[0, 1] < 1.

mask = ref_mask & test_mask
Expand Down

0 comments on commit bf3f467

Please sign in to comment.