boofcv.alg.transform.wavelet.impl.ImplWaveletTransformNaive Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of boofcv-ip Show documentation
Show all versions of boofcv-ip Show documentation
BoofCV is an open source Java library for real-time computer vision and robotics applications.
/*
* Copyright (c) 2011-2019, 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.struct.border.BorderIndex1D;
import boofcv.struct.image.GrayF32;
import boofcv.struct.image.GrayI;
import boofcv.struct.wavelet.WlBorderCoef;
import boofcv.struct.wavelet.WlCoef_F32;
import boofcv.struct.wavelet.WlCoef_I32;
/**
*
* Unoptimized and simplistic implementation of a forward and inverse wavelet transform across one
* level. Primary used for validation testing.
*
*
*
* DO NOT MODIFY: This class was automatically generated by {@link GenerateImplWaveletTransformNaive}.
*
*
* @author Peter Abeles
*/
public class ImplWaveletTransformNaive {
/**
* Performs a single level wavelet transform along the horizontal axis.
*
* @param coefficients Description of wavelet coefficients.
* @param input Input image which is being transform. Not modified.
* @param output where the output is written to. Modified
*/
public static void horizontal(BorderIndex1D border , WlCoef_F32 coefficients ,
GrayF32 input , GrayF32 output ) {
UtilWavelet.checkShape(input,output);
final int offsetA = coefficients.offsetScaling;
final int offsetB = coefficients.offsetWavelet;
final float[] alpha = coefficients.scaling;
final float[] beta = coefficients.wavelet;
border.setLength(input.width+input.width%2);
final boolean isLarger = output.width > input.width;
for( int y = 0; y < input.height; y++ ) {
for( int x = 0; x < input.width; x += 2 ) {
float scale = 0;
float wavelet = 0;
for( int i = 0; i < alpha.length; i++ ) {
int xx = border.getIndex(x+i+offsetA);
if( isLarger && xx >= input.width )
continue;
scale += input.get(xx,y)*alpha[i];
}
for( int i = 0; i < beta.length; i++ ) {
int xx = border.getIndex(x+i+offsetB);
if( isLarger && xx >= input.width )
continue;
wavelet += input.get(xx,y)*beta[i];
}
int outX = x/2;
output.set(outX,y,scale);
output.set(output.width/2 + outX , y , wavelet );
}
}
}
/**
* Performs a single level wavelet transform along the vertical axis.
*
* @param coefficients Description of wavelet coefficients.
* @param input Input image which is being transform. Not modified.
* @param output where the output is written to. Modified
*/
public static void vertical(BorderIndex1D border , WlCoef_F32 coefficients ,
GrayF32 input , GrayF32 output ) {
UtilWavelet.checkShape(input,output);
final int offsetA = coefficients.offsetScaling;
final int offsetB = coefficients.offsetWavelet;
final float[] alpha = coefficients.scaling;
final float[] beta = coefficients.wavelet;
border.setLength(input.height+input.height%2);
boolean isLarger = output.height > input.height;
for( int x = 0; x < input.width; x++) {
for( int y = 0; y < input.height; y += 2 ) {
float scale = 0;
float wavelet = 0;
for( int i = 0; i < alpha.length; i++ ) {
int yy = border.getIndex(y+i+offsetA);
if( isLarger && yy >= input.height )
continue;
scale += input.get(x,yy)*alpha[i];
}
for( int i = 0; i < beta.length; i++ ) {
int yy = border.getIndex(y+i+offsetB);
if( isLarger && yy >= input.height )
continue;
wavelet += input.get(x,yy)*beta[i];
}
int outY = y/2;
output.set(x , outY,scale);
output.set(x , output.height/2 + outY , wavelet );
}
}
}
/**
* Performs a single level inverse wavelet transform along the horizontal axis.
*
* @param inverseCoef Description of wavelet coefficients.
* @param input Transformed image. Not modified.
* @param output Reconstruction of original image. Modified
*/
public static void horizontalInverse(BorderIndex1D border , WlBorderCoef inverseCoef , GrayF32 input , GrayF32 output ) {
UtilWavelet.checkShape(output,input);
float []trends = new float[ output.width ];
float []details = new float[ output.width ];
boolean isLarger = input.width >= output.width;
int paddedWidth = output.width + output.width%2;
final int lowerBorder = inverseCoef.getLowerLength()*2;
final int upperBorder = output.width - inverseCoef.getUpperLength()*2;
border.setLength(output.width+output.width%2);
WlCoef_F32 coefficients;
for( int y = 0; y < output.height; y++ ) {
for( int i = 0; i < details.length; i++ ) {
details[i] = 0;
trends[i] = 0;
}
for( int x = 0; x < output.width; x += 2 ) {
float a = input.get(x/2,y);
float d = input.get(input.width/2+x/2,y);
if( x < lowerBorder ) {
coefficients = inverseCoef.getBorderCoefficients(x);
} else if( x >= upperBorder ) {
coefficients = inverseCoef.getBorderCoefficients(x-paddedWidth);
} else {
coefficients = inverseCoef.getInnerCoefficients();
}
final int offsetA = coefficients.offsetScaling;
final int offsetB = coefficients.offsetWavelet;
final float[] alpha = coefficients.scaling;
final float[] beta = coefficients.wavelet;
// add the trend
for( int i = 0; i < alpha.length; i++ ) {
// if an odd image don't update the outer edge
int xx = border.getIndex(x+offsetA+i);
if( isLarger && xx >= output.width )
continue;
trends[xx] += a*alpha[i];
}
// add the detail signal
for( int i = 0; i < beta.length; i++ ) {
int xx = border.getIndex(x+offsetB+i);
if( isLarger && xx >= output.width )
continue;
details[xx] += d*beta[i];
}
}
for( int x = 0; x < output.width; x++ ) {
output.set(x,y, trends[x] + details[x]);
}
}
}
/**
* Performs a single level inverse wavelet transform along the vertical axis.
*
* @param inverseCoef Description of wavelet coefficients.
* @param input Transformed image. Not modified.
* @param output Reconstruction of original image. Modified
*/
public static void verticalInverse(BorderIndex1D border , WlBorderCoef inverseCoef , GrayF32 input , GrayF32 output ) {
UtilWavelet.checkShape(output,input);
float []trends = new float[ output.height ];
float []details = new float[ output.height ];
boolean isLarger = input.height > output.height;
int paddedHeight = output.height + output.height%2;
final int lowerBorder = inverseCoef.getLowerLength()*2;
final int upperBorder = output.height - inverseCoef.getUpperLength()*2;
border.setLength(output.height+output.height%2);
WlCoef_F32 coefficients;
for( int x = 0; x < output.width; x++) {
for( int i = 0; i < details.length; i++ ) {
details[i] = 0;
trends[i] = 0;
}
for( int y = 0; y < output.height; y += 2 ) {
float a = input.get(x,y/2);
float d = input.get(x,y/2+input.height/2);
if( y < lowerBorder ) {
coefficients = inverseCoef.getBorderCoefficients(y);
} else if( y >= upperBorder ) {
coefficients = inverseCoef.getBorderCoefficients(y-paddedHeight);
} else {
coefficients = inverseCoef.getInnerCoefficients();
}
final int offsetA = coefficients.offsetScaling;
final int offsetB = coefficients.offsetWavelet;
final float[] alpha = coefficients.scaling;
final float[] beta = coefficients.wavelet;
// add the 'average' signal
for( int i = 0; i < alpha.length; i++ ) {
// if an odd image don't update the outer edge
int yy = border.getIndex(y+offsetA+i);
if( isLarger && yy >= output.height )
continue;
trends[yy] += a*alpha[i];
}
// add the detail signal
for( int i = 0; i < beta.length; i++ ) {
int yy = border.getIndex(y+offsetB+i);
if( isLarger && yy >= output.height )
continue;
details[yy] += d*beta[i];
}
}
for( int y = 0; y < output.height; y++ ) {
output.set(x,y, trends[y] + details[y]);
}
}
}
/**
* Performs a single level wavelet transform along the horizontal axis.
*
* @param coefficients Description of wavelet coefficients.
* @param input Input image which is being transform. Not modified.
* @param output where the output is written to. Modified
*/
public static void horizontal(BorderIndex1D border , WlCoef_I32 coefficients ,
GrayI input , GrayI output ) {
UtilWavelet.checkShape(input,output);
final int offsetA = coefficients.offsetScaling;
final int offsetB = coefficients.offsetWavelet;
final int[] alpha = coefficients.scaling;
final int[] beta = coefficients.wavelet;
border.setLength(input.width+input.width%2);
final boolean isLarger = output.width > input.width;
for( int y = 0; y < input.height; y++ ) {
for( int x = 0; x < input.width; x += 2 ) {
int scale = 0;
int wavelet = 0;
for( int i = 0; i < alpha.length; i++ ) {
int xx = border.getIndex(x+i+offsetA);
if( isLarger && xx >= input.width )
continue;
scale += input.get(xx,y)*alpha[i];
}
for( int i = 0; i < beta.length; i++ ) {
int xx = border.getIndex(x+i+offsetB);
if( isLarger && xx >= input.width )
continue;
wavelet += input.get(xx,y)*beta[i];
}
int outX = x/2;
scale = 2*scale/coefficients.denominatorScaling;
wavelet = 2*wavelet/coefficients.denominatorWavelet;
output.set(outX,y,scale);
output.set(output.width/2 + outX , y , wavelet );
}
}
}
/**
* Performs a single level wavelet transform along the vertical axis.
*
* @param coefficients Description of wavelet coefficients.
* @param input Input image which is being transform. Not modified.
* @param output where the output is written to. Modified
*/
public static void vertical(BorderIndex1D border , WlCoef_I32 coefficients ,
GrayI input , GrayI output ) {
UtilWavelet.checkShape(input,output);
final int offsetA = coefficients.offsetScaling;
final int offsetB = coefficients.offsetWavelet;
final int[] alpha = coefficients.scaling;
final int[] beta = coefficients.wavelet;
border.setLength(input.height+input.height%2);
boolean isLarger = output.height > input.height;
for( int x = 0; x < input.width; x++) {
for( int y = 0; y < input.height; y += 2 ) {
int scale = 0;
int wavelet = 0;
for( int i = 0; i < alpha.length; i++ ) {
int yy = border.getIndex(y+i+offsetA);
if( isLarger && yy >= input.height )
continue;
scale += input.get(x,yy)*alpha[i];
}
for( int i = 0; i < beta.length; i++ ) {
int yy = border.getIndex(y+i+offsetB);
if( isLarger && yy >= input.height )
continue;
wavelet += input.get(x,yy)*beta[i];
}
int outY = y/2;
scale = 2*scale/coefficients.denominatorScaling;
wavelet = 2*wavelet/coefficients.denominatorWavelet;
output.set(x , outY,scale);
output.set(x , output.height/2 + outY , wavelet );
}
}
}
/**
* Performs a single level inverse wavelet transform along the horizontal axis.
*
* @param inverseCoef Description of wavelet coefficients.
* @param input Transformed image. Not modified.
* @param output Reconstruction of original image. Modified
*/
public static void horizontalInverse(BorderIndex1D border , WlBorderCoef inverseCoef , GrayI input , GrayI output ) {
UtilWavelet.checkShape(output,input);
int []trends = new int[ output.width ];
int []details = new int[ output.width ];
boolean isLarger = input.width >= output.width;
int paddedWidth = output.width + output.width%2;
final int lowerBorder = inverseCoef.getLowerLength()*2;
final int upperBorder = output.width - inverseCoef.getUpperLength()*2;
border.setLength(output.width+output.width%2);
WlCoef_I32 coefficients = inverseCoef.getInnerCoefficients();
final int e = coefficients.denominatorScaling*2;
final int f = coefficients.denominatorWavelet*2;
final int ef = e*f;
final int ef2 = ef/2;
for( int y = 0; y < output.height; y++ ) {
for( int i = 0; i < details.length; i++ ) {
details[i] = 0;
trends[i] = 0;
}
for( int x = 0; x < output.width; x += 2 ) {
int a = input.get(x/2,y);
int d = input.get(input.width/2+x/2,y);
if( x < lowerBorder ) {
coefficients = inverseCoef.getBorderCoefficients(x);
} else if( x >= upperBorder ) {
coefficients = inverseCoef.getBorderCoefficients(x-paddedWidth);
} else {
coefficients = inverseCoef.getInnerCoefficients();
}
final int offsetA = coefficients.offsetScaling;
final int offsetB = coefficients.offsetWavelet;
final int[] alpha = coefficients.scaling;
final int[] beta = coefficients.wavelet;
// add the trend
for( int i = 0; i < alpha.length; i++ ) {
// if an odd image don't update the outer edge
int xx = border.getIndex(x+offsetA+i);
if( isLarger && xx >= output.width )
continue;
trends[xx] += a*alpha[i];
}
// add the detail signal
for( int i = 0; i < beta.length; i++ ) {
int xx = border.getIndex(x+offsetB+i);
if( isLarger && xx >= output.width )
continue;
details[xx] += d*beta[i];
}
}
for( int x = 0; x < output.width; x++ ) {
output.set(x,y, UtilWavelet.round(trends[x]*f + details[x]*e ,ef2,ef));
}
}
}
/**
* Performs a single level inverse wavelet transform along the vertical axis.
*
* @param inverseCoef Description of wavelet coefficients.
* @param input Transformed image. Not modified.
* @param output Reconstruction of original image. Modified
*/
public static void verticalInverse(BorderIndex1D border , WlBorderCoef inverseCoef , GrayI input , GrayI output ) {
UtilWavelet.checkShape(output,input);
int []trends = new int[ output.height ];
int []details = new int[ output.height ];
boolean isLarger = input.height > output.height;
int paddedHeight = output.height + output.height%2;
final int lowerBorder = inverseCoef.getLowerLength()*2;
final int upperBorder = output.height - inverseCoef.getUpperLength()*2;
border.setLength(output.height+output.height%2);
WlCoef_I32 coefficients = inverseCoef.getInnerCoefficients();
final int e = coefficients.denominatorScaling*2;
final int f = coefficients.denominatorWavelet*2;
final int ef = e*f;
final int ef2 = ef/2;
for( int x = 0; x < output.width; x++) {
for( int i = 0; i < details.length; i++ ) {
details[i] = 0;
trends[i] = 0;
}
for( int y = 0; y < output.height; y += 2 ) {
int a = input.get(x,y/2);
int d = input.get(x,y/2+input.height/2);
if( y < lowerBorder ) {
coefficients = inverseCoef.getBorderCoefficients(y);
} else if( y >= upperBorder ) {
coefficients = inverseCoef.getBorderCoefficients(y-paddedHeight);
} else {
coefficients = inverseCoef.getInnerCoefficients();
}
final int offsetA = coefficients.offsetScaling;
final int offsetB = coefficients.offsetWavelet;
final int[] alpha = coefficients.scaling;
final int[] beta = coefficients.wavelet;
// add the 'average' signal
for( int i = 0; i < alpha.length; i++ ) {
// if an odd image don't update the outer edge
int yy = border.getIndex(y+offsetA+i);
if( isLarger && yy >= output.height )
continue;
trends[yy] += a*alpha[i];
}
// add the detail signal
for( int i = 0; i < beta.length; i++ ) {
int yy = border.getIndex(y+offsetB+i);
if( isLarger && yy >= output.height )
continue;
details[yy] += d*beta[i];
}
}
for( int y = 0; y < output.height; y++ ) {
output.set(x,y, UtilWavelet.round(trends[y]*f + details[y]*e,ef2,ef));
}
}
}
}