All Downloads are FREE. Search and download functionalities are using the official Maven repository.

boofcv.alg.transform.wavelet.WaveletTransformOps Maven / Gradle / Ivy

/*
 * 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.InputSanityCheck;
import boofcv.alg.misc.PixelMath;
import boofcv.alg.transform.wavelet.impl.ImplWaveletTransformBorder;
import boofcv.alg.transform.wavelet.impl.ImplWaveletTransformInner;
import boofcv.alg.transform.wavelet.impl.ImplWaveletTransformNaive;
import boofcv.struct.image.GrayF32;
import boofcv.struct.image.GrayS32;
import boofcv.struct.wavelet.WaveletDescription;
import boofcv.struct.wavelet.WlCoef_F32;
import boofcv.struct.wavelet.WlCoef_I32;

/**
 * 

* Functional interface for applying general purpose wavelet and inverse wavelet transforms. *

* *

* A single level wavelet transform breaks the image up into four regions: *

* * *
ah
vd
* Each region has M/2,N/2 rows and columns. Region 'a' is the scaling image, 'h' and 'v' are * a combination of scaling and wavelet, and 'd' is a combination of horizontal and vertical wavelets. * When a multiple level transform is performed then the input to the next level is the 'a' from the previous * level. *

* *

* DO NOT MODIFY: This class was automatically generated by {@link boofcv.alg.transform.wavelet.GenerateWaveletTransformOps} *

* * @author Peter Abeles */ public class WaveletTransformOps { /** *

* Performs a single level wavelet transform. *

* * @param desc Description of the wavelet. * @param input Input image. Not modified. * @param output Where the wavelet transform is written to. Modified. * @param storage Optional storage image. Should be the same size as output image. If null then * an image is declared internally. */ public static void transform1(WaveletDescription desc , GrayF32 input , GrayF32 output , GrayF32 storage ) { UtilWavelet.checkShape(input,output); WlCoef_F32 coef = desc.getForward(); if( output.width < coef.scaling.length || output.width < coef.wavelet.length ) throw new IllegalArgumentException("Wavelet is too large for provided image."); if( output.height < coef.scaling.length || output.height < coef.wavelet.length ) throw new IllegalArgumentException("Wavelet is too large for provided image."); storage = InputSanityCheck.checkDeclare(output, storage); // the faster routines can only be run on images which are not too small int minSize = Math.max(coef.getScalingLength(),coef.getWaveletLength())*3; if( input.getWidth() <= minSize || input.getHeight() <= minSize ) { ImplWaveletTransformNaive.horizontal(desc.getBorder(),coef,input,storage); ImplWaveletTransformNaive.vertical(desc.getBorder(),coef,storage,output); } else { ImplWaveletTransformInner.horizontal(coef,input,storage); ImplWaveletTransformBorder.horizontal(desc.getBorder(),coef,input,storage); ImplWaveletTransformInner.vertical(coef,storage,output); ImplWaveletTransformBorder.vertical(desc.getBorder(),coef,storage,output); } } /** *

* Performs a level N wavelet transform using the fast wavelet transform (FWT). *

* *

To save memory the input image is used to store intermediate results and is modified.

* * @param desc Description of the wavelet. * @param input Input image and is used as internal workspace. Modified. * @param output Where the multilevel wavelet transform is written to. Modified. * @param storage Optional storage image. Should be the same size as output image. If null then * an image is declared internally. * @param numLevels Number of levels which should be computed in the transform. */ public static void transformN(WaveletDescription desc , GrayF32 input , GrayF32 output , GrayF32 storage , int numLevels ) { if( numLevels == 1 ) { transform1(desc,input,output, storage); return; } UtilWavelet.checkShape(desc.getForward(),input,output,numLevels); storage = InputSanityCheck.checkDeclare(output, storage); // modify the shape of a temporary image not the original storage = storage.subimage(0,0,output.width,output.height, null); storage.subImage = false; transform1(desc,input,output, storage); for( int i = 2; i <= numLevels; i++ ) { int width = output.width/2; int height = output.height/2; width += width%2; height += height%2; input = input.subimage(0,0,width,height, null); output = output.subimage(0,0,width,height, null); input.setTo(output); // transform the scaling image and save the results in the output image storage.reshape(width,height); transform1(desc,input,output,storage); } } /** *

* Performs a single level inverse wavelet transform. Do not pass in a whole image which has been * transformed by a multilevel transform. Just the relevant sub-image. *

* * @param desc Description of the inverse wavelet. * @param input Input wavelet transform. Not modified. * @param output Reconstruction of original image. Modified. * @param storage Optional storage image. Should be the same size as the input image. If null then * an image is declared internally. * @param minValue Minimum allowed pixel value * @param maxValue Maximum allowed pixel value */ public static void inverse1(WaveletDescription desc , GrayF32 input , GrayF32 output , GrayF32 storage , float minValue , float maxValue ) { UtilWavelet.checkShape(output,input); WlCoef_F32 coef = desc.getForward(); if( output.width < coef.scaling.length || output.width < coef.wavelet.length ) throw new IllegalArgumentException("Wavelet is too large for provided image."); if( output.height < coef.scaling.length || output.height < coef.wavelet.length ) throw new IllegalArgumentException("Wavelet is too large for provided image."); storage = InputSanityCheck.checkDeclare(input, storage); // the faster routines can only be run on images which are not too small int minSize = Math.max(coef.getScalingLength(),coef.getWaveletLength())*3; if( output.getWidth() <= minSize || output.getHeight() <= minSize ) { ImplWaveletTransformNaive.verticalInverse(desc.getBorder(),desc.getInverse(),input,storage); ImplWaveletTransformNaive.horizontalInverse(desc.getBorder(),desc.getInverse(),storage,output); } else { ImplWaveletTransformInner.verticalInverse(desc.getInverse().getInnerCoefficients(),input,storage); ImplWaveletTransformBorder.verticalInverse(desc.getBorder(),desc.getInverse(),input,storage); ImplWaveletTransformInner.horizontalInverse(desc.getInverse().getInnerCoefficients(),storage,output); ImplWaveletTransformBorder.horizontalInverse(desc.getBorder(),desc.getInverse(),storage,output); } if( minValue != -Float.MAX_VALUE && maxValue != Float.MAX_VALUE ) PixelMath.boundImage(output,minValue,maxValue); } /** *

Performs a level N inverse fast wavelet transform (FWT).

* *

To save memory the input image is used to store intermediate results and is modified.

* * @param desc Description of the inverse wavelet. * @param input Input wavelet transform and is used as internal workspace. Modified. * @param output Reconstruction of original image. Modified. * @param storage Optional storage image. Should be the same size as the input image. If null then * an image is declared internally. * @param numLevels Number of levels in the transform. * @param minValue Minimum allowed pixel value * @param maxValue Maximum allowed pixel value */ public static void inverseN(WaveletDescription desc , GrayF32 input , GrayF32 output , GrayF32 storage, int numLevels , float minValue , float maxValue) { if( numLevels == 1 ) { inverse1(desc,input,output, storage,minValue,maxValue); PixelMath.boundImage(output, minValue, maxValue); return; } UtilWavelet.checkShape(desc.getForward(),output,input,numLevels); storage = InputSanityCheck.checkDeclare(input, storage); // modify the shape of a temporary image not the original storage = storage.subimage(0,0,input.width,input.height, null); storage.subImage = false; int width,height; int scale = UtilWavelet.computeScale(numLevels); width = input.width/scale; height = input.height/scale; width += width%2; height += height%2; GrayF32 levelIn = input.subimage(0,0,width,height, null); GrayF32 levelOut = output.subimage(0,0,width,height, null); storage.reshape(width,height); inverse1(desc,levelIn,levelOut, storage,-Float.MAX_VALUE,Float.MAX_VALUE); for( int i = numLevels-1; i >= 1; i-- ) { // copy the decoded segment into the input levelIn.setTo(levelOut); if( i > 1 ) { scale /= 2; width = input.width/scale; height = input.height/scale; width += width%2; height += height%2; storage.reshape(width,height); levelIn = input.subimage(0,0,width,height, null); levelOut = output.subimage(0,0,width,height, null); } else { levelIn = input; levelOut = output; } storage.reshape(levelIn.width,levelIn.height); inverse1(desc,levelIn,levelOut, storage,-Float.MAX_VALUE,Float.MAX_VALUE); } if( minValue != -Float.MAX_VALUE && maxValue != Float.MAX_VALUE ) PixelMath.boundImage(output, minValue, maxValue); } /** *

* Performs a single level wavelet transform. *

* * @param desc Description of the wavelet. * @param input Input image. Not modified. * @param output Where the wavelet transform is written to. Modified. * @param storage Optional storage image. Should be the same size as output image. If null then * an image is declared internally. */ public static void transform1(WaveletDescription desc , GrayS32 input , GrayS32 output , GrayS32 storage ) { UtilWavelet.checkShape(input,output); WlCoef_I32 coef = desc.getForward(); if( output.width < coef.scaling.length || output.width < coef.wavelet.length ) throw new IllegalArgumentException("Wavelet is too large for provided image."); if( output.height < coef.scaling.length || output.height < coef.wavelet.length ) throw new IllegalArgumentException("Wavelet is too large for provided image."); storage = InputSanityCheck.checkDeclare(output, storage); // the faster routines can only be run on images which are not too small int minSize = Math.max(coef.getScalingLength(),coef.getWaveletLength())*3; if( input.getWidth() <= minSize || input.getHeight() <= minSize ) { ImplWaveletTransformNaive.horizontal(desc.getBorder(),coef,input,storage); ImplWaveletTransformNaive.vertical(desc.getBorder(),coef,storage,output); } else { ImplWaveletTransformInner.horizontal(coef,input,storage); ImplWaveletTransformBorder.horizontal(desc.getBorder(),coef,input,storage); ImplWaveletTransformInner.vertical(coef,storage,output); ImplWaveletTransformBorder.vertical(desc.getBorder(),coef,storage,output); } } /** *

* Performs a level N wavelet transform using the fast wavelet transform (FWT). *

* *

To save memory the input image is used to store intermediate results and is modified.

* * @param desc Description of the wavelet. * @param input Input image and is used as internal workspace. Modified. * @param output Where the multilevel wavelet transform is written to. Modified. * @param storage Optional storage image. Should be the same size as output image. If null then * an image is declared internally. * @param numLevels Number of levels which should be computed in the transform. */ public static void transformN(WaveletDescription desc , GrayS32 input , GrayS32 output , GrayS32 storage , int numLevels ) { if( numLevels == 1 ) { transform1(desc,input,output, storage); return; } UtilWavelet.checkShape(desc.getForward(),input,output,numLevels); storage = InputSanityCheck.checkDeclare(output, storage); // modify the shape of a temporary image not the original storage = storage.subimage(0,0,output.width,output.height, null); storage.subImage = false; transform1(desc,input,output, storage); for( int i = 2; i <= numLevels; i++ ) { int width = output.width/2; int height = output.height/2; width += width%2; height += height%2; input = input.subimage(0,0,width,height, null); output = output.subimage(0,0,width,height, null); input.setTo(output); // transform the scaling image and save the results in the output image storage.reshape(width,height); transform1(desc,input,output,storage); } } /** *

* Performs a single level inverse wavelet transform. Do not pass in a whole image which has been * transformed by a multilevel transform. Just the relevant sub-image. *

* * @param desc Description of the inverse wavelet. * @param input Input wavelet transform. Not modified. * @param output Reconstruction of original image. Modified. * @param storage Optional storage image. Should be the same size as the input image. If null then * an image is declared internally. * @param minValue Minimum allowed pixel value * @param maxValue Maximum allowed pixel value */ public static void inverse1(WaveletDescription desc , GrayS32 input , GrayS32 output , GrayS32 storage , int minValue , int maxValue ) { UtilWavelet.checkShape(output,input); WlCoef_I32 coef = desc.getForward(); if( output.width < coef.scaling.length || output.width < coef.wavelet.length ) throw new IllegalArgumentException("Wavelet is too large for provided image."); if( output.height < coef.scaling.length || output.height < coef.wavelet.length ) throw new IllegalArgumentException("Wavelet is too large for provided image."); storage = InputSanityCheck.checkDeclare(input, storage); // the faster routines can only be run on images which are not too small int minSize = Math.max(coef.getScalingLength(),coef.getWaveletLength())*3; if( output.getWidth() <= minSize || output.getHeight() <= minSize ) { ImplWaveletTransformNaive.verticalInverse(desc.getBorder(),desc.getInverse(),input,storage); ImplWaveletTransformNaive.horizontalInverse(desc.getBorder(),desc.getInverse(),storage,output); } else { ImplWaveletTransformInner.verticalInverse(desc.getInverse().getInnerCoefficients(),input,storage); ImplWaveletTransformBorder.verticalInverse(desc.getBorder(),desc.getInverse(),input,storage); ImplWaveletTransformInner.horizontalInverse(desc.getInverse().getInnerCoefficients(),storage,output); ImplWaveletTransformBorder.horizontalInverse(desc.getBorder(),desc.getInverse(),storage,output); } if( minValue != Integer.MIN_VALUE && maxValue != Integer.MAX_VALUE ) PixelMath.boundImage(output,minValue,maxValue); } /** *

Performs a level N inverse fast wavelet transform (FWT).

* *

To save memory the input image is used to store intermediate results and is modified.

* * @param desc Description of the inverse wavelet. * @param input Input wavelet transform and is used as internal workspace. Modified. * @param output Reconstruction of original image. Modified. * @param storage Optional storage image. Should be the same size as the input image. If null then * an image is declared internally. * @param numLevels Number of levels in the transform. * @param minValue Minimum allowed pixel value * @param maxValue Maximum allowed pixel value */ public static void inverseN(WaveletDescription desc , GrayS32 input , GrayS32 output , GrayS32 storage, int numLevels , int minValue , int maxValue) { if( numLevels == 1 ) { inverse1(desc,input,output, storage,minValue,maxValue); PixelMath.boundImage(output, minValue, maxValue); return; } UtilWavelet.checkShape(desc.getForward(),output,input,numLevels); storage = InputSanityCheck.checkDeclare(input, storage); // modify the shape of a temporary image not the original storage = storage.subimage(0,0,input.width,input.height, null); storage.subImage = false; int width,height; int scale = UtilWavelet.computeScale(numLevels); width = input.width/scale; height = input.height/scale; width += width%2; height += height%2; GrayS32 levelIn = input.subimage(0,0,width,height, null); GrayS32 levelOut = output.subimage(0,0,width,height, null); storage.reshape(width,height); inverse1(desc,levelIn,levelOut, storage,Integer.MIN_VALUE,Integer.MAX_VALUE); for( int i = numLevels-1; i >= 1; i-- ) { // copy the decoded segment into the input levelIn.setTo(levelOut); if( i > 1 ) { scale /= 2; width = input.width/scale; height = input.height/scale; width += width%2; height += height%2; storage.reshape(width,height); levelIn = input.subimage(0,0,width,height, null); levelOut = output.subimage(0,0,width,height, null); } else { levelIn = input; levelOut = output; } storage.reshape(levelIn.width,levelIn.height); inverse1(desc,levelIn,levelOut, storage,Integer.MIN_VALUE,Integer.MAX_VALUE); } if( minValue != Integer.MIN_VALUE && maxValue != Integer.MAX_VALUE ) PixelMath.boundImage(output, minValue, maxValue); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy