src_image_labelingDebug.js
import {Point2D} from '../math/point.js';
// doc imports
/* eslint-disable no-unused-vars */
import {Line} from '../math/line.js';
/* eslint-enable no-unused-vars */
/**
* Helper for the LabelingFilter, provides a debug display for diameters and
* contours.
*
* Temporary until a proper way of rendering them is added.
*/
export class LabelingDebug {
/**
* Cleans buffer of debug lines before calculations.
*
* @param {TypedArray} imageBuffer The image buffer to clean.
*/
cleanBuffer(imageBuffer) {
for (let i = 0; i < imageBuffer.length; i++) {
if (imageBuffer[i] >= 128) {
imageBuffer[i] = imageBuffer[i] - 128;
}
}
}
/**
* Convert a slice local world coordinate to a slice local offset value.
*
* @param {Point2D} point Point on the slice, scaled.
* @param {number[]} unitVectors The unit vectors for index to offset
* conversion.
* @param {number[]} spacing The pixel spacing of the image.
*
* @returns {number} Offset relative to the offset at the start of the slice.
*/
#sliceWorldToSliceOffset(point, unitVectors, spacing) {
const offset =
(unitVectors[0] * Math.round(point.getX() / spacing[0])) +
(unitVectors[1] * Math.round(point.getY() / spacing[1]));
return offset;
}
/**
* Draw a debug line segment of an angle less that 45 degrees.
* Points should be in slice world space.
*
* @param {TypedArray} imageBuffer The image buffer to draw debug lines on.
* @param {number[]} unitVectors The unit vectors for index to offset
* conversion.
* @param {number[]} spacing The pixel spacing of the image.
* @param {Line} line The line segment to plot.
* @param {number} z The slice index.
*/
#plotLineLow(imageBuffer, unitVectors, spacing, line, z) {
const p0 = line.getBegin();
const p1 = line.getEnd();
const dx = line.getDeltaX();
const dy = Math.abs(line.getDeltaY());
let D = 2 * dy - dx;
let y = p0.getY();
const yi = (p0.getY() < p1.getY()) ? 1 : -1;
for (let x = p0.getX(); x <= p1.getX(); x++) {
const sliceOffset =
this.#sliceWorldToSliceOffset(new Point2D(x, y), unitVectors, spacing);
const offset = sliceOffset + (unitVectors[2] * z);
imageBuffer[offset] = imageBuffer[offset] + 128;
if (D > 0) {
y = y + yi;
D = D - 2 * dx;
}
D = D + 2 * dy;
}
}
/**
* Draw a debug line segment of an angle greater that 45 degrees.
* Points should be in slice world space.
*
* @param {TypedArray} imageBuffer The image buffer to draw debug lines on.
* @param {number[]} unitVectors The unit vectors for index to offset
* conversion.
* @param {number[]} spacing The pixel spacing of the image.
* @param {Line} line The line segment to plot.
* @param {number} z The slice index.
*/
#plotLineHigh(imageBuffer, unitVectors, spacing, line, z) {
const p0 = line.getBegin();
const p1 = line.getEnd();
const dx = Math.abs(line.getDeltaX());
const dy = line.getDeltaY();
let D = 2 * dx - dy;
let x = p0.getX();
const xi = (p0.getX() < p1.getX()) ? 1 : -1;
for (let y = p0.getY(); y <= p1.getY(); y++) {
const sliceOffset =
this.#sliceWorldToSliceOffset(new Point2D(x, y), unitVectors, spacing);
const offset = sliceOffset + (unitVectors[2] * z);
imageBuffer[offset] = imageBuffer[offset] + 128;
if (D > 0) {
x = x + xi;
D = D - 2 * dy;
}
D = D + 2 * dx;
}
}
/**
* Draw a debug line segment.
* Points should be in slice world space.
*
* @param {TypedArray} imageBuffer The image buffer to draw debug lines on.
* @param {number[]} unitVectors The unit vectors for index to offset
* conversion.
* @param {number[]} spacing The pixel spacing of the image.
* @param {Line} line The line segment to plot.
* @param {number} z The slice index.
*/
#plotPoints(imageBuffer, unitVectors, spacing, line, z) {
const p0 = line.getBegin();
const p1 = line.getEnd();
if (Math.abs(line.getDeltaY()) < Math.abs(line.getDeltaX())) {
if (p0.getX() < p1.getX()) {
this.#plotLineLow(
imageBuffer,
unitVectors,
spacing,
line,
z
);
} else {
this.#plotLineLow(
imageBuffer,
unitVectors,
spacing,
line.getFlipped(),
z
);
}
} else {
if (p0.getY() < p1.getY()) {
this.#plotLineHigh(
imageBuffer,
unitVectors,
spacing,
line,
z
);
} else {
this.#plotLineHigh(
imageBuffer,
unitVectors,
spacing,
line.getFlipped(),
z
);
}
}
}
/**
* Renders debug lines for contours and diameters.
* The pixel value of the debug lines are the segmentation label of the
* segment + 128.
*
* @param {TypedArray} imageBuffer The image buffer to draw debug lines on.
* @param {number[]} unitVectors The unit vectors for index to offset
* conversion.
* @param {number[]} sizes The image dimensions.
* @param {number[]} spacing The pixel spacing of the image.
* @param {TypedArray} borders The buffer containing the border pixel arrays.
* @param {object} maxDiameters The dictionary of calculated diameters.
*/
drawDebugLines(
imageBuffer,
unitVectors,
sizes,
spacing,
borders,
maxDiameters
) {
Object.values(maxDiameters).map((diameter) => {
this.#plotPoints(
imageBuffer,
unitVectors,
spacing,
diameter.major.line,
diameter.zIndex
);
if (typeof diameter.minor !== 'undefined') {
this.#plotPoints(
imageBuffer,
unitVectors,
spacing,
diameter.minor.line,
diameter.zIndex
);
}
});
}
} //class LabelingDebug