private void equalsTranVertical( WaveletDescription<?> desc, ImageSingleBand input, ImageSingleBand expected, ImageSingleBand found) { int w = expected.width; int h = expected.height; int lowerBorder = UtilWavelet.borderForwardLower(desc.getInverse().getInnerCoefficients()); int upperBorder = input.height - UtilWavelet.borderForwardUpper( desc.getInverse().getInnerCoefficients(), input.height); equalsTranVertical( expected.subimage(0, 0, w, h / 2), found.subimage(0, 0, w, h / 2), lowerBorder / 2, upperBorder / 2, "top"); equalsTranVertical( expected.subimage(0, h / 2, w, h), found.subimage(0, h / 2, w, h), lowerBorder / 2, upperBorder / 2, "bottom"); }
/** * Compares two wavelet transformations while ignoring the input image borders. Input borders * affect the borders of internal segments inside the transformation. */ private void equalsTranHorizontal( WaveletDescription<?> desc, ImageSingleBand input, ImageSingleBand expected, ImageSingleBand found) { int w = expected.width; int h = expected.height; int lowerBorder = UtilWavelet.borderForwardLower(desc.getInverse().getInnerCoefficients()); int upperBorder = input.width - UtilWavelet.borderForwardUpper(desc.getInverse().getInnerCoefficients(), input.width); equalsTranHorizontal( expected.subimage(0, 0, w / 2, h), found.subimage(0, 0, w / 2, h), lowerBorder / 2, upperBorder / 2, "left"); equalsTranHorizontal( expected.subimage(w / 2, 0, w, h), found.subimage(w / 2, 0, w, h), lowerBorder / 2, upperBorder / 2, "right"); }
/** See how well it processes an image which is not an GrayS32 */ @Test public void checkOtherType() { GrayS32 orig = new GrayS32(width, height); GImageMiscOps.fillUniform(orig, rand, 0, 20); GrayU8 orig8 = ConvertImage.convert(orig, (GrayU8) null); int N = 3; ImageDimension dimen = UtilWavelet.transformDimension(orig, N); GrayS32 found = new GrayS32(dimen.width, dimen.height); GrayS32 expected = new GrayS32(dimen.width, dimen.height); WaveletDescription<WlCoef_I32> desc = FactoryWaveletDaub.biorthogonal_I32(5, BorderType.REFLECT); GrayS32 storage = new GrayS32(dimen.width, dimen.height); WaveletTransformOps.transformN(desc, orig.clone(), expected, storage, N); WaveletTransformInt<GrayU8> alg = new WaveletTransformInt<>(desc, N, 0, 255, GrayU8.class); alg.transform(orig8, found); // see if the two techniques produced the same results BoofTesting.assertEquals(expected, found, 0); // see if it can convert it back GrayU8 reconstructed = new GrayU8(width, height); alg.invert(found, reconstructed); BoofTesting.assertEquals(orig8, reconstructed, 0); // make sure the input has not been modified BoofTesting.assertEquals(expected, found, 0); }
@Test public void compareToWaveletTransformOps() { GrayS32 orig = new GrayS32(width, height); GImageMiscOps.fillUniform(orig, rand, 0, 20); GrayS32 origCopy = orig.clone(); int N = 3; ImageDimension dimen = UtilWavelet.transformDimension(orig, N); GrayS32 found = new GrayS32(dimen.width, dimen.height); GrayS32 expected = new GrayS32(dimen.width, dimen.height); WaveletDescription<WlCoef_I32> desc = FactoryWaveletDaub.biorthogonal_I32(5, BorderType.REFLECT); GrayS32 storage = new GrayS32(dimen.width, dimen.height); WaveletTransformOps.transformN(desc, orig.clone(), expected, storage, N); WaveletTransformInt<GrayS32> alg = new WaveletTransformInt<>(desc, N, 0, 255, GrayS32.class); alg.transform(orig, found); // make sure the original input was not modified like it is in WaveletTransformOps BoofTesting.assertEquals(origCopy, orig, 0); // see if the two techniques produced the same results BoofTesting.assertEquals(expected, found, 0); // test inverse transform GrayS32 reconstructed = new GrayS32(width, height); alg.invert(found, reconstructed); BoofTesting.assertEquals(orig, reconstructed, 0); // make sure the input has not been modified BoofTesting.assertEquals(expected, found, 0); }
/** * Computes inverse coefficients * * @param border * @param forward Forward coefficients. * @param inverse Inverse used in the inner portion of the data stream. * @return */ private static WlBorderCoef<WlCoef_F32> computeBorderCoefficients( BorderIndex1D border, WlCoef_F32 forward, WlCoef_F32 inverse) { int N = Math.max(forward.getScalingLength(), forward.getWaveletLength()); N += N % 2; N *= 2; border.setLength(N); // Because the wavelet transform is a linear invertible system the inverse coefficients // can be found by creating a matrix and inverting the matrix. Boundary conditions are then // extracted from this inverted matrix. DenseMatrix64F A = new DenseMatrix64F(N, N); for (int i = 0; i < N; i += 2) { for (int j = 0; j < forward.scaling.length; j++) { int index = border.getIndex(j + i + forward.offsetScaling); A.add(i, index, forward.scaling[j]); } for (int j = 0; j < forward.wavelet.length; j++) { int index = border.getIndex(j + i + forward.offsetWavelet); A.add(i + 1, index, forward.wavelet[j]); } } LinearSolver<DenseMatrix64F> solver = LinearSolverFactory.linear(N); if (!solver.setA(A) || solver.quality() < 1e-5) { throw new IllegalArgumentException("Can't invert matrix"); } DenseMatrix64F A_inv = new DenseMatrix64F(N, N); solver.invert(A_inv); int numBorder = UtilWavelet.borderForwardLower(inverse) / 2; WlBorderCoefFixed<WlCoef_F32> ret = new WlBorderCoefFixed<>(numBorder, numBorder + 1); ret.setInnerCoef(inverse); // add the lower coefficients first for (int i = 0; i < ret.getLowerLength(); i++) { computeLowerCoef(inverse, A_inv, ret, i * 2); } // add upper coefficients for (int i = 0; i < ret.getUpperLength(); i++) { computeUpperCoef(inverse, N, A_inv, ret, i * 2); } return ret; }