/* * 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.fft; import boofcv.struct.image.GrayF32; /** * Direct implementation of a Fourier transform. Horribly inefficient. * * @author Peter Abeles */ public class FourierTransformNaive_F32 { public static float PI2 = (float)(2.0*Math.PI); public static void forward( float inputR[] , float outputR[] , float outputI[] , int start , int length ) { for( int k = 0; k < length; k++ ) { float real = 0; float img = 0; for( int l = 0; l < length; l++ ) { float theta = -PI2*l*k/(float)length; real += inputR[start+l]*Math.cos(theta); img += inputR[start+l]*Math.sin(theta); } outputR[start+k] = real/length; outputI[start+k] = img/length; } } public static void inverse( float inputR[] , float inputI[] , float outputR[] , int start , int length ) { for( int k = 0; k < length; k++ ) { float real = 0; for( int l = 0; l < length; l++ ) { float theta = PI2*l*k/(float)length; float ra = (float)Math.cos(theta); float ia = (float)Math.sin(theta); float rb = inputR[start+l]; float ib = inputI[start+l]; real += ra*rb - ia*ib; // assume imaginary component is zero } outputR[start+k] = real; } } public static void transform( boolean forward , float inputR[] , float inputI[], float outputR[] , float outputI[] , int start , int length ) { float coef = PI2/(float)length; if( forward ) coef = -coef; for( int k = 0; k < length; k++ ) { float real = 0; float img = 0; for( int l = 0; l < length; l++ ) { float theta = coef*l*k; float ra = (float)Math.cos(theta); float ia = (float)Math.sin(theta); float rb = inputR[start+l]; float ib = inputI[start+l]; real += ra*rb - ia*ib; img += ia*rb + ra*ib; } if( forward ) { outputR[start+k] = real/length; outputI[start+k] = img/length; } else { outputR[start+k] = real; outputI[start+k] = img; } } } public static void forward(GrayF32 inputR , GrayF32 outputR , GrayF32 outputI ) { GrayF32 tempR = new GrayF32(inputR.width,inputR.height); GrayF32 tempI = new GrayF32(outputI.width,outputI.height); for( int y = 0; y < inputR.height; y++ ) { int index = inputR.startIndex + inputR.stride*y; forward( inputR.data , tempR.data , tempI.data , index , inputR.width); } float columnR0[] = new float[ inputR.height ]; float columnI0[] = new float[ inputR.height ]; float columnR1[] = new float[ inputR.height ]; float columnI1[] = new float[ inputR.height ]; for( int x = 0; x < inputR.width; x++ ) { // copy the column for( int y = 0; y < inputR.height; y++ ) { columnR0[y] = tempR.unsafe_get(x,y); columnI0[y] = tempI.unsafe_get(x,y); } transform(true,columnR0,columnI0,columnR1,columnI1,0,inputR.height); // copy the results back for( int y = 0; y < inputR.height; y++ ) { outputR.unsafe_set(x,y,columnR1[y]); outputI.unsafe_set(x,y,columnI1[y]); } } } public static void inverse(GrayF32 inputR , GrayF32 inputI, GrayF32 outputR ) { GrayF32 tempR = new GrayF32(inputR.width,inputR.height); GrayF32 tempI = new GrayF32(inputI.width,inputI.height); for( int y = 0; y < inputR.height; y++ ) { int index = inputR.startIndex + inputR.stride*y; transform(false,inputR.data , inputI.data, tempR.data , tempI.data,index,inputR.width); } float columnR0[] = new float[ inputR.height ]; float columnI0[] = new float[ inputR.height ]; float columnR1[] = new float[ inputR.height ]; for( int x = 0; x < inputR.width; x++ ) { // copy the column for( int y = 0; y < inputR.height; y++ ) { columnR0[y] = tempR.unsafe_get(x,y); columnI0[y] = tempI.unsafe_get(x,y); } inverse(columnR0,columnI0,columnR1,0,inputR.height); // copy the results back for( int y = 0; y < inputR.height; y++ ) { outputR.unsafe_set(x,y,columnR1[y]); } } } }