/** * Compute the steepest descent images of the template at the identity warp. Each steepest descent * image comprises the partial derivatives of template intensities with respect to one parameter * of the warp function. * * <p>The result is stored in the <em>n+1</em> dimensional {@link #target} image. Dimension * <em>n</em> is used to index the partial derivative. For example, the partial derivative by the * second parameter of the warp function is stored in slice <em>n=1</em>. * * @param gradients n+1 dimensional image of partial derivatives of the template. Dimension n is * used to index the partial derivative. For example, the partial derivative by Y is stored in * slice n=1. * @param warpFunction The warp function to be applied to the template. The partial derivatives of * template intensities with respect to the parameters of this warp function are computed. * @param target Image of <em>n+1</em> dimensions to store the steepest descent Dimension * <em>n</em> is used to index the parameters of the warp function. For example, the partial * derivative of the template image intensity by parameter 2 of the warp function at pixel * <em>(x,y)</em> is stored at position <em>(x,y,1)</em>. */ public static <T extends NumericType<T>> void computeSteepestDescents( final RandomAccessibleInterval<T> gradients, final WarpFunction warpFunction, final RandomAccessibleInterval<T> target) { final int n = gradients.numDimensions() - 1; final int numParameters = warpFunction.numParameters(); final T tmp = Util.getTypeFromInterval(gradients).createVariable(); for (int p = 0; p < numParameters; ++p) { for (int d = 0; d < n; ++d) { final Cursor<T> gd = Views.flatIterable(Views.hyperSlice(gradients, n, d)).localizingCursor(); for (final T t : Views.flatIterable(Views.hyperSlice(target, n, p))) { tmp.set(gd.next()); tmp.mul(warpFunction.partial(gd, d, p)); t.add(tmp); } } } }
double alignStep(final RandomAccessibleInterval<T> image) { // compute error image = warped image - template computeDifference(Views.extendBorder(image), currentTransform, template, error); // compute transform parameter update final double[] gradient = new double[numParameters]; for (int p = 0; p < numParameters; ++p) { final Cursor<T> err = Views.flatIterable(error).cursor(); for (final T t : Views.flatIterable(Views.hyperSlice(descent, n, p))) gradient[p] += t.getRealDouble() * err.next().getRealDouble(); } final double[] dp = new double[numParameters]; LinAlgHelpers.mult(Hinv, gradient, dp); // udpate transform currentTransform.preConcatenate(warpFunction.getAffine(dp)); // return norm of parameter update vector return LinAlgHelpers.length(dp); }