mesh_closest_points.ijm does not mesh closest points
- Dominant language
- ImageJ Macro
- Stars
- 8
- Forks
- 14
- PR merge metrics
- No merged PRs in 30d
Description
I was using your mesh_closest_points.ijm as a starting point for a macro and found an error stemming from
`Ext.CLIJ2_generateDistanceMatrix(pointlist, pointlist, distance_matrix);`
specifically, generateDistanceMatrix() creates a distance matrix of (n+1)*(m+1) pixels, that has all (X, 0) and (0, Y) pixels set to '0' intensity, and the 'desired' distances are shifted by X+1 and Y+1 pixels. For example, if there are 15 points, the distance_matrix is 16x16 pixels, with all pixels at (X, 0) and (0, Y) having intensity value == 0 (i.e. the first row and column, respectively, are black). I'm guessing this is so that the intensity from the label corresponds with the X and/or Y value in the distance_matrix, rather than the index. Either way, this leads to downstream issues, e.g. when generating a Results table from these images, as the corresponding columns are right-shifted and rows are down-shifted due to the blank column1 and row1, thus throwing off the data extraction, adding a point at (0,0), and ignoring the last point (now row/column 16). I'm sure there are other ways to deal with it, but I found that cropping the first row and column of the distance_matrix solved the issue.
Here's the same code with my additions. I left the Ext.CLIJ2_pull(distance_matrix); in there so you can see what I'm referring to, but it's not required. A couple other minor bug fixes and additions too. Either way, thanks for the backbone!
`// CLIJ example macro: mesh_closest_pointsijm
//
// This macro shows how to draw lines between closest points in the GPU.
//
// Author: Robert Haase,
// September 2019
// ---------------------------------------------
// Get test data
run("Blobs (25K)");
//open("C:/structure/data/blobs.gif");
getDimensions(width, height, channels, slices, frames);
input = getTitle();
threshold = 128;
// Init GPU
run("CLIJ2 Macro Extensions", "cl_device=");
Ext.CLIJ2_clear();
// push data to GPU
Ext.CLIJ2_push(input);
// cleanup ImageJ
run("Close All");
// blur
blurred = "blurred";
Ext.CLIJ2_blur2D(input, blurred, 15, 15);
// detect spots
detected_spots = "detected_spots";
Ext.CLIJ2_detectMaximaBox(blurred, detected_spots, 10);
Ext.CLIJ2_pullBinary(detected_spots);
// get spot positions as pointlist
pointlist = "pointlist";
Ext.CLIJ2_spotsToPointList(detected_spots, pointlist);
Ext.CLIJ2_pull(pointlist);
Ext.CLIJ2_getSize(pointlist);
number_of_detected_spots = getResult("Width", nResults() - 1);
IJ.log("number of spots: " + number_of_detected_spots);
// determine distances between points
distance_matrix = "distance_matrix";
Ext.CLIJ2_generateDistanceMatrix(pointlist, pointlist, distance_matrix);
Ext.CLIJ2_pull(distance_matrix);
// crop first row and column of distance_matrix
crop_distance_matrix = "crop_distance_matrix";
Ext.CLIJ2_crop2D(distance_matrix, crop_distance_matrix, 1, 1, number_of_detected_spots, number_of_detected_spots);
Ext.CLIJ2_pull(crop_distance_matrix);
// determine n closest points
n_closest_points = 5;
cropclosestPointsIndices = "cropclosestPointsIndices";
Ext.CLIJ2_nClosestPoints(crop_distance_matrix, cropclosestPointsIndices, n_closest_points);
// empty results table
run("Clear Results");
// we build a table with 2+n rows:
// x and y of the points and n rows with indices to closes points.
// as every points is the closest to itself, row number 3 will always be 0, 1, 3, 4 ...
Ext.CLIJ2_image2DToResultsTable(pointlist);
Ext.CLIJ2_image2DToResultsTable(cropclosestPointsIndices);
crop_mesh = "crop_mesh";
Ext.CLIJ2_create2D(crop_mesh, width, height, 32);
Ext.CLIJ2_set(crop_mesh, 0);
for (p = 0; p < number_of_detected_spots; p++) {
x1 = getResult("X" + p, 0);
y1 = getResult("X" + p, 1);
// we start at 1 (and not at 0) because we
// don't want to draw line from the point
// to itself
for (q = 1; q < n_closest_points; q++) {
pointIndex = getResult("X" + p, q + 2);
x2 = getResult("X" + pointIndex, 0);
y2 = getResult("X" + pointIndex, 1);
thickness = 1;
Ext.CLIJ2_drawLine(crop_mesh, x1, y1, 0, x2, y2, 0, thickness,p);
}
}mesh = "mesh";
Ext.CLIJ2_create2D(mesh, width, height, 32);
Ext.CLIJ2_set(mesh, 0);
for (p = 0; p < number_of_detected_spots; p++) {
x1 = getResult("X" + p, 0);
y1 = getResult("X" + p, 1);
// we start at 1 (and not at 0) because we
// don't want to draw line from the point
// to itself
for (q = 1; q < n_closest_points; q++) {
pointIndex = getResult("X" + p, q + 2);
x2 = getResult("X" + pointIndex, 0);
y2 = getResult("X" + pointIndex, 1);
thickness = 1;
Ext.CLIJ2_drawLine(mesh, x1, y1, 0, x2, y2, 0, thickness, p);
}
}
Table.rename("Results", "closestPointsIndices");
// show result
Ext.CLIJ2_pull(mesh);
run("3-3-2 RGB");`
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with mesh_closest_points.ijm and inspect the Ext.CLIJ2_generateDistanceMatrix call, then follow how distance_matrix is converted into the Results table. Run the macro with the Blobs (25K) test data and verify that closest-point indices align with the detected points and no extra (0,0) point or final point is lost.
Written by the indexing model from the issue text.
Assessment
- Domain
- documentation
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100