Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 图像处理与快速傅里叶变换_Android_Image Processing_Fft - Fatal编程技术网

Android 图像处理与快速傅里叶变换

Android 图像处理与快速傅里叶变换,android,image-processing,fft,Android,Image Processing,Fft,我正在开发一个实时图像处理的应用程序,以获得每帧之间的y和时间。它们存储在2个双数组中,为了进一步实现,我需要对这些值运行快速傅立叶变换 我在其他问题中见过一些fft算法,例如 我也读过他们建议使用的主题 然而,由于我对FFT的了解非常有限,我不知道如何在代码中实现它 我的主要活动是 public class MainActivity extends AppCompatActivity implements CameraView.PreviewReadyCallback { private

我正在开发一个实时图像处理的应用程序,以获得每帧之间的y和时间。它们存储在2个双数组中,为了进一步实现,我需要对这些值运行快速傅立叶变换

我在其他问题中见过一些fft算法,例如

  • 我也读过他们建议使用的主题

    然而,由于我对FFT的了解非常有限,我不知道如何在代码中实现它

    我的主要活动是

    public class MainActivity extends AppCompatActivity implements CameraView.PreviewReadyCallback {
    private static Camera camera = null;
    private CameraView image = null;
    Button fftButton;
    
    private LineChart bp_graph;
    private int img_Y_Avg, img_U_Avg, img_V_Avg;
    private long end = 0, begin = 0;
    Handler handler;
    private int readingRemaining = 1200;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    
        bp_graph = (LineChart)findViewById(R.id.graph);
        fftButton = (Button)findViewById(R.id.runFFT);
    
        graph_features();
    
        //open camera
        try {
            camera = Camera.open();
    
            handler = new Handler();
            final Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    camera.stopPreview();
                    camera.release();
                    fftButton.setVisibility(View.VISIBLE);
                }
            };
            handler.postDelayed(runnable, 30000);
    
        } catch (Exception e) {
            Log.d("ERROR", "Failed to get camera: " + e.getMessage());
        }
    
        if (camera != null) {
            image = new CameraView(this, camera);
            FrameLayout camera_view = (FrameLayout) findViewById(R.id.camera_view);
            camera_view.addView(image);
            image.setOnPreviewReady(this);
        }
    }
    
    
    @Override
    protected void onResume(){
        super.onResume();
    }
    
    @Override
    protected void onPause() {
        super.onPause();
    }
    
    @Override
    public void onPreviewFrame(long startTime, int ySum, int uSum, int vSum, long endTime) {
        begin = startTime;
        img_Y_Avg = ySum;
        img_U_Avg = uSum;
        img_V_Avg = vSum;
        end = endTime;
    
       showResults(begin, img_Y_Avg, img_U_Avg, img_V_Avg, end);
    }
    
    private void showResults(long startTime, int ySum, int uSum, int vSum, long endTime){
    
        //set value of Y on the text view
        TextView valueOfY = (TextView)findViewById(R.id.valueY);
        //valueY = img_Y_Avg;
        valueOfY.setText(String.valueOf(img_Y_Avg));
    
        //start time in milliseconds
        long StartDurationInMs = TimeUnit.MILLISECONDS.convert(begin, TimeUnit.MILLISECONDS);
        ArrayList<Long> startOfTime = new ArrayList<>();
        startOfTime.add(StartDurationInMs);
    
        //store value to array list
        ArrayList<Integer> yAverage = new ArrayList<>();
        yAverage.add(img_Y_Avg);
    
        ArrayList<Long> getValues = new ArrayList<>();
    
        for(int i = 0; i < yAverage.size(); i++) {
            getValues.add(startOfTime.get(i));
            getValues.add((long)(yAverage.get(i)));
        }
    
        storeCsv(yAverage, getValues);
        Log.d("MyEntryData", String.valueOf(getValues));
    
    }
    
    /**
     * method to store raw time and y-sum data into CSV file**/
    public void storeCsv(ArrayList<Integer>yAverage, ArrayList<Long>getValues){
    
        String filename = "temporary.csv";
    
        //File directoryDownload = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
        String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/bpReader";
        //File logDir = new File (directoryDownload, "bpReader"); //Creates a new folder in DOWNLOAD directory
        File logDir = new File(path);
        logDir.mkdirs();
        File file = new File(logDir, filename);
    
    
        FileOutputStream outputStream = null;
           try {
               file.createNewFile();
               outputStream = new FileOutputStream(file, true);
               //outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
               for (int i = 0; i < yAverage.size(); i += 2) {
                   outputStream.write((getValues.get(i) + ",").getBytes());
                   outputStream.write((getValues.get(i + 1) + "\n").getBytes());
                   //outputStream.write((getValues.get(i + 2) + ",").getBytes());
                   //outputStream.write((getValues.get(i + 3) + "\n").getBytes());
               }
               outputStream.flush();
               outputStream.close();
           } catch (Exception e) {
               e.printStackTrace();
           }
    
    }
    
    //Method for button which appears after the reading is done and the data is saved into csv file
    public void readFile(View view){
        readCsv();
    }
    //Method to read the data from the csv and get the time and y-sum value
    public void readCsv(){
        String getPath = Environment.getExternalStorageDirectory() + "/bpReader";
        String csvFile = "temporary.csv";
        String path = getPath+ "/" + csvFile;
    
    
        int length = 500;
        double[] xCoords = new double[length];
        double[] yCoords = new double[length];
        double[] newXcord = new double[length];
    
        CSVReader reader;
    
        try {
            File myFile = new File (path);
            reader = new CSVReader(new FileReader(myFile));
            String[] line;
            int i;
            for (i = 0; i < xCoords.length; i ++){
                if ((line = reader.readNext()) != null){
                    xCoords[i] = Double.parseDouble(line[0]);
                    yCoords[i] = Double.parseDouble(line[1]);
                }
            }
    
            for (i = 0; i < xCoords.length ; i++){
                if (xCoords[i]!=0) {
                    newXcord[i] = xCoords[i] - xCoords[0];
    
                    Log.d("read:: ", "Time: " + String.valueOf(newXcord[i]) + " Y-Sum " + String.valueOf(yCoords[i]));
                }
            }
            myFile.delete();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    }
    }
    
    我的FFT类是从其他堆栈溢出问题中的一些建议中得到的

    public class FFT {
    
    /**
     * The Fast Fourier Transform (generic version, with NO optimizations).
     *
     * @param inputReal
     *            an array of length n, the real part
     * @param inputImag
     *            an array of length n, the imaginary part
     * @param DIRECT
     *            TRUE = direct transform, FALSE = inverse transform
     * @return a new array of length 2n
     */
    public static double[] fft(final double[] inputReal, double[] inputImag,
                               boolean DIRECT) {
        // - n is the dimension of the problem
        // - nu is its logarithm in base e
        int n = inputReal.length;
    
        // If n is a power of 2, then ld is an integer (_without_ decimals)
        double ld = Math.log(n) / Math.log(2.0);
    
        // Here I check if n is a power of 2. If exist decimals in ld, I quit
        // from the function returning null.
        if (((int) ld) - ld != 0) {
            System.out.println("The number of elements is not a power of 2.");
            return null;
        }
    
        // Declaration and initialization of the variables
        // ld should be an integer, actually, so I don't lose any information in
        // the cast
        int nu = (int) ld;
        int n2 = n / 2;
        int nu1 = nu - 1;
        double[] xReal = new double[n];
        double[] xImag = new double[n];
        double tReal, tImag, p, arg, c, s;
    
        // Here I check if I'm going to do the direct transform or the inverse
        // transform.
        double constant;
        if (DIRECT)
            constant = -2 * Math.PI;
        else
            constant = 2 * Math.PI;
    
        // I don't want to overwrite the input arrays, so here I copy them. This
        // choice adds \Theta(2n) to the complexity.
        for (int i = 0; i < n; i++) {
            xReal[i] = inputReal[i];
            xImag[i] = inputImag[i];
        }
    
        // First phase - calculation
        int k = 0;
        for (int l = 1; l <= nu; l++) {
            while (k < n) {
                for (int i = 1; i <= n2; i++) {
                    p = bitReverseReference(k >> nu1, nu);
                    // direct FFT or inverse FFT
                    arg = constant * p / n;
                    c = Math.cos(arg);
                    s = Math.sin(arg);
                    tReal = xReal[k + n2] * c + xImag[k + n2] * s;
                    tImag = xImag[k + n2] * c - xReal[k + n2] * s;
                    xReal[k + n2] = xReal[k] - tReal;
                    xImag[k + n2] = xImag[k] - tImag;
                    xReal[k] += tReal;
                    xImag[k] += tImag;
                    k++;
                }
                k += n2;
            }
            k = 0;
            nu1--;
            n2 /= 2;
        }
    
        // Second phase - recombination
        k = 0;
        int r;
        while (k < n) {
            r = bitReverseReference(k, nu);
            if (r > k) {
                tReal = xReal[k];
                tImag = xImag[k];
                xReal[k] = xReal[r];
                xImag[k] = xImag[r];
                xReal[r] = tReal;
                xImag[r] = tImag;
            }
            k++;
        }
    
        // Here I have to mix xReal and xImag to have an array (yes, it should
        // be possible to do this stuff in the earlier parts of the code, but
        // it's here to readibility).
        double[] newArray = new double[xReal.length * 2];
        double radice = 1 / Math.sqrt(n);
        for (int i = 0; i < newArray.length; i += 2) {
            int i2 = i / 2;
            // I used Stephen Wolfram's Mathematica as a reference so I'm going
            // to normalize the output while I'm copying the elements.
            newArray[i] = xReal[i2] * radice;
            newArray[i + 1] = xImag[i2] * radice;
        }
        return newArray;
    }
    
    /**
     * The reference bitreverse function.
     */
    private static int bitReverseReference(int j, int nu) {
        int j2;
        int j1 = j;
        int k = 0;
        for (int i = 1; i <= nu; i++) {
            j2 = j1 / 2;
            k = 2 * k + j1 - 2 * j2;
            j1 = j2;
        }
        return k;
    }
    }
    
    公共类FFT{
    /**
    *快速傅里叶变换(通用版本,无优化)。
    *
    *@param-inputReal
    *长度为n的数组,实数部分
    *@param inputImag
    *长度为n的数组,虚部
    *@param-DIRECT
    *真=直接变换,假=逆变换
    *@返回长度为2n的新数组
    */
    公共静态双[]fft(最终双[]输入,双[]输入,
    布尔(直接){
    //-n是问题的维数
    //-nu是以e为底的对数
    int n=inputReal.length;
    //如果n是2的幂,那么ld是整数(_不带小数)
    双ld=Math.log(n)/Math.log(2.0);
    //这里我检查n是否是2的幂。如果ld中存在小数,我退出
    //从函数返回null。
    如果((int)ld)-ld!=0){
    System.out.println(“元素的数量不是2的幂”);
    返回null;
    }
    //变量的声明和初始化
    //实际上,ld应该是一个整数,所以我不会丢失任何信息
    //演员阵容
    int nu=(int)ld;
    int n2=n/2;
    int nu1=nu-1;
    double[]xReal=新的双精度[n];
    double[]xImag=新的double[n];
    双通道,tImag,p,arg,c,s;
    //在这里,我检查我是要做正变换还是逆变换
    //转变。
    双常数;
    如果(直接)
    常数=-2*Math.PI;
    其他的
    常数=2*Math.PI;
    //我不想覆盖输入数组,所以我在这里复制它们
    //选择增加了\Theta(2n)的复杂性。
    对于(int i=0;ik){
    tReal=xReal[k];
    tImag=xImag[k];
    xReal[k]=xReal[r];
    xImag[k]=xImag[r];
    xReal[r]=tReal;
    xImag[r]=tImag;
    }
    k++;
    }
    //在这里,我必须混合使用xReal和xImag来创建一个数组(是的,应该是这样的)
    //可以在代码的前面部分做这些事情,但是
    //这是为了便于阅读)。
    double[]newArray=newdouble[xReal.length*2];
    双半径=1/数学sqrt(n);
    对于(int i=0;ipublic class FFT {
    
    /**
     * The Fast Fourier Transform (generic version, with NO optimizations).
     *
     * @param inputReal
     *            an array of length n, the real part
     * @param inputImag
     *            an array of length n, the imaginary part
     * @param DIRECT
     *            TRUE = direct transform, FALSE = inverse transform
     * @return a new array of length 2n
     */
    public static double[] fft(final double[] inputReal, double[] inputImag,
                               boolean DIRECT) {
        // - n is the dimension of the problem
        // - nu is its logarithm in base e
        int n = inputReal.length;
    
        // If n is a power of 2, then ld is an integer (_without_ decimals)
        double ld = Math.log(n) / Math.log(2.0);
    
        // Here I check if n is a power of 2. If exist decimals in ld, I quit
        // from the function returning null.
        if (((int) ld) - ld != 0) {
            System.out.println("The number of elements is not a power of 2.");
            return null;
        }
    
        // Declaration and initialization of the variables
        // ld should be an integer, actually, so I don't lose any information in
        // the cast
        int nu = (int) ld;
        int n2 = n / 2;
        int nu1 = nu - 1;
        double[] xReal = new double[n];
        double[] xImag = new double[n];
        double tReal, tImag, p, arg, c, s;
    
        // Here I check if I'm going to do the direct transform or the inverse
        // transform.
        double constant;
        if (DIRECT)
            constant = -2 * Math.PI;
        else
            constant = 2 * Math.PI;
    
        // I don't want to overwrite the input arrays, so here I copy them. This
        // choice adds \Theta(2n) to the complexity.
        for (int i = 0; i < n; i++) {
            xReal[i] = inputReal[i];
            xImag[i] = inputImag[i];
        }
    
        // First phase - calculation
        int k = 0;
        for (int l = 1; l <= nu; l++) {
            while (k < n) {
                for (int i = 1; i <= n2; i++) {
                    p = bitReverseReference(k >> nu1, nu);
                    // direct FFT or inverse FFT
                    arg = constant * p / n;
                    c = Math.cos(arg);
                    s = Math.sin(arg);
                    tReal = xReal[k + n2] * c + xImag[k + n2] * s;
                    tImag = xImag[k + n2] * c - xReal[k + n2] * s;
                    xReal[k + n2] = xReal[k] - tReal;
                    xImag[k + n2] = xImag[k] - tImag;
                    xReal[k] += tReal;
                    xImag[k] += tImag;
                    k++;
                }
                k += n2;
            }
            k = 0;
            nu1--;
            n2 /= 2;
        }
    
        // Second phase - recombination
        k = 0;
        int r;
        while (k < n) {
            r = bitReverseReference(k, nu);
            if (r > k) {
                tReal = xReal[k];
                tImag = xImag[k];
                xReal[k] = xReal[r];
                xImag[k] = xImag[r];
                xReal[r] = tReal;
                xImag[r] = tImag;
            }
            k++;
        }
    
        // Here I have to mix xReal and xImag to have an array (yes, it should
        // be possible to do this stuff in the earlier parts of the code, but
        // it's here to readibility).
        double[] newArray = new double[xReal.length * 2];
        double radice = 1 / Math.sqrt(n);
        for (int i = 0; i < newArray.length; i += 2) {
            int i2 = i / 2;
            // I used Stephen Wolfram's Mathematica as a reference so I'm going
            // to normalize the output while I'm copying the elements.
            newArray[i] = xReal[i2] * radice;
            newArray[i + 1] = xImag[i2] * radice;
        }
        return newArray;
    }
    
    /**
     * The reference bitreverse function.
     */
    private static int bitReverseReference(int j, int nu) {
        int j2;
        int j1 = j;
        int k = 0;
        for (int i = 1; i <= nu; i++) {
            j2 = j1 / 2;
            k = 2 * k + j1 - 2 * j2;
            j1 = j2;
        }
        return k;
    }
    }