First version of the dynamic time warping algorithm.
F32 only. Some windows suppported.pull/94/head
parent
5bee006eaa
commit
b46a2f86b5
@ -0,0 +1,153 @@
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_braycurtis_distance_f32.c
|
||||
* Description: Bray-Curtis distance between two vectors
|
||||
*
|
||||
* $Date: 23 April 2021
|
||||
* $Revision: V1.9.0
|
||||
*
|
||||
* Target Processor: Cortex-M and Cortex-A cores
|
||||
* -------------------------------------------------------------------- */
|
||||
/*
|
||||
* Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "dsp/distance_functions.h"
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#define E(MAT,R,C) \
|
||||
(*((MAT)->pData + (MAT)->numCols*(R) + (C)))
|
||||
|
||||
#define WIN(R,C) \
|
||||
((pWindow == NULL) ? 1 : \
|
||||
((*((pWindow)->pData + (pWindow)->numCols*(R) + (C)))==1))
|
||||
|
||||
/**
|
||||
@ingroup FloatDist
|
||||
*/
|
||||
|
||||
/**
|
||||
@defgroup DTW Dynamic Time Warping Distance
|
||||
|
||||
Dynamic Time Warping Distance.
|
||||
|
||||
This is not really a distance since triangular inequality is
|
||||
not respected.
|
||||
|
||||
The step pattern used is symmetric2.
|
||||
Future versions of this function will provide more customization options.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
@addtogroup DTW
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Dynamic Time Warping distance
|
||||
* @param[in] pDistance Distance matrix (Query rows * Template columns)
|
||||
* @param[in] pWindow Windowing matrix (can be NULL if no windowing used)
|
||||
* @param[out] pDTW Temporary cost buffer (same size)
|
||||
* @param[out] distance Distance
|
||||
* @return ARM_MATH_ARGUMENT_ERROR in case no path can be found with window constraint
|
||||
*
|
||||
* @par Windowing matrix
|
||||
*
|
||||
* The windowing matrix is used to impose some
|
||||
* constraints on the search for a path.
|
||||
* The algorithm will run faster (smaller search
|
||||
* path) but may not be able to find a solution.
|
||||
*
|
||||
* The distance matrix must be initialized only
|
||||
* where the windowing matrix is containing 1.
|
||||
* Thus, use of a window also decreases the number
|
||||
* of distances which must be computed.
|
||||
*/
|
||||
arm_status arm_dtw_distance_f32(const arm_matrix_instance_f32 *pDistance,
|
||||
const arm_matrix_instance_q7 *pWindow,
|
||||
arm_matrix_instance_f32 *pDTW,
|
||||
float32_t *distance)
|
||||
{
|
||||
const uint32_t queryLength = pDistance -> numRows;
|
||||
const uint32_t templateLength = pDistance -> numCols;
|
||||
float32_t result;
|
||||
|
||||
float32_t *temp = pDTW->pData;
|
||||
for(uint32_t q=0 ; q < queryLength; q++)
|
||||
{
|
||||
for(uint32_t t= 0; t < templateLength; t++)
|
||||
{
|
||||
*temp++ = F32_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
pDTW->pData[0] = E(pDistance,0,0);
|
||||
for(uint32_t q = 1; q < queryLength; q++)
|
||||
{
|
||||
if (!WIN(q,0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
E(pDTW,q,0) = E(pDTW,q-1,0) + E(pDistance,q,0);
|
||||
}
|
||||
|
||||
for(uint32_t t = 1; t < templateLength; t++)
|
||||
{
|
||||
if (!WIN(0,t))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
E(pDTW,0,t) = E(pDTW,0,t-1) + E(pDistance,0,t);
|
||||
}
|
||||
|
||||
|
||||
for(uint32_t q = 1; q < queryLength; q++)
|
||||
{
|
||||
for(uint32_t t = 1; t < templateLength; t++)
|
||||
{
|
||||
if (!WIN(q,t))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
E(pDTW,q,t) =
|
||||
MIN(E(pDTW,q-1,t-1) + 2.0f * E(pDistance,q,t),
|
||||
MIN(E(pDTW,q,t-1) + E(pDistance,q,t),
|
||||
E(pDTW,q-1,t) + E(pDistance,q,t)));
|
||||
}
|
||||
}
|
||||
|
||||
if (E(pDTW,queryLength-1,templateLength-1) == F32_MAX)
|
||||
{
|
||||
return(ARM_MATH_ARGUMENT_ERROR);
|
||||
}
|
||||
|
||||
result = E(pDTW,queryLength-1,templateLength-1);
|
||||
result = result / (queryLength + templateLength);
|
||||
*distance = result;
|
||||
|
||||
return(ARM_MATH_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of DTW group
|
||||
*/
|
||||
|
||||
@ -0,0 +1,120 @@
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_dtw_path_f32.c
|
||||
* Description: Warping path
|
||||
*
|
||||
* $Date: 23 April 2021
|
||||
* $Revision: V1.9.0
|
||||
*
|
||||
* Target Processor: Cortex-M and Cortex-A cores
|
||||
* -------------------------------------------------------------------- */
|
||||
/*
|
||||
* Copyright (C) 2010-2022 ARM Limited or its affiliates. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "dsp/distance_functions.h"
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
/**
|
||||
@addtogroup DTW
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Window for dynamic time warping computation
|
||||
* @param[in] windowType Type of window
|
||||
* @param[in] windowSize Window size
|
||||
* @param[in,out] pWindow Window
|
||||
* @return Error if window type not recognized
|
||||
*
|
||||
* @par Windowing matrix
|
||||
* The window matrix will contain 1 for the
|
||||
* position which are accepted and 0 for the
|
||||
* positions which are rejected.
|
||||
*
|
||||
* The input matrix must already contain a buffer
|
||||
* and the number of rows (query length) and columns
|
||||
* (template length) must be initialized.
|
||||
* The function will fill the matrix with 0 and 1.
|
||||
*
|
||||
*/
|
||||
arm_status arm_dtw_init_window_q7(const arm_dtw_window windowType,
|
||||
const int32_t windowSize,
|
||||
arm_matrix_instance_q7 *pWindow)
|
||||
{
|
||||
const int32_t queryLength = pWindow -> numRows;
|
||||
const int32_t templateLength = pWindow -> numCols;
|
||||
|
||||
switch(windowType)
|
||||
{
|
||||
case ARM_DTW_SAKOE_CHIBA_WINDOW:
|
||||
{
|
||||
for(int32_t q = 0; q < queryLength; q++)
|
||||
{
|
||||
for(int32_t t = 0; t < templateLength; t++)
|
||||
{
|
||||
pWindow->pData[templateLength*q + t] = (q7_t)(abs(q-t) <= windowSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case ARM_DTW_ITAKURA_WINDOW:
|
||||
{
|
||||
for(int32_t q = 0; q < queryLength; q++)
|
||||
{
|
||||
for(int32_t t = 0; t < templateLength; t++)
|
||||
{
|
||||
pWindow->pData[templateLength*q + t] = (q7_t)(
|
||||
(t < 2 * q) &&
|
||||
(q <= 2 * t) &&
|
||||
(q >= queryLength - 1 - 2 * (templateLength - t)) &&
|
||||
(t > templateLength - 1 - 2 * (queryLength - q)));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case ARM_DTW_SLANTED_BAND_WINDOW:
|
||||
{
|
||||
for(int32_t q = 0; q < queryLength; q++)
|
||||
{
|
||||
for(int32_t t = 0; t < templateLength; t++)
|
||||
{
|
||||
float32_t diag = (1.0f * q * templateLength / queryLength);
|
||||
pWindow->pData[templateLength*q + t] = (q7_t)(fabsf((float32_t)t - diag) <= (float32_t)windowSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return(ARM_MATH_ARGUMENT_ERROR);
|
||||
}
|
||||
|
||||
return(ARM_MATH_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of DTW group
|
||||
*/
|
||||
|
||||
@ -0,0 +1,166 @@
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_dtw_path_f32.c
|
||||
* Description: Warping path
|
||||
*
|
||||
* $Date: 23 April 2021
|
||||
* $Revision: V1.9.0
|
||||
*
|
||||
* Target Processor: Cortex-M and Cortex-A cores
|
||||
* -------------------------------------------------------------------- */
|
||||
/*
|
||||
* Copyright (C) 2010-2022 ARM Limited or its affiliates. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "dsp/distance_functions.h"
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#define E(MAT,R,C) \
|
||||
(*((MAT)->pData + (MAT)->numCols*(R) + (C)))
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@addtogroup DTW
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Mapping between query and template
|
||||
* @param[in] pDTW Cost matrix (Query rows * Template columns)
|
||||
* @param[out] pPath Warping path in cost matrix 2*(nb rows + nb columns)
|
||||
* @param[out] pathLength Length of path in number of points
|
||||
* @return none
|
||||
*
|
||||
* @par Warping path
|
||||
*
|
||||
* The warping path has length which is at most
|
||||
* 2*(query length + template length) in float.
|
||||
* 2 because it is a list of coordinates :
|
||||
* (query index, template index) coordinate.
|
||||
*
|
||||
* The buffer pPath must be big enough to contain
|
||||
* the warping path.
|
||||
*
|
||||
* pathLength is the number of points in
|
||||
* the returned path. The resturned path
|
||||
* may be smaller than query + template.
|
||||
*
|
||||
*/
|
||||
void arm_dtw_path_f32(const arm_matrix_instance_f32 *pDTW,
|
||||
int16_t *pPath,
|
||||
uint32_t *pathLength)
|
||||
{
|
||||
int q,t;
|
||||
float32_t temp;
|
||||
|
||||
*pathLength = 0;
|
||||
q=pDTW->numRows-1;
|
||||
t=pDTW->numCols-1;
|
||||
while((q>0) || (t>0))
|
||||
{
|
||||
int p=-1;
|
||||
float32_t current=F32_MAX;
|
||||
|
||||
if (q>0)
|
||||
{
|
||||
temp = E(pDTW,q-1,t);
|
||||
if (temp<current)
|
||||
{
|
||||
current=temp;
|
||||
p=2;
|
||||
}
|
||||
}
|
||||
|
||||
if (t>0)
|
||||
{
|
||||
temp = E(pDTW,q,t-1);
|
||||
if (temp<current)
|
||||
{
|
||||
current=temp;
|
||||
p=0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((q>0) && (t>0))
|
||||
{
|
||||
temp = E(pDTW,q-1,t-1);
|
||||
if (temp<current)
|
||||
{
|
||||
current=temp;
|
||||
p=1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
pPath[2 * (*pathLength)] = q;
|
||||
pPath[2 * (*pathLength) + 1] = t;
|
||||
|
||||
*pathLength = *pathLength + 1;
|
||||
|
||||
switch(p)
|
||||
{
|
||||
case 0:
|
||||
t = t-1;
|
||||
break;
|
||||
case 1:
|
||||
t=t-1;
|
||||
q=q-1;
|
||||
break;
|
||||
case 2:
|
||||
q=q-1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pPath[2 * (*pathLength)] = 0;
|
||||
pPath[2 * (*pathLength) + 1] = 0;
|
||||
*pathLength = *pathLength + 1;
|
||||
|
||||
/* Reverse the path */
|
||||
int16_t *fh,*sh;
|
||||
fh = pPath;
|
||||
sh = pPath + 2* (*pathLength)-2;
|
||||
int halfLength = (*pathLength)>>1;
|
||||
for(int i = 0; i< halfLength; i++)
|
||||
{
|
||||
temp = fh[0];
|
||||
fh[0] = sh[0];
|
||||
sh[0] = temp;
|
||||
|
||||
temp = fh[1];
|
||||
fh[1] = sh[1];
|
||||
sh[1] = temp;
|
||||
|
||||
fh += 2;
|
||||
sh -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of DTW group
|
||||
*/
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
H
|
||||
3
|
||||
// 0.299623
|
||||
0x34cb
|
||||
// 0.413192
|
||||
0x369c
|
||||
// 0.617100
|
||||
0x38f0
|
||||
@ -0,0 +1,46 @@
|
||||
H
|
||||
22
|
||||
// 0
|
||||
0x0000
|
||||
// 0
|
||||
0x0000
|
||||
// 1
|
||||
0x0001
|
||||
// 0
|
||||
0x0000
|
||||
// 2
|
||||
0x0002
|
||||
// 0
|
||||
0x0000
|
||||
// 3
|
||||
0x0003
|
||||
// 0
|
||||
0x0000
|
||||
// 4
|
||||
0x0004
|
||||
// 0
|
||||
0x0000
|
||||
// 5
|
||||
0x0005
|
||||
// 1
|
||||
0x0001
|
||||
// 6
|
||||
0x0006
|
||||
// 2
|
||||
0x0002
|
||||
// 7
|
||||
0x0007
|
||||
// 2
|
||||
0x0002
|
||||
// 8
|
||||
0x0008
|
||||
// 2
|
||||
0x0002
|
||||
// 9
|
||||
0x0009
|
||||
// 3
|
||||
0x0003
|
||||
// 9
|
||||
0x0009
|
||||
// 4
|
||||
0x0004
|
||||
@ -0,0 +1,22 @@
|
||||
H
|
||||
10
|
||||
// 0.083872
|
||||
0x2d5e
|
||||
// 0.680823
|
||||
0x3972
|
||||
// 1.067564
|
||||
0x3c45
|
||||
// 0.889145
|
||||
0x3b1d
|
||||
// 0.425134
|
||||
0x36cd
|
||||
// -0.325905
|
||||
0xb537
|
||||
// -0.809349
|
||||
0xba7a
|
||||
// -0.909794
|
||||
0xbb47
|
||||
// -0.640265
|
||||
0xb91f
|
||||
// 0.069237
|
||||
0x2c6e
|
||||
@ -0,0 +1,12 @@
|
||||
H
|
||||
5
|
||||
// 1.000000
|
||||
0x3c00
|
||||
// 0.000796
|
||||
0x1286
|
||||
// -0.999999
|
||||
0xbc00
|
||||
// -0.002389
|
||||
0x98e5
|
||||
// 0.999995
|
||||
0x3c00
|
||||
@ -0,0 +1,8 @@
|
||||
W
|
||||
3
|
||||
// 0.299623
|
||||
0x3e996838
|
||||
// 0.413192
|
||||
0x3ed38dd7
|
||||
// 0.617100
|
||||
0x3f1dfa43
|
||||
@ -0,0 +1,46 @@
|
||||
H
|
||||
22
|
||||
// 0
|
||||
0x0000
|
||||
// 0
|
||||
0x0000
|
||||
// 1
|
||||
0x0001
|
||||
// 0
|
||||
0x0000
|
||||
// 2
|
||||
0x0002
|
||||
// 0
|
||||
0x0000
|
||||
// 3
|
||||
0x0003
|
||||
// 0
|
||||
0x0000
|
||||
// 4
|
||||
0x0004
|
||||
// 0
|
||||
0x0000
|
||||
// 5
|
||||
0x0005
|
||||
// 1
|
||||
0x0001
|
||||
// 6
|
||||
0x0006
|
||||
// 2
|
||||
0x0002
|
||||
// 7
|
||||
0x0007
|
||||
// 2
|
||||
0x0002
|
||||
// 8
|
||||
0x0008
|
||||
// 2
|
||||
0x0002
|
||||
// 9
|
||||
0x0009
|
||||
// 3
|
||||
0x0003
|
||||
// 9
|
||||
0x0009
|
||||
// 4
|
||||
0x0004
|
||||
@ -0,0 +1,22 @@
|
||||
W
|
||||
10
|
||||
// 0.083872
|
||||
0x3dabc511
|
||||
// 0.680823
|
||||
0x3f2e4a66
|
||||
// 1.067564
|
||||
0x3f88a5f1
|
||||
// 0.889145
|
||||
0x3f639f09
|
||||
// 0.425134
|
||||
0x3ed9ab29
|
||||
// -0.325905
|
||||
0xbea6dd0f
|
||||
// -0.809349
|
||||
0xbf4f317c
|
||||
// -0.909794
|
||||
0xbf68e848
|
||||
// -0.640265
|
||||
0xbf23e865
|
||||
// 0.069237
|
||||
0x3d8dcc1a
|
||||
@ -0,0 +1,12 @@
|
||||
W
|
||||
5
|
||||
// 1.000000
|
||||
0x3f800000
|
||||
// 0.000796
|
||||
0x3a50c095
|
||||
// -0.999999
|
||||
0xbf7fffeb
|
||||
// -0.002389
|
||||
0xbb1c9067
|
||||
// 0.999995
|
||||
0x3f7fffab
|
||||
@ -0,0 +1,8 @@
|
||||
D
|
||||
3
|
||||
// 0.299623
|
||||
0x3fd32d07076c6930
|
||||
// 0.413192
|
||||
0x3fda71bad76ba597
|
||||
// 0.617100
|
||||
0x3fe3bf485eb516e2
|
||||
@ -0,0 +1,46 @@
|
||||
H
|
||||
22
|
||||
// 0
|
||||
0x0000
|
||||
// 0
|
||||
0x0000
|
||||
// 1
|
||||
0x0001
|
||||
// 0
|
||||
0x0000
|
||||
// 2
|
||||
0x0002
|
||||
// 0
|
||||
0x0000
|
||||
// 3
|
||||
0x0003
|
||||
// 0
|
||||
0x0000
|
||||
// 4
|
||||
0x0004
|
||||
// 0
|
||||
0x0000
|
||||
// 5
|
||||
0x0005
|
||||
// 1
|
||||
0x0001
|
||||
// 6
|
||||
0x0006
|
||||
// 2
|
||||
0x0002
|
||||
// 7
|
||||
0x0007
|
||||
// 2
|
||||
0x0002
|
||||
// 8
|
||||
0x0008
|
||||
// 2
|
||||
0x0002
|
||||
// 9
|
||||
0x0009
|
||||
// 3
|
||||
0x0003
|
||||
// 9
|
||||
0x0009
|
||||
// 4
|
||||
0x0004
|
||||
@ -0,0 +1,22 @@
|
||||
D
|
||||
10
|
||||
// 0.083872
|
||||
0x3fb578a228337ad7
|
||||
// 0.680823
|
||||
0x3fe5c94cc5558a20
|
||||
// 1.067564
|
||||
0x3ff114be2ac8808d
|
||||
// 0.889145
|
||||
0x3fec73e1132ad516
|
||||
// 0.425134
|
||||
0x3fdb356527212c20
|
||||
// -0.325905
|
||||
0xbfd4dba1e745f4d7
|
||||
// -0.809349
|
||||
0xbfe9e62f8f39c447
|
||||
// -0.909794
|
||||
0xbfed1d090a6abd0d
|
||||
// -0.640265
|
||||
0xbfe47d0cab3420c4
|
||||
// 0.069237
|
||||
0x3fb1b98343ecbedb
|
||||
@ -0,0 +1,12 @@
|
||||
D
|
||||
5
|
||||
// 1.000000
|
||||
0x3ff0000000000000
|
||||
// 0.000796
|
||||
0x3f4a18129720662e
|
||||
// -0.999999
|
||||
0xbfeffffd573f6831
|
||||
// -0.002389
|
||||
0xbf63920cdb4e508b
|
||||
// 0.999995
|
||||
0x3feffff55c743065
|
||||
Loading…
Reference in New Issue