public void bwd() { if (m_count % m_breaks[0] == 0) { // we check this already, so just do it m_ra.setPosition(m_lastPos[0], 0); m_ra.bck(1); // skip the last dim, is handled by previous // dims for (int i = 1; i < m_breaks.length - 1; i++) { if (m_count % m_breaks[i] == 0) { m_ra.setPosition(m_lastPos[i], i); m_ra.bck(i + 1); } } } else { m_ra.bck(0); } m_count--; }
/** * Computes the n-dimensional 1st derivative vector in 3x3x3...x3 environment for a certain {@link * Img} location defined by the position of the {@link LocalizableByDimCursor}. * * @param cursor - the position for which to compute the Hessian Matrix * @param derivativeVector - the derivative, which is essentially a one-dimensional {@link * DoubleType} {@link Img} of size [numDimensions] */ public static final <T extends RealType<T>> void computeDerivativeVector( final RandomAccess<T> cursor, final Img<DoubleType> derivativeVector) { // instantiate a cursor to traverse over the derivative vector we want to compute, the position // defines the current dimension final Cursor<DoubleType> derivativeCursor = derivativeVector.localizingCursor(); while (derivativeCursor.hasNext()) { derivativeCursor.fwd(); final int dim = derivativeCursor.getIntPosition(0); // we compute the derivative for dimension A like this // // | a0 | a1 | a2 | // ^ // | // Original position of Img cursor // // d(a) = (a2 - a0)/2 // we divide by 2 because it is a jump over two pixels cursor.fwd(dim); final double a2 = cursor.get().getRealDouble(); cursor.bck(dim); cursor.bck(dim); final double a0 = cursor.get().getRealDouble(); // back to the original position cursor.fwd(dim); derivativeCursor.get().setReal((a2 - a0) / 2); } }
// change the return type to Img<FloatType> and adjust the code accordingly public <T extends RealType<T>> Img<T> gradient(Img<T> img) { // create a new ImgLib2 image of same dimensions, but FloatType // to to that, create a new PlanarImgFactory and instantiate a new // Img<FloatType> /** * ImgFactory<T> imgFactory = img.factory(); Img<T> gradientImg = imgFactory.create( img, * img.firstElement() ); */ // create a localizing cursor on the GradientImg, it will iterate all pixels // and is able to efficiently return its position at each pixel, at each // pixel we will compute the gradient /** Cursor<T> cursor = gradientImg.localizingCursor(); */ // We extend the input image by a mirroring out of bounds strategy so // that we can access pixels outside of the image RandomAccessible<T> view = Views.extendMirrorSingle(img); // instantiate a RandomAccess on the extended view, it will be used to // compute the gradient locally at each pixel location RandomAccess<T> randomAccess = view.randomAccess(); // iterate over all pixels while (cursor.hasNext()) { // move the cursor to the next pixel cursor.fwd(); // compute gradient in each dimension double gradient = 0; for (int d = 0; d < img.numDimensions(); ++d) { // set the randomaccess to the location of the cursor randomAccess.setPosition(cursor); // move one pixel back in dimension d randomAccess.bck(d); // get the value double v1 = randomAccess.get().getRealDouble(); // move twice forward in dimension d, i.e. // one pixel above the location of the cursor randomAccess.fwd(d); randomAccess.fwd(d); // get the value double v2 = randomAccess.get().getRealDouble(); // add the square of the magnitude of the gradient gradient += ((v2 - v1) * (v2 - v1)) / 4; } // the square root of all quadratic sums yields // the magnitude of the gradient at this location, // set the pixel value of the gradient image // change the value to float, otherwise it will not be // compatible cursor.get().setReal(Math.sqrt(gradient)); } return gradientImg; }
/** * Computes the n-dimensional Hessian Matrix in 3x3x3...x3 environment for a certain {@link Img} * location defined by the position of the {@link LocalizableByDimCursor}. * * @param cursor - the position for which to compute the Hessian Matrix * @param hessianMatrix - the hessian matrix, which is essentially a two-dimensional {@link * DoubleType} {@link Img} of size [numDimensions][numDimensions] */ public static final <T extends RealType<T>> void computeHessianMatrix( final RandomAccess<T> cursor, final Img<DoubleType> hessianMatrix) { // we need this for all diagonal elements final double temp = 2.0 * cursor.get().getRealDouble(); // instantiate a cursor to traverse over the hessian matrix we want to compute, the position // defines the current dimensions final Cursor<DoubleType> hessianCursor = hessianMatrix.localizingCursor(); // another cursor to fill the redundant lower area of the matrix final RandomAccess<DoubleType> hessianCursorLowerHalf = hessianMatrix.randomAccess(); while (hessianCursor.hasNext()) { hessianCursor.fwd(); final int dimA = hessianCursor.getIntPosition(0); final int dimB = hessianCursor.getIntPosition(1); if (dimA == dimB) { // diagonal elements h(aa) for dimension a // computed from the row a in the input Img // // | a0 | a1 | a2 | // ^ // | // Original position of Img cursor // // h(aa) = (a2-a1) - (a1-a0) // = a2 - 2*a1 + a0 cursor.fwd(dimA); final double a2 = cursor.get().getRealDouble(); cursor.bck(dimA); cursor.bck(dimA); final double a0 = cursor.get().getRealDouble(); // back to the original position cursor.fwd(dimA); hessianCursor.get().set(a2 - temp + a0); } else if (dimB > dimA) // we compute all elements above the diagonal (see below for explanation) { // other elements h(ab) are computed as a combination // of dimA (dimension a) and dimB (dimension b), i.e. we always operate in a // two-dimensional plane // ______________________ // | a0b0 | a1b0 | a2b0 | // | a0b1 | a1b1 | a2b1 | // | a0b2 | a1b2 | a2b2 | // ---------------------- // where a1b1 is the original position of the cursor // // h(ab) = ( (a2b2-a0b2)/2 - (a2b0 - a0b0)/2 )/2 // // we divide by 2 because these are always jumps over two pixels // we only have to do that if dimB > dimA, // because h(ab) = h(ba) cursor.fwd(dimB); cursor.fwd(dimA); final double a2b2 = cursor.get().getRealDouble(); cursor.bck(dimA); cursor.bck(dimA); final double a0b2 = cursor.get().getRealDouble(); cursor.bck(dimB); cursor.bck(dimB); final double a0b0 = cursor.get().getRealDouble(); cursor.fwd(dimA); cursor.fwd(dimA); final double a2b0 = cursor.get().getRealDouble(); // back to the original position cursor.bck(dimA); cursor.fwd(dimB); hessianCursor.get().set(((a2b2 - a0b2) / 2 - (a2b0 - a0b0) / 2) / 2); // update the corresponding element below the diagonal hessianCursorLowerHalf.setPosition(dimB, 0); hessianCursorLowerHalf.setPosition(dimA, 1); hessianCursorLowerHalf.get().set(hessianCursor.get()); } } }