Skip to content

Commit

Permalink
rgb compatibility #171
Browse files Browse the repository at this point in the history
  • Loading branch information
hcwinsemius committed Jun 21, 2024
1 parent 2cbce5a commit 37d6a70
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 24 deletions.
11 changes: 8 additions & 3 deletions pyorc/api/cameraconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ def get_bbox(
self,
camera: Optional[bool] = False,
h_a: Optional[float] = None,
z_a: Optional[float] = None,
within_image: Optional[bool] = False,
expand_exterior=True,
) -> Polygon:
Expand All @@ -423,8 +424,11 @@ def get_bbox(
In this case ``h_a`` may be set to provide the right water level, to estimate the bounding box for.
h_a : float, optional
If set with ``camera=True``, then the bbox coordinates will be transformed to the camera perspective,
using h_a as a present water level. In case a video with higher (lower) water levels is used, this
will result in a different perspective plane than the control video.
using h_a as a present water level (in local datum). In case a video with higher (lower) water levels is
used, this will result in a different perspective plane than the control video.
z_a : float, optional
similar to setting h_a, but z_a represent the vertical coordinate in the coordinate reference system of
the camera configuration instead of the local datum.
within_image : bool, optional (default False)
Set to True to make an attempt to remove parts of the polygon that lie outside of the image field of view
expand_exterior : bool, optional
Expand Down Expand Up @@ -452,7 +456,8 @@ def get_bbox(
new_coords = np.linspace(coords[n], coords[n + 1], 100)
coords_expand = np.r_[coords_expand, new_coords]
coords = coords_expand
z_a = self.get_z_a(h_a)
if not z_a:
z_a = self.get_z_a(h_a)
# add vertical coordinates to the set
coords = np.c_[coords, np.ones(len(coords))*z_a]
# project points to pixel image coordinates
Expand Down
26 changes: 15 additions & 11 deletions pyorc/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ def project_numpy(
points_cam = cc.project_points(
list(zip(xs, ys, np.ones(len(xs)) * z))
)
# round cam coordinates to pixels
points_cam = np.int64(np.round(points_cam))
# find locations that lie within the camera objective, rest should remain missing value
idx_in = np.all(
[
Expand All @@ -186,21 +188,25 @@ def project_numpy(
],
axis=0
)
# round cam coordinates to pixels
points_cam = np.int64(np.round(points_cam))
# coerce 2D idxs to 1D idxs
idx_back = np.array(points_cam[idx_in, 1]) * len(da.x) + np.array(points_cam[idx_in, 0])
vals = da.stack(points=("y", "x")).isel(points=idx_back)
da_new[:, idx_in] = vals
da_new[..., idx_in] = vals

if reducer is not "nearest":
# also fill in the parts that have valid averaged pixels
coli, rowi = np.meshgrid(
np.arange(len(da.x)),
np.arange(len(da.y))
)
poly = cc.get_bbox(camera=True, h_a=0.)
mask = rasterize([poly], out_shape=(cc.height, cc.width)) == 1
poly = cc.get_bbox(camera=True, z_a=z)
mask = xr.DataArray(
rasterize([poly], out_shape=(cc.height, cc.width)) == 1,
coords={"y": da.y, "x": da.x},
name="mask",
# attrs=da.attrs
)
# mask = rasterize([poly], out_shape=(cc.height, cc.width)) == 1
# retrieve only the pixels within mask
src_pix = list(
zip(
Expand All @@ -217,7 +223,7 @@ def project_numpy(
x_pix, y_pix, z_pix = dst_pix.T
idx_y, idx_x = helpers.map_to_pixel(x_pix, y_pix, cc.transform)
# ensure no pixels outside of target grid (can be in case of edges)
idx_inside = np.all([idx_y >= 0, idx_y < len(y), idx_x >= 0, idx_x < len(idx_x)], axis=0)
idx_inside = np.all([idx_y >= 0, idx_y < len(y), idx_x >= 0, idx_x < len(x)], axis=0)
idx_x = idx_x[idx_inside]
idx_y = idx_y[idx_inside]
# get 1D flat array indexes
Expand All @@ -226,7 +232,7 @@ def project_numpy(
# flatten points within mask
da_point = da.where(mask).stack(points=("y", "x"))
da_point["points_idx"] = "points", np.arange(len(da_point.points))
da_point = da_point.dropna(dim="points") # TODO: check if order is correct
da_point = da_point.dropna(dim="points")

# ensure any values that may be outside of target grid are dropped
da_point = da_point.isel(points=idx_inside)
Expand All @@ -249,9 +255,7 @@ def project_numpy(
expected_groups=classes,
engine="numba"
)

# replace the nearest by mean values where relevant
idxs = da_point.group.values
da_point["group"] = idxs
da_new[:, classes] = da_point.values
da_point["group"] = da_new.group[classes]
da_new[..., classes] = da_point.values
return da_new.unstack()
22 changes: 12 additions & 10 deletions tests/test_frames.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@
import matplotlib.pyplot as plt

@pytest.mark.parametrize(
"frames, resolution, method, dims, shape",
"frames, resolution, method, dims, shape, kwargs",
[
(pytest.lazy_fixture("frames_grayscale"), 0.1, "numpy", 3, (79, 88)),
(pytest.lazy_fixture("frames_rgb"), 0.1, "numpy", 4, (79, 88, 3)),
(pytest.lazy_fixture("frames_grayscale"), 0.1, "cv", 3, (79, 88)),
(pytest.lazy_fixture("frames_grayscale"), 0.01, "cv", 3, (786, 878)),
(pytest.lazy_fixture("frames_grayscale"), 0.05, "cv", 3, (157, 176)),
(pytest.lazy_fixture("frames_rgb"), 0.1, "cv", 4, (79, 88, 3)),
(pytest.lazy_fixture("frames_grayscale"), 0.1, "numpy", 3, (79, 88), {}),
(pytest.lazy_fixture("frames_grayscale"), 0.1, "numpy", 3, (79, 88), {"reducer": "mean"}),
(pytest.lazy_fixture("frames_rgb"), 0.1, "numpy", 4, (79, 88, 3), {"reducer": "mean"}),
(pytest.lazy_fixture("frames_rgb"), 0.1, "numpy", 4, (79, 88, 3), {}),
(pytest.lazy_fixture("frames_grayscale"), 0.1, "cv", 3, (79, 88), {}),
(pytest.lazy_fixture("frames_grayscale"), 0.01, "cv", 3, (786, 878), {}),
(pytest.lazy_fixture("frames_grayscale"), 0.05, "cv", 3, (157, 176), {}),
(pytest.lazy_fixture("frames_rgb"), 0.1, "cv", 4, (79, 88, 3), {}),
]
)
def test_project(frames, resolution, method, dims, shape):
# def test_project(frames_grayscale, resolution=0.01, dims=3, shape=(840, 1100)):
def test_project(frames, resolution, method, dims, shape, kwargs):
# import matplotlib
# matplotlib.use('Qt5Agg')
frames_proj = frames.frames.project(resolution=resolution, method=method)
frames_proj = frames.frames.project(resolution=resolution, method=method, **kwargs)
# check amount of time steps is equal
assert(len(frames_proj.time) == len(frames.time))
# check if the amount of dims is as expected (different for rgb)
Expand All @@ -27,6 +28,7 @@ def test_project(frames, resolution, method, dims, shape):

# import matplotlib.pyplot as plt
# plt.imshow(frames_proj[0])
# plt.colorbar()
# plt.show()


Expand Down

0 comments on commit 37d6a70

Please sign in to comment.