/* * 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; import boofcv.alg.misc.GImageMiscOps; import boofcv.core.image.GeneralizedImageOps; import boofcv.core.image.border.BorderType; import boofcv.factory.transform.wavelet.FactoryWaveletDaub; import boofcv.struct.image.GrayF32; import boofcv.struct.image.GrayS32; import boofcv.struct.image.ImageDimension; import boofcv.struct.image.ImageGray; import boofcv.struct.wavelet.WaveletDescription; import boofcv.testing.BoofTesting; import org.junit.Test; import java.util.Random; import static org.junit.Assert.fail; /** * @author Peter Abeles */ public class TestWaveletTransformOps { Random rand = new Random(234); int width = 250; int height = 300; Class<?> typeInput; Class<?> types[]={GrayF32.class,GrayS32.class}; /** * See if it is possible to overflow the image */ @Test public void checkOverflow1() { for( Class t : types ) { checkOverflow1(t); } } public <T extends ImageGray> void checkOverflow1(Class<T> typeInput ) { this.typeInput = typeInput; WaveletDescription<?> desc = createDesc(typeInput); int width = 20; int height = 22; T transform = GeneralizedImageOps.createSingleBand(typeInput, width + (width % 2), height + (height % 2)); T found = GeneralizedImageOps.createSingleBand(typeInput, width, height); GImageMiscOps.fillUniform(transform, rand, 100, 150); invokeTransform(desc, null, transform, found,100,150); checkBounds(found,100,150); } /** * See if images which are the smallest possible can be transformed. */ @Test public void smallImage1(){ for( Class t : types ) { testSmallImage1(t); } } public <T extends ImageGray> void testSmallImage1(Class<T> typeInput ) { this.typeInput = typeInput; WaveletDescription<?> desc = createDesc(typeInput); int length = Math.max(desc.getForward().getScalingLength(),desc.getForward().getWaveletLength()); for( int i = length; i < 20; i++ ) { T input = GeneralizedImageOps.createSingleBand(typeInput, i, i); T output = GeneralizedImageOps.createSingleBand(typeInput, input.width + (input.width % 2), input.height + (input.height % 2)); T found = GeneralizedImageOps.createSingleBand(typeInput, input.width, input.height); GImageMiscOps.fillUniform(input, rand, 0, 50); invokeTransform(desc, input, output, found,0,255); BoofTesting.assertEquals(input, found, 1e-4f); } } private WaveletDescription<?> createDesc(Class<?> typeInput) { boolean isFloat = GeneralizedImageOps.isFloatingPoint(typeInput); WaveletDescription<?> desc; if( isFloat ) desc = FactoryWaveletDaub.daubJ_F32(4); else desc = FactoryWaveletDaub.biorthogonal_I32(5, BorderType.WRAP); return desc; } @Test public void multipleLevel() { for( Class<?> t : types ) { testMultipleLevels(t); } } private void testMultipleLevels(Class typeInput) { this.typeInput = typeInput; WaveletDescription<?> desc = createDesc(typeInput); // try different sized images for( int adjust = 0; adjust < 5; adjust++ ) { int w = width+adjust; int h = height+adjust; ImageGray input = GeneralizedImageOps.createSingleBand(typeInput, w, h); ImageGray found = GeneralizedImageOps.createSingleBand(typeInput, w, h); GImageMiscOps.fillUniform(input, rand, 0, 50); for( int level = 1; level <= 5; level++ ) { ImageDimension dim = UtilWavelet.transformDimension(w,h,level); ImageGray output = GeneralizedImageOps.createSingleBand(typeInput, dim.width, dim.height); // System.out.println("adjust "+adjust+" level "+level+" scale "+ div); invokeTransformN(desc, (ImageGray)input.clone(), output, found, level, 0, 255); BoofTesting.assertEquals(input, found, 1e-4f); } } } /** * See if it is possible to overflow the image */ @Test public void checkOverflowN() { for( Class t : types ) { checkOverflowN(t); } } public <T extends ImageGray> void checkOverflowN(Class<T> typeInput ) { this.typeInput = typeInput; WaveletDescription<?> desc = createDesc(typeInput); int width = 20; int height = 22; int level = 3; ImageDimension dim = UtilWavelet.transformDimension(width,height,level); T transform = GeneralizedImageOps.createSingleBand(typeInput, dim.width,dim.height); T found = GeneralizedImageOps.createSingleBand(typeInput, width, height); GImageMiscOps.fillUniform(transform, rand, 100, 150); invokeTransformN(desc, null, transform, found, 3, 100, 150); checkBounds(found,100,150); } private void invokeTransform(WaveletDescription desc, ImageGray input, ImageGray output, ImageGray found, double minValue , double maxValue ) { if( input != null ) { if( input.getDataType().isInteger() ) { WaveletTransformOps.transform1(desc, (GrayS32) input, (GrayS32) output, null); } else { WaveletTransformOps.transform1(desc, (GrayF32) input, (GrayF32) output, null); } } if( output.getDataType().isInteger() ) { WaveletTransformOps.inverse1(desc,(GrayS32)output,(GrayS32)found,null, (int)minValue,(int)maxValue); } else { WaveletTransformOps.inverse1(desc,(GrayF32)output,(GrayF32)found,null, (float)minValue,(float)maxValue); } } private void invokeTransformN(WaveletDescription desc, ImageGray input, ImageGray output, ImageGray found, int numLevels , double minValue , double maxValue ) { if( input != null ) { if( input.getDataType().isInteger() ) { WaveletTransformOps.transformN(desc, (GrayS32) input, (GrayS32) output, null, numLevels); } else { WaveletTransformOps.transformN(desc, (GrayF32) input, (GrayF32) output, null, numLevels); } } if( output.getDataType().isInteger() ) { WaveletTransformOps.inverseN(desc, (GrayS32) output, (GrayS32) found, null, numLevels, (int) minValue, (int) maxValue); } else { WaveletTransformOps.inverseN(desc, (GrayF32) output, (GrayF32) found, null, numLevels, (float) minValue, (float) maxValue); } } private void checkBounds(ImageGray image , double low , double upper ) { for( int y = 0; y < image.height; y++ ) { for( int x = 0; x < image.width; x++ ) { double v = GeneralizedImageOps.get(image,x,y); if( v < low || v > upper ) fail("out of bounds"); } } } }