clij / clij/clij2-docs

mesh_closest_points.ijm does not mesh closest points

Open
#14 4 comments 1 reaction 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.