GPU accelerated image processing for everyone
Authors: Robert Haase, Daniela Vorkel, April 2020
When dealing with three dimensional point coordinates, it is mandatory to take the voxel size into account, e.g. for measuring distances between points. This example shows how to multiply a list of coordinates by a given voxel size.
run("CLIJ2 Macro Extensions", "cl_device=[gfx900]"); Ext.CLIJ2_clear();
We define the voxel size as an ImageJ macro array and push it to the GPU:
Ext.CLIJ2_pushArray(voxel_size, newArray(0.2, 0.2, 0.5), 1, 3, 1); Ext.CLIJ2_print(voxel_size);
> 0.2 > 0.2 > 0.5
We also define a CLIJ-matrix of XYZ coordinates:
number_of_coordinates = 4; number_of_dimensions = 3; Ext.CLIJ2_pushArray(pointlist, newArray( 1, 3, 5, 11, // X 0, 6, 1, 2, // Y 9, 11, 6, 2 // Z ), number_of_coordinates, number_of_dimensions, 1); Ext.CLIJ2_print(pointlist);
> 1.0 3.0 5.0 11.0 > 0.0 6.0 1.0 2.0 > 9.0 11.0 6.0 2.0
When multiplying images of different size, the clamp-to-edge (CLK_ADDRESS_CLAMP_TO_EDGE) strategy is used: to access a pixel outside the image, the value of a closest pixel at the image boundary is used, instead. This enables to multiply a vector by a matrix, like shown above:
Ext.CLIJ2_multiplyImages(pointlist, voxel_size, transformed_pointlist); Ext.CLIJ2_print(transformed_pointlist);
> 0.2 0.6 1.0 2.2 > 0.0 1.2 0.2 0.4 > 4.5 5.5 3.0 1.0
Note: If the resulting image does not exist in first place, CLIJ has to guess its size. Thus, it takes the input size of the first image to operate. So, if you permute the input parameters, the resulting matrix size will be ‘wrong’:
Ext.CLIJ2_multiplyImages(voxel_size, pointlist, transformed_pointlist2); Ext.CLIJ2_print(transformed_pointlist2);
> 0.2 > 0.0 > 4.5
At the end of the macro, clean up:
Ext.CLIJ2_clear();