use of boofcv.struct.wavelet.WlCoef_F32 in project BoofCV by lessthanoptimal.
the class FactoryImageDenoise method createDefaultShrinkTransform.
/**
* Default wavelet transform used for denoising images.
*/
private static WaveletTransform createDefaultShrinkTransform(ImageDataType imageType, int numLevels, double minPixelValue, double maxPixelValue) {
WaveletTransform descTran;
if (!imageType.isInteger()) {
WaveletDescription<WlCoef_F32> waveletDesc_F32 = FactoryWaveletDaub.daubJ_F32(4);
descTran = FactoryWaveletTransform.create_F32(waveletDesc_F32, numLevels, (float) minPixelValue, (float) maxPixelValue);
} else {
WaveletDescription<WlCoef_I32> waveletDesc_I32 = FactoryWaveletDaub.biorthogonal_I32(5, BorderType.REFLECT);
descTran = FactoryWaveletTransform.create_I(waveletDesc_I32, numLevels, (int) minPixelValue, (int) maxPixelValue, ImageType.getImageClass(ImageType.Family.GRAY, imageType));
}
return descTran;
}
use of boofcv.struct.wavelet.WlCoef_F32 in project BoofCV by lessthanoptimal.
the class ImplWaveletTransformBorder method verticalInverse.
public static void verticalInverse(BorderIndex1D border, WlBorderCoef<WlCoef_F32> desc, GrayF32 input, GrayF32 output) {
float[] trends = new float[input.height];
float[] details = new float[input.height];
final int width = output.width;
final int paddedHeight = output.height + output.height % 2;
WlCoef inner = desc.getInnerCoefficients();
// need to convolve coefficients that influence the ones being updated
int lowerExtra = -Math.min(inner.offsetScaling, inner.offsetWavelet);
int upperExtra = Math.max(inner.getScalingLength() + inner.offsetScaling, inner.getWaveletLength() + inner.offsetWavelet);
lowerExtra += lowerExtra % 2;
upperExtra += upperExtra % 2;
int lowerBorder = (UtilWavelet.borderInverseLower(desc, border) + lowerExtra) / 2;
int upperBorder = (UtilWavelet.borderInverseUpper(desc, border, output.height) + upperExtra) / 2;
boolean isLarger = input.height >= output.height;
// where updated wavelet values are stored
int lowerCompute = lowerBorder * 2 - lowerExtra;
int upperCompute = upperBorder * 2 - upperExtra;
int[] indexes = new int[lowerBorder + upperBorder];
for (int i = 0; i < lowerBorder; i++) indexes[i] = i * 2;
for (int i = lowerBorder; i < indexes.length; i++) indexes[i] = paddedHeight - (indexes.length - i) * 2;
border.setLength(output.height + output.height % 2);
WlCoef_F32 coefficients;
for (int x = 0; x < width; x++) {
// initialize details and trends arrays
for (int i = 0; i < indexes.length; i++) {
int y = indexes[i];
details[y] = 0;
trends[y] = 0;
y++;
details[y] = 0;
trends[y] = 0;
}
for (int i = 0; i < indexes.length; i++) {
int y = indexes[i];
float a = input.get(x, y / 2);
float d = input.get(x, input.height / 2 + y / 2);
if (y < lowerBorder) {
coefficients = desc.getBorderCoefficients(y);
} else if (y >= upperBorder) {
coefficients = desc.getBorderCoefficients(y - paddedHeight);
} else {
coefficients = desc.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 j = 0; j < alpha.length; j++) {
// if an odd image don't update the outer edge
int yy = border.getIndex(y + offsetA + j);
if (isLarger && yy >= output.height)
continue;
trends[yy] += a * alpha[j];
}
// add the detail signal
for (int j = 0; j < beta.length; j++) {
int yy = border.getIndex(y + offsetB + j);
if (isLarger && yy >= output.height)
continue;
details[yy] += d * beta[j];
}
}
int indexDst = output.startIndex + x;
for (int y = 0; y < lowerCompute; y++) {
output.data[indexDst + y * output.stride] = (trends[y] + details[y]);
}
for (int y = paddedHeight - upperCompute; y < output.height; y++) {
output.data[indexDst + y * output.stride] = (trends[y] + details[y]);
}
}
}
use of boofcv.struct.wavelet.WlCoef_F32 in project BoofCV by lessthanoptimal.
the class ImplWaveletTransformNaive method horizontalInverse.
/**
* 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<WlCoef_F32> 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]);
}
}
}
use of boofcv.struct.wavelet.WlCoef_F32 in project BoofCV by lessthanoptimal.
the class FactoryWaveletCoiflet method generate_F32.
/**
* Creates a description of a Coiflet of order I wavelet.
* @param I order of the wavelet.
* @return Wavelet description.
*/
public static WaveletDescription<WlCoef_F32> generate_F32(int I) {
if (I != 6) {
throw new IllegalArgumentException("Only 6 is currently supported");
}
WlCoef_F32 coef = new WlCoef_F32();
coef.offsetScaling = -2;
coef.offsetWavelet = -2;
coef.scaling = new float[6];
coef.wavelet = new float[6];
double sqrt7 = Math.sqrt(7);
double div = 16.0 * Math.sqrt(2);
coef.scaling[0] = (float) ((1.0 - sqrt7) / div);
coef.scaling[1] = (float) ((5.0 + sqrt7) / div);
coef.scaling[2] = (float) ((14.0 + 2.0 * sqrt7) / div);
coef.scaling[3] = (float) ((14.0 - 2.0 * sqrt7) / div);
coef.scaling[4] = (float) ((1.0 - sqrt7) / div);
coef.scaling[5] = (float) ((-3.0 + sqrt7) / div);
coef.wavelet[0] = coef.scaling[5];
coef.wavelet[1] = -coef.scaling[4];
coef.wavelet[2] = coef.scaling[3];
coef.wavelet[3] = -coef.scaling[2];
coef.wavelet[4] = coef.scaling[1];
coef.wavelet[5] = -coef.scaling[0];
WlBorderCoefStandard<WlCoef_F32> inverse = new WlBorderCoefStandard<>(coef);
return new WaveletDescription<>(new BorderIndex1D_Wrap(), coef, inverse);
}
use of boofcv.struct.wavelet.WlCoef_F32 in project BoofCV by lessthanoptimal.
the class CommonFactoryWavelet method checkBiorthogonal_F32.
/**
* Computes the dot product of two wavelets separated by different offsets. If
* the offset is zero and they have an orthogonal/biorothogonal relationship then
* the dot product should be one. Otherwise it will be zero.
*/
public static void checkBiorthogonal_F32(WaveletDescription<WlCoef_F32> desc) {
WlCoef_F32 forward = desc.getForward();
BorderIndex1D border = desc.getBorder();
int N = Math.max(forward.getScalingLength(), forward.getWaveletLength());
N += N % 2;
N *= 2;
border.setLength(N);
DMatrixRMaj A = new DMatrixRMaj(N, N);
DMatrixRMaj B = new DMatrixRMaj(N, N);
// using the provided wrapping rule to construct a matrix with the coefficients
for (int i = 0; i < N; i += 2) {
for (int j = 0; j < forward.scaling.length; j++) {
int index = border.getIndex(i + j + forward.offsetScaling);
A.add(i, index, forward.scaling[j]);
}
for (int j = 0; j < forward.wavelet.length; j++) {
int index = border.getIndex(i + j + forward.offsetWavelet);
A.add(i + 1, index, forward.wavelet[j]);
}
}
// the inverse coefficients should create a matrix that is the inverse of the forward coefficients
final int lowerBorder = desc.getInverse().getLowerLength() * 2;
final int upperBorder = N - desc.getInverse().getUpperLength() * 2;
for (int i = 0; i < N; i += 2) {
WlCoef_F32 inverse;
if (i < lowerBorder) {
inverse = desc.getInverse().getBorderCoefficients(i);
} else if (i >= upperBorder) {
inverse = desc.getInverse().getBorderCoefficients(i - N);
} else {
inverse = desc.getInverse().getInnerCoefficients();
}
for (int j = 0; j < inverse.scaling.length; j++) {
int index = border.getIndex(i + j + inverse.offsetScaling);
B.add(index, i, inverse.scaling[j]);
}
for (int j = 0; j < inverse.wavelet.length; j++) {
int index = border.getIndex(i + j + inverse.offsetWavelet);
B.add(index, i + 1, inverse.wavelet[j]);
}
}
DMatrixRMaj C = new DMatrixRMaj(N, N);
CommonOps_DDRM.mult(A, B, C);
// A.print();
// B.print();
// C.print();
assertTrue(MatrixFeatures_DDRM.isIdentity(C, 1e-4));
}
Aggregations