-
Notifications
You must be signed in to change notification settings - Fork 0
grid for cmc added #178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
grid for cmc added #178
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
f6d0b1b
first commit
cfs-data 602f58d
update
cfs-data 4193f62
update
cfs-data e249da7
update
cfs-data 20f37a4
first commit
cfs-data 7acf340
Merge branch 'main' of https://github.com/NetherlandsForensicInstitut…
cfs-data d7f6a2f
comments
cfs-data feef72b
comments
cfs-data 7798fab
update utils
cfs-data ea78d41
add comment
cfs-data b6d7a5e
grid for cmc added
SimoneAriens ccf68a2
cicd fix
SimoneAriens 799cebc
fix
SimoneAriens 4bab8a1
Merge branch 'main' of https://github.com/NetherlandsForensicInstitut…
cfs-data 000a1c4
Merge branch 'cmc-pipeline-base' of https://github.com/NetherlandsFor…
cfs-data 80368c1
fix pipeline
cfs-data 7c052d5
update branch
cfs-data 2d103bf
fix tests
cfs-data a04d492
update branch
cfs-data 2abf025
feedback
SimoneAriens fdafd41
Merge branch 'main' of https://github.com/NetherlandsForensicInstitut…
cfs-data File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
packages/scratch-core/src/conversion/surface_comparison/cell_registration.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 88 additions & 37 deletions
125
packages/scratch-core/src/conversion/surface_comparison/grid.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,57 +1,108 @@ | ||
| from container_models.base import FloatArray2D | ||
| from container_models.scan_image import ScanImage | ||
| from conversion.surface_comparison.models import ComparisonParams | ||
| import math | ||
|
|
||
| from dataclasses import dataclass | ||
| import numpy as np | ||
|
|
||
| from container_models.base import FloatArray2D | ||
| from container_models.scan_image import ScanImage | ||
| from conversion.surface_comparison.models import GridCell | ||
| from conversion.surface_comparison.utils import convert_meters_to_pixels | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class GridCell: | ||
| def generate_grid( | ||
| scan_image: ScanImage, cell_size: tuple[float, float], minimum_fill_fraction: float | ||
| ) -> list[GridCell]: | ||
| """ | ||
| Container class for storing generated grid cells. | ||
| Generate a centered grid of cells covering the image. The image is assumed to be isotropic. | ||
|
|
||
| All the values of the attributes and properties are in pixel units. | ||
| The grid is symmetrically centered on the image using the MATLAB even/odd | ||
| seed logic. Cells with insufficient valid data are filtered out. | ||
|
|
||
| :param top_left: Tuple containing the top-left pixel coordinates (x, y) corresponding to the reference image. | ||
| :param cell_data: 2D array containing the sliced image data from the reference image. | ||
| :param scan_image: reference scan image | ||
| :param cell_size: size of the cells of the grid in meters | ||
| :param minimum_fill_fraction: minimum fraction of valid data of each cell | ||
| :return: list of valid grid cells | ||
| """ | ||
| cell_width, cell_height = convert_meters_to_pixels(cell_size, scan_image.scale_x) | ||
| xs = _tile_axis(scan_image.width, cell_width) | ||
| ys = _tile_axis(scan_image.height, cell_height) | ||
|
|
||
| top_left: tuple[int, int] | ||
| cell_data: FloatArray2D | ||
| output = [] | ||
| for y in ys: | ||
| for x in xs: | ||
| cell_data = extract_patch( | ||
| scan_image=scan_image, | ||
| coordinates=(x, y), | ||
|
SimoneAriens marked this conversation as resolved.
|
||
| patch_size=(cell_width, cell_height), | ||
| fill_value=np.nan, | ||
| ) | ||
| cell = GridCell(top_left=(x, y), cell_data=cell_data) | ||
| if cell.fill_fraction < minimum_fill_fraction: | ||
| continue | ||
| output.append(cell) | ||
| return output | ||
|
|
||
| @property | ||
| def width(self) -> int: | ||
| return self.cell_data.shape[1] | ||
|
|
||
| @property | ||
| def height(self) -> int: | ||
| return self.cell_data.shape[0] | ||
| def extract_patch( | ||
| scan_image: ScanImage, | ||
| coordinates: tuple[int, int], | ||
|
SimoneAriens marked this conversation as resolved.
|
||
| patch_size: tuple[int, int], | ||
| fill_value: float = np.nan, | ||
| ) -> FloatArray2D: | ||
| """ | ||
| Extract a rectangular patch from a scan image, padding with fill_value | ||
| where the patch extends beyond the image boundaries. | ||
|
|
||
| @property | ||
| def center(self) -> tuple[float, float]: | ||
| return self.top_left[0] + self.width / 2, self.top_left[1] + self.height / 2 | ||
| :param scan_image: source image to extract from | ||
| :param coordinates: (x, y) top-left corner of the patch, may be negative, in pixel coordinates | ||
| :param patch_size: (width, height) of the output patch | ||
| :param fill_value: value to use for out-of-bounds pixels | ||
| :return: 2D array of shape (height, width) | ||
| """ | ||
| x, y = coordinates | ||
|
SimoneAriens marked this conversation as resolved.
|
||
| width, height = patch_size | ||
|
|
||
| @property | ||
| def fill_fraction(self) -> float: | ||
| return float(np.count_nonzero(~np.isnan(self.cell_data)) / self.cell_data.size) | ||
| # Find the overlap between the patch and the image | ||
| row_start = max(y, 0) | ||
| row_end = min(y + height, scan_image.height) | ||
| col_start = max(x, 0) | ||
| col_end = min(x + width, scan_image.width) | ||
|
|
||
| def fill_nans(self, fill_value: float): | ||
| self.cell_data[np.isnan(self.cell_data)] = fill_value | ||
| if row_start >= row_end or col_start >= col_end: | ||
|
SimoneAriens marked this conversation as resolved.
SimoneAriens marked this conversation as resolved.
|
||
| raise ValueError( | ||
| f"Patch at ({x}, {y}) with size ({width}, {height}) " | ||
| f"has no overlap with image of size ({scan_image.width}, {scan_image.height})" | ||
| ) | ||
|
|
||
| # Get the patch | ||
| patch = scan_image.data[row_start:row_end, col_start:col_end] | ||
|
|
||
| def generate_grid(scan_image: ScanImage, params: ComparisonParams) -> list[GridCell]: | ||
| """TODO: Implement function.""" | ||
| # Pad where needed | ||
| pad_top = row_start - y | ||
| pad_bottom = y + height - row_end | ||
| pad_left = col_start - x | ||
| pad_right = x + width - col_end | ||
|
|
||
| # Create a dummy cell | ||
| x, y = 0, 0 # Top-left coordinates of cell in reference image | ||
| pixel_size = scan_image.scale_x # Assumes isotropic image | ||
| width, height = convert_meters_to_pixels( | ||
| values=params.cell_size, pixel_size=pixel_size | ||
| padded = np.pad( | ||
| patch, | ||
| pad_width=((pad_top, pad_bottom), (pad_left, pad_right)), | ||
| mode="constant", | ||
| constant_values=fill_value, | ||
| ) | ||
| dummy = GridCell( | ||
| top_left=(x, y), cell_data=scan_image.data[y : y + height, x : x + width] | ||
| ) | ||
| return [dummy] | ||
| return padded | ||
|
|
||
|
|
||
| def _tile_axis(image_size: int, cell_size: int) -> list[int]: | ||
| """Generate top-left coordinates for cells along one axis. | ||
|
|
||
| Places cells symmetrically around the midpoint of the image. When an | ||
| odd number of cells fits, one cell is centered on the midpoint. When | ||
| even, two cells straddle it. | ||
|
|
||
| :param image_size: image size in pixels along the axis | ||
| :param cell_size: cell size in pixels along the axis | ||
| :return: sorted list of top-left coordinates | ||
| """ | ||
| n = math.ceil(image_size / cell_size) | ||
| offsets = np.arange(n) - n / 2 | ||
| top_lefts = np.round(offsets * cell_size + image_size / 2).astype(int) | ||
| return top_lefts.tolist() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.