使用Apple Accelerate Framework中的vDSP_conv执行自相关。

7
我需要对一个数组(向量)执行自相关,但我找不到正确的方法。我相信我需要使用加速框架中的"vDSP_conv"方法,但我无法成功设置它。最困扰我的是需要两个输入。也许我选择了错误的函数,但我找不到一个只操作单个向量的函数。
文档可以在这里找到。
从网站复制。

vDSP_conv

Performs either correlation or convolution on two vectors; single precision.

void vDSP_conv ( const float __vDSP_signal[], vDSP_Stride __vDSP_signalStride, const float __vDSP_filter[], vDSP_Stride __vDSP_strideFilter, float __vDSP_result[], vDSP_Stride __vDSP_strideResult, vDSP_Length __vDSP_lenResult, vDSP_Length __vDSP_lenFilter );

Parameters

__vDSP_signal

Input vector A. The length of this vector must be at least __vDSP_lenResult + __vDSP_lenFilter - 1.

__vDSP_signalStride

The stride through __vDSP_signal.

__vDSP_filter

Input vector B.

__vDSP_strideFilter

The stride through __vDSP_filter.

__vDSP_result

Output vector C.

__vDSP_strideResult

The stride through __vDSP_result.

__vDSP_lenResult

The length of __vDSP_result.

__vDSP_lenFilter

The length of __vDSP_filter.
假设您有一个float x = [1.0, 2.0, 3.0, 4.0, 5.0]的数组,如何计算自相关?输出结果应类似于float y = [5.0, 14.0, 26.0, 40.0, 55.0, 40.0, 26.0, 14.0, 5.0] //使用Matlab的xcorr(x)函数生成
1个回答

4

执行自相关简单地意味着将一个向量与其自身进行互相关。这并不复杂。

所以在您的情况下,请执行:

vDSP_conv(x, 1, x, 1, result, 1, 2*len_X-1, len_X); 

请查看以下示例代码(进行卷积)以获取更多详细信息:

http://disanji.net/iOS_Doc/#documentation/Performance/Conceptual/vDSP_Programming_Guide/SampleCode/SampleCode.html

编辑:这几乎是荒谬的,但您需要通过特定数量的零来偏移x值,这太疯狂了。

以下是一个可行的代码,只需将过滤器设置为所需的x值,它就会将其余部分放置在正确的位置:

float          *signal, *filter, *result;

int32_t         signalStride, filterStride, resultStride;

uint32_t        lenSignal, filterLength, resultLength;

uint32_t        i;



filterLength = 5;

resultLength = filterLength*2 -1;

lenSignal = ((filterLength + 3) & 0xFFFFFFFC) + resultLength;



signalStride = filterStride = resultStride = 1;



printf("\nConvolution ( resultLength = %d, "

       "filterLength = %d )\n\n", resultLength, filterLength);



/* Allocate memory for the input operands and check its availability. */

signal = (float *) malloc(lenSignal * sizeof(float));

filter = (float *) malloc(filterLength * sizeof(float));

result = (float *) malloc(resultLength * sizeof(float));



for (i = 0; i < filterLength; i++)

    filter[i] = (float)(i+1);

for (i = 0; i < resultLength; i++)
    if (i >=resultLength- filterLength)
        signal[i] = filter[i - filterLength+1];


/* Correlation. */

vDSP_conv(signal, signalStride, filter, filterStride,

          result, resultStride, resultLength, filterLength);


printf("signal: ");
for (i = 0; i < lenSignal; i++)        
    printf("%2.1f ", signal[i]);


printf("\n filter: ");
for (i = 0; i < filterLength; i++)
    printf("%2.1f ", filter[i]);

printf("\n result: ");
for (i = 0; i < resultLength; i++)
    printf("%2.1f ", result[i]);


/* Free allocated memory. */

free(signal);

free(filter);

free(result);

我刚刚使用我的示例尝试了一下。但输出的数据有些错误。我做错了什么吗?x = 1到5,结果大小为9(5 * 2-1)vDSP_conv(x,1,x,1,result,1,9,5); -> 输出-> 55.0,40.0,26.0,14.0,5.0,0.0,0.0,0.0,294.0 - MrHappyAsthma
我觉得我犯了一个错误,你可能需要用零填充x...我没有我的Mac在我面前,但似乎输入应该比输出长(这至少很奇怪) - Rasman
呃 :P 真糟糕。我会试着调整一下。如果你找到了确切的解决方法,请发帖告诉我 :D - MrHappyAsthma
@MrHappyAsthma,我花了一些时间,但我弄清楚了。请查看上面的编辑。祝你好运。 - Rasman
真是太奇怪了,居然要这样做,但它确实有效!:D 非常感谢!!! - MrHappyAsthma
这是一个老问题 - 但如果有用的话 - 如果您想要线性自相关,则需要使用与数据相同长度的零填充输入 - 如果不这样做,则会得到循环自相关,因此答案会略有偏差 - 我猜测这是因为内部使用FFT。 - Simon East

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接