/* * Copyright (c) 2011-2016, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package boofcv.alg.transform.wavelet.impl; import boofcv.alg.transform.wavelet.UtilWavelet; import boofcv.core.image.FactoryGImageGray; import boofcv.core.image.GImageGray; import boofcv.struct.image.ImageGray; import boofcv.struct.wavelet.WaveletDescription; import boofcv.struct.wavelet.WlCoef; import boofcv.testing.BoofTesting; import org.junit.Test; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** * @author Peter Abeles */ public class TestImplWaveletTransformInner extends CompareToNaiveWavelet { public TestImplWaveletTransformInner() { super(2,ImplWaveletTransformInner.class); } @Test public void checkAllHorizontal() { checkAll("horizontal","checkHorizontal"); } @Test public void checkAllVertical() { checkAll("vertical","checkVertical"); } @Test public void checkAllHorizontalInverse() { checkAll("horizontalInverse","checkHorizontalInverse"); } @Test public void checkAllVerticalInverse() { checkAll("verticalInverse","checkVerticalInverse"); } public void checkHorizontal( Method m ) { PermuteWaveletCompare test = new InnerCompare() { @Override public void compareResults(WaveletDescription<?> desc, ImageGray input, ImageGray expected, ImageGray found ) { equalsTranHorizontal(desc,input,expected,found ); } }; test.runTests(false); } public void checkVertical( Method m ) { PermuteWaveletCompare test = new InnerCompare() { @Override public void compareResults(WaveletDescription<?> desc, ImageGray input, ImageGray expected, ImageGray found ) { equalsTranVertical(desc,input,expected,found ); } }; test.runTests(false); } public void checkHorizontalInverse( Method m ) { PermuteWaveletCompare test = new InnerCompare() { @Override public void compareResults(WaveletDescription<?> desc, ImageGray input, ImageGray expected, ImageGray found ) { // BoofTesting.printDiff(expected,found); int lowerBorder = UtilWavelet.borderInverseLower(desc.getInverse(),desc.getBorder()); int upperBorder = UtilWavelet.borderInverseUpper(desc.getInverse(),desc.getBorder(),found.getWidth()); int w = expected.getWidth(); int h = expected.getHeight(); // System.out.print("lb "+lowerBorder+" ub "+upperBorder); // only compare the relevant portion of the images expected = expected.subimage(lowerBorder,0,w+w%2-upperBorder,h, null); found = found.subimage(lowerBorder,0,w+w%2-upperBorder,h, null); BoofTesting.assertEquals(expected, found, 1e-4f); } }; test.runTests(true); } public void checkVerticalInverse( Method m ) { PermuteWaveletCompare test = new InnerCompare() { @Override public void compareResults(WaveletDescription<?> desc, ImageGray input, ImageGray expected, ImageGray found ) { int lowerBorder = UtilWavelet.borderInverseLower(desc.getInverse(),desc.getBorder()); int upperBorder = UtilWavelet.borderInverseUpper(desc.getInverse(),desc.getBorder(),found.getHeight()); int w = expected.getWidth(); int h = expected.getWidth(); // only compare the relevant portion of the images expected = expected.subimage(0,lowerBorder,w,h+h%2-upperBorder, null); found = found.subimage(0,lowerBorder,w,h+h%2-upperBorder, null); BoofTesting.assertEquals(expected, found, 1e-4f); } }; test.runTests(true); } /** * 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, ImageGray input , ImageGray expected , ImageGray 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, null),found.subimage(0,0,w/2,h, null),lowerBorder/2,upperBorder/2,"left"); equalsTranHorizontal(expected.subimage(w/2,0,w,h, null),found.subimage(w/2,0,w,h, null),lowerBorder/2,upperBorder/2,"right"); } /** * Compares two wavelet transformations while ignoring the input image borders. Input borders * affect the borders of internal segments inside the transformation. */ private void equalsTranHorizontal(ImageGray expected , ImageGray found , int begin , int end , String quad ) { GImageGray e = FactoryGImageGray.wrap(expected); GImageGray f = FactoryGImageGray.wrap(found); for( int y = 0; y < expected.height; y++ ) { for( int x = 0; x < expected.width; x++ ) { // see if the inner image is identical to the naive implementation // the border should be unmodified, zeros if( x >= begin && x < end ) assertEquals(quad+" ( "+x+" , "+y+" )",e.get(x,y).floatValue() , f.get(x,y).floatValue() , 1e-4f); else assertTrue(quad+" ( "+x+" , "+y+" ) 0 != "+f.get(x,y),0 == f.get(x,y).floatValue()); } } } private void equalsTranVertical(WaveletDescription<?> desc, ImageGray input , ImageGray expected , ImageGray 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, null),found.subimage(0,0,w,h/2, null),lowerBorder/2,upperBorder/2,"top"); equalsTranVertical(expected.subimage(0,h/2,w,h, null),found.subimage(0,h/2,w,h, null),lowerBorder/2,upperBorder/2,"bottom"); } private void equalsTranVertical(ImageGray expected , ImageGray found , int begin , int end , String quad ) { GImageGray e = FactoryGImageGray.wrap(expected); GImageGray f = FactoryGImageGray.wrap(found); for( int y = 0; y < expected.height; y++ ) { // see if the inner image is identical to the naive implementation // the border should be unmodified, zeros if( y >= begin && y < end ) { for( int x = 0; x < expected.width; x++ ) { assertEquals(quad+" ( "+x+" , "+y+" )",e.get(x,y).floatValue() , f.get(x,y).floatValue() , 1e-4f); } } else { for( int x = 0; x < expected.width; x++ ) { assertTrue(quad+" ( "+x+" , "+y+" ) 0 != "+f.get(x,y),0 == f.get(x,y).floatValue()); } } } } private abstract class InnerCompare extends BaseCompare { @Override public void applyTransform(WaveletDescription<?> desc, ImageGray input, ImageGray output) { applyInnerMethod(functionName,desc, input, output); } } public static void applyInnerMethod(String functionName , WaveletDescription<?> desc, ImageGray input, ImageGray output ) { Method m; Object args[]; if( functionName.contains("Inverse")) { WlCoef coef = desc.getInverse().getInnerCoefficients(); m = BoofTesting.findMethod(ImplWaveletTransformInner.class,functionName,coef.getClass(),input.getClass(),output.getClass()); args = new Object[]{coef,input,output}; } else { WlCoef coef = desc.getForward(); m = BoofTesting.findMethod(ImplWaveletTransformInner.class,functionName,coef.getClass(),input.getClass(),output.getClass()); args = new Object[]{coef,input,output}; } try { m.invoke(null,args); } catch (InvocationTargetException | IllegalAccessException e) { throw new RuntimeException(e); } } }