Skip to content
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

Add bounding box iteration #466

Merged
merged 7 commits into from Mar 1, 2019

Conversation

JoostJM
Copy link
Collaborator

@JoostJM JoostJM commented Feb 18, 2019

Builds on PR #463 by adding bounding-box constrained iteration in the C extensions.

This is then used to speed up and simplify voxel-based extraction:

  • no need to iterate over the entire image, only the defined kernel
  • no need to keep updating the mask array, kernel defined as combination of maskArray and bounding box in C (i.e. voxel index +/- kernelRadius in moving dimensions)
  • allows vectorized feature calculation of multiple voxels

@JoostJM JoostJM force-pushed the add-bounding-box-iteration branch 5 times, most recently from d69cb4c to 4125f3e Compare February 20, 2019 16:23
Update C extensions to iterate only over a view of the image (bounding box). This can be used later on to rapidly define kernels for a voxel based-calculation.
- Define bounding box array as {L_0, L_1, ..., L_n, U_0, U_1, ..., U_n} (i.e. first all lower bounds, then all upper bounds).
- Start iteration over the image on by calculating the first `i` from the lower bounds.
- Upon each increase of `i`, calculate to see if `i` exceeds image bounds, and if so, increase `i` in that dimension to the lower bound.
- When computing neighbours, compare against bounding box instead of size to determine valid angles.
- For now, fix bb initialization to {0, size - 1} in each dimension.

Testing:
- Add print statements in GLCM and GLRLM to reflect new behaviour.

Finally, add a check to ensure allocation for memory for `size` and `strides` is successful.
Add an extra dimension as the first dimension of each texture matrix, which will correspond to the matrix for the segment (segment-based, size 1) or the specific kernel identified by the voxel index in the passed array (voxel-based).
This will allow a more vectorized calculation of kernels when processing in by-voxel mode.

Additionally, update the python formulas to allow for this additional dimension by adding axis specifications to all reducing operations and updating defined axes to shift by +1.

Use numpy.squeeze to convert the returned result in segment-based calculation from a 1-D array with size 1 to a scalar float value.
Implement vectorized calculation of voxel kernels and remove need of kernel generation for voxel-based calculation of texture matrices.
For the latter, define kernels by updating the bounding box for calculation on the fly in the C extension. The mask array is then only utilized to either mask the kernels (`maskedKernel=True`, maskArray elements true where segmented) or no mask, in which case the maskArray is set to `numpy.ones` of `shape(imageArray)`. This reduces both the number of python-based loops, as the iteration time in the C extension (only iterates over the kernel for each voxel, not the entire image).

Vectorize all feature formulas (exception: shape and shape2D features)

Update firstorder to work with vectorized calculation (add dimension to `targetVoxelArray`, add `discretizedTargetVoxelArray`.

Add voxelSetting parameter `voxelBatch`, which controls the maximum number of voxel calculated in a vectorized way (allows specification of less voxels in 1 batch to conserve memory). Default setting of -1 means all voxels are calculated in one batch

Additionally, remove `self.matrix`, as this is reference equal to `self.imageArray` when applying binning.
In segment based mode, empty angles are removed from the calculation, but when calculating multiple voxel kernels, empty angles may presist (empty in some kernels, not in others). Exclude those angles from the calculations per voxel by setting them to NaN and using `nanmean` for combining angle results.

Additionally, move some of the coefficients that are only used in single features to those features. Conserves memory and prevents unnecessary calculation.
When growing the regions, mask voxels are set to 0 to prevent reprocessing. However, when extracting voxel-based, these need to be reset to allow for correct processing of voxels in the subsequent kernels. Therefore, if Nvox > 1, keep track of the processed voxels and reset them after processing.

Additionally, force cast PyArray_DIM to make function `try_parse_voxels_arr` consistent with function `try_parse_arrays`.
@JoostJM JoostJM merged commit 49bda8c into AIM-Harvard:master Mar 1, 2019
@JoostJM JoostJM deleted the add-bounding-box-iteration branch March 15, 2019 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant