package ie.dcu.image.binary; import ie.dcu.image.dt.DistanceTransform; import ie.dcu.matrix.*; import ie.dcu.matrix.Matrix.Type; /** * Implementation of the Medial Axis Transform (MAT). * * Computes the MAT by finding the Laplace of the square distance transform. * * @author Kevin McGuinness */ public class MedialAxisTransformOp extends AbstractBinaryImageOp { private boolean simpleLaplace = false; @Override protected Matrix processImage(ByteMatrix input) { DistanceTransform transform = new DistanceTransform(); transform.init(input, foregroundValue); IntMatrix dt = transform.computeSquareTransform(); return laplace(dt).clamp(0, Integer.MAX_VALUE); } private IntMatrix laplace(IntMatrix m) { return simpleLaplace ? laplace4(m) : laplace8(m); } private IntMatrix laplace4(IntMatrix m) { IntMatrix result = new IntMatrix(m.rows, m.cols); int n0, n1, n2, n3; for (int i = 0; i < m.rows; i++) { n0 = (i != 0) ? 1 : 0; n3 = (i != m.rows - 1) ? 1 : 0; for (int j = 0; j < m.cols; j++) { n1 = (j != 0) ? 1 : 0; n2 = (j != m.cols-1) ? 1 : 0; int value = (n0 + n1 + n2 + n3) * m.intAt(i, j); value -= (n0 != 0) ? m.intAt(i-1, j) : 0; value -= (n1 != 0) ? m.intAt(i, j-1) : 0; value -= (n2 != 0) ? m.intAt(i, j+1) : 0; value -= (n3 != 0) ? m.intAt(i+1, j) : 0; result.setIntAt(i, j, value); } } return result; } private IntMatrix laplace8(IntMatrix m) { IntMatrix result = new IntMatrix(m.rows, m.cols); int a = m.rows - 1; int b = m.cols - 1; int n0, n1, n2, n3, n4, n5, n6, n7; for (int i = 0; i < m.rows; i++) { for (int j = 0; j < m.cols; j++) { n0 = (i != 0 && j != 0) ? 1 : 0; n1 = (i != 0) ? 1 : 0; n2 = (i != 0 && j != b) ? 1 : 0; n3 = (j != 0) ? 1 : 0; n4 = (j != b) ? 1 : 0; n5 = (i != a && j != 0) ? 1 : 0; n6 = (i != a) ? 1 : 0; n7 = (i != a && j != b) ? 1 : 0; int w = (n0 + n1 + n2 + n3 + n4 + n5 + n6 + n7); int v = w * m.intAt(i, j); v -= (n0 != 0) ? m.intAt(i-1, j-1) : 0; v -= (n1 != 0) ? m.intAt(i-1, j ) : 0; v -= (n2 != 0) ? m.intAt(i-1, j+1) : 0; v -= (n3 != 0) ? m.intAt(i , j-1) : 0; v -= (n4 != 0) ? m.intAt(i , j+1) : 0; v -= (n5 != 0) ? m.intAt(i+1, j-1) : 0; v -= (n6 != 0) ? m.intAt(i+1, j ) : 0; v -= (n7 != 0) ? m.intAt(i+1, j+1) : 0; result.setIntAt(i, j, v); } } return result; } public Type getDefaultMatrixType() { return Matrix.Type.Int; } }