0

这是光谱减法算法代码的一部分,我正在尝试针对 android 优化它。请帮助我。

这是matlab代码:

function Seg=segment(signal,W,SP,Window)

% SEGMENT chops a signal to overlapping windowed segments
% A= SEGMENT(X,W,SP,WIN) returns a matrix which its columns are segmented
% and windowed frames of the input one dimentional signal, X. W is the
% number of samples per window, default value W=256. SP is the shift
% percentage, default value SP=0.4. WIN is the window that is multiplied by
% each segment and its length should be W. the default window is hamming
% window.
% 06-Sep-04
% Esfandiar Zavarehei

if nargin<3
    SP=.4;
end
if nargin<2
    W=256;
end
if nargin<4
    Window=hamming(W);
end
Window=Window(:); %make it a column vector

L=length(signal);
SP=fix(W.*SP);
N=fix((L-W)/SP +1); %number of segments

Index=(repmat(1:W,N,1)+repmat((0:(N-1))'*SP,1,W))';
hw=repmat(Window,1,N);
Seg=signal(Index).*hw;

这是我们这个函数的java代码:

public class MatrixAndSegments 
{
    public int numberOfSegments;
    public double[][] res;

    public MatrixAndSegments(int numberOfSegments,double[][] res)
    {
        this.numberOfSegments = numberOfSegments;
        this.res = res;
    }
}



public MatrixAndSegments segment (double[] signal_in,int samplesPerWindow, double           shiftPercentage, double[] window)
{
    //default shiftPercentage = 0.4
    //default samplesPerWindow = 256  //W
    //default window = hanning 

    int L = signal_in.length;
    shiftPercentage = fix(samplesPerWindow * shiftPercentage); //SP
    int numberOfSegments = fix ( (L - samplesPerWindow)/ shiftPercentage + 1); //N

    double[][] reprowMatrix =  reprowtrans(samplesPerWindow,numberOfSegments);
    double[][] repcolMatrix = repcoltrans(numberOfSegments,    shiftPercentage,samplesPerWindow );

    //Index=(repmat(1:W,N,1)+repmat((0:(N-1))'*SP,1,W))';
    double[][] index = new double[samplesPerWindow+1][numberOfSegments+1];

    for (int x = 1;  x < samplesPerWindow+1; x++ )
    {
        for (int y = 1 ; y < numberOfSegments + 1; y++) //numberOfSegments was 3
        {
             index[x][y] = reprowMatrix[x][y] + repcolMatrix[x][y];
        }
    }

    //hamming window
    double[] hammingWindow = this.HammingWindow(samplesPerWindow);
    double[][] HW = repvector(hammingWindow, numberOfSegments);

    double[][] seg = new double[samplesPerWindow][numberOfSegments];
    for (int y = 1 ; y < numberOfSegments + 1; y++)
    {
        for (int x = 1; x < samplesPerWindow+1; x++)
        {
            seg[x-1][y-1] = signal_in[ (int)index[x][y]-1 ] * HW[x-1][y-1]; 
        }
    }
    MatrixAndSegments Matrixseg = new MatrixAndSegments(numberOfSegments,seg);
    return Matrixseg;
}


public int fix(double val) {
    if (val < 0) {
        return (int) Math.ceil(val);
    }
    return (int) Math.floor(val);
}

public double[][] repvector(double[] vec, int replications)
{
    double[][] result = new double[vec.length][replications];

    for (int x = 0; x < vec.length; x++) {
        for (int y = 0; y < replications; y++) {
            result[x][y] = vec[x];
        }
    }

    return result;
}

public double[][] reprowtrans(int end, int replications)
{
    double[][] result = new double[end +1][replications+1];

    for (int x = 1; x <= end; x++) {
        for (int y = 1; y <= replications; y++) {
            result[x][y] = x ;
        }
    }

    return result;
}

public double[][] repcoltrans(int end, double multiplier, int replications)
{
    double[][] result = new double[replications+1][end+1];

    for (int x = 1; x <= replications; x++) {
        for (int y = 1; y <= end ; y++) {
            result[x][y] = (y-1)*multiplier;
        }
    }  
    return result;
}

public double[] HammingWindow(int size)
{
    double[] window = new double[size];
    for (int i = 0; i < size; i++)
    {
        window[i] =  0.54-0.46 * (Math.cos(2.0 * Math.PI * i / (size-1)));
    }
    return window;
}
4

1 回答 1

5

逐句将 Matlab 代码“移植”到 Java 是一种不好的方法。

在 Matlab 中,很少使用循环和寻址单个元素来处理数据(因为 Matlab 解释器/VM 相当慢),而是通过调用块处理函数(已经仔细编写和优化)。这导致了一种非常特殊的编程风格,其中repmat, reshape, find, 花哨的索引等。用于执行通过 Java 循环更自然地表达的操作。

例如,要将矩阵 A 的每一列乘以向量 v,您将在 matlab 中编写:

A = diag(v) * A

或者

A = repmat(v', 1, size(A, 2)) .* A

这个解决方案:

for i = 1:size(A, 2),
  A(:, i) = A(:, i) .* v';
end;

效率低下。

但是尝试在 Java 中做同样的事情并调用矩阵乘积或使用重复的 v 副本构建矩阵是非常愚蠢的。相反,只需执行以下操作:

for (int i = 0; i < rows; i++) {
  for (int j = 0; j < columns; j++) {
    a[i][j] *= v[i]
  }
}

我建议你尝试了解这个matlab 函数实际上在做什么,而不是专注于它是如何做的,并在 Java 中从头开始重新实现它,忘记除了注释中给出的规范之外的所有 matlab 实现。确实,您编写的代码中有一半是无用的。实际上,在我看来,这个函数根本不需要,它的作用可以有效地集成到调用者的代码中。

于 2012-08-18T12:36:08.490 回答