D:/work/code_by/CbmrEngine/cbmrdtw.cpp

查看本檔案說明文件.
00001 /*==============================================================================
00002 最後修改日期:2001/1/4 by 高名揚
00003 最快、最省記憶體的dynamic time warping
00004 dtw table只有WINDOW_WIDTH行
00005 ==============================================================================*/
00006 #include <stdlib.h>
00007 #include "cbmrdtw.h"
00008 
00009 #define WINDOW_WIDTH 2
00010 
00011 typedef struct
00012 {
00013   int dist;
00014   int matchLength;
00015 } DTWtableStruct;
00016 
00017 DTWtableStruct *DTWtable[WINDOW_WIDTH];
00018 
00019 void newDTWtable(int height)
00020 {
00021   int i;
00022 
00023   for (i = 0; i < WINDOW_WIDTH; i++)
00024     DTWtable[i] = new DTWtableStruct[height];
00025 }
00026 
00027 void delDTWtable(void)
00028 {
00029   int i;
00030 
00031   for (i = 0; i < WINDOW_WIDTH; i++)
00032     delete[] DTWtable[i];
00033 }
00034 
00035 int dtw(int *data1, int size1, int *data2, int size2,
00036       bool fixLeft, int *pathLength, int threshold)
00037 {
00038   int i, j, k;
00039   int startj, endj;
00040   int tableColumn;
00041   int finali, finalj;
00042   int preDistance, minDistance;
00043   int preMatchLength;
00044   int parentIndex[WINDOW_WIDTH][WINDOW_WIDTH] = {{1, 0}, {0, 1}}, *pIndex;
00045   int minDistOfCol;
00046   int minDistOfCols[WINDOW_WIDTH];  //最近WINDOW_WIDTH行的最小值
00047 
00048   if (size2 <= (size1 + WINDOW_WIDTH - 2) / WINDOW_WIDTH)  //data2太短
00049   {
00050     *pathLength = 0;
00051     return INFINITE_INT;
00052   }
00053 
00054   newDTWtable(size2 + WINDOW_WIDTH);
00055   //把應該是INF的地方先填上
00056   for (i = 0; i < WINDOW_WIDTH; i++)
00057     for (j = 0; j < size2 + WINDOW_WIDTH; j++)
00058       DTWtable[i][j].dist = INFINITE_INT;
00059 
00060   //先算好第0行
00061   if (!fixLeft)
00062   {
00063     minDistOfCol = INFINITE_INT;
00064     for (j = size2 - (size1 + WINDOW_WIDTH - 2) / WINDOW_WIDTH - 1; j >= 0; j--)
00065     {
00066       if ((DTWtable[0][j + WINDOW_WIDTH].dist = abs(data1[0] - data2[j])) < minDistOfCol)
00067         minDistOfCol = DTWtable[0][j + WINDOW_WIDTH].dist;
00068       DTWtable[0][j + WINDOW_WIDTH].matchLength = 1;
00069     }
00070     minDistOfCols[0] = minDistOfCol;
00071   }
00072   else
00073   {
00074     DTWtable[0][WINDOW_WIDTH].dist = abs(data1[0] - data2[0]);
00075     DTWtable[0][WINDOW_WIDTH].matchLength = 1;
00076     minDistOfCols[0] = DTWtable[0][WINDOW_WIDTH].dist;
00077   }
00078   for (i = 1; i < WINDOW_WIDTH; i++)
00079     minDistOfCols[i] = INFINITE_INT;
00080   //計算其他點的距離
00081   tableColumn = 0;
00082   startj = 1;
00083   for (i = 1; i < size1; i++)  //計算dtw table的每一行
00084   {
00085     if (++tableColumn == WINDOW_WIDTH)
00086       tableColumn = 0;
00087     //計算endj
00088     endj = size2 - (size1 + WINDOW_WIDTH - 2 - i) / WINDOW_WIDTH - 1;
00089     if (fixLeft)
00090       if (endj > i * WINDOW_WIDTH)
00091         endj = i * WINDOW_WIDTH;
00092 
00093     pIndex = parentIndex[tableColumn];
00094     minDistOfCol = INFINITE_INT;
00095     for (j = endj; j >= startj; j--)  //計算dtw table第i行的每一個元素
00096     {
00097       preDistance = DTWtable[pIndex[0]][j + WINDOW_WIDTH - 1].dist;
00098       preMatchLength = DTWtable[pIndex[0]][j + WINDOW_WIDTH - 1].matchLength;
00099       if (DTWtable[pIndex[1]][j + WINDOW_WIDTH - 1].dist < preDistance)
00100       {
00101         preDistance = DTWtable[pIndex[1]][j + WINDOW_WIDTH - 1].dist;
00102         preMatchLength = DTWtable[pIndex[1]][j + WINDOW_WIDTH - 1].matchLength;
00103       }
00104       if (DTWtable[pIndex[0]][j + WINDOW_WIDTH - 2].dist < preDistance)
00105       {
00106         preDistance = DTWtable[pIndex[0]][j + WINDOW_WIDTH - 2].dist;
00107         preMatchLength = DTWtable[pIndex[0]][j + WINDOW_WIDTH - 2].matchLength;
00108       }
00109 
00110       DTWtable[tableColumn][j + WINDOW_WIDTH].dist = preDistance < INFINITE_INT? preDistance + abs(data1[i] - data2[j]) : INFINITE_INT;  //累積距離
00111       DTWtable[tableColumn][j + WINDOW_WIDTH].matchLength = preMatchLength + 1;  //match長度加1
00112 
00113       if (DTWtable[tableColumn][j + WINDOW_WIDTH].dist < minDistOfCol)
00114         minDistOfCol = DTWtable[tableColumn][j + WINDOW_WIDTH].dist;
00115     }  //for j
00116 
00117     for (j = startj - WINDOW_WIDTH; j < startj; j++)  //在每一行下方補上WINDOW_WIDTH個INF
00118       DTWtable[tableColumn][j + WINDOW_WIDTH].dist = INFINITE_INT;
00119 
00120     if (tableColumn == 0)
00121       startj++;  //更新startj
00122 
00123     minDistOfCols[tableColumn] = minDistOfCol;  //目前這一行的最小值
00124     for (k = 0; k < WINDOW_WIDTH; k++)  //找出最近WINDOW_WIDTH行中的最小值
00125       if (minDistOfCols[k] < minDistOfCol)
00126         minDistOfCol = minDistOfCols[k];
00127     if (minDistOfCol > threshold)  //如果最小值比threshold還大則跳出
00128     {
00129       *pathLength = 0;
00130       delDTWtable();
00131       return INFINITE_INT;
00132     }
00133   }  //for i
00134   //從最後一行找出最小值minDistance及其位置(finali, finalj)
00135   minDistance = INFINITE_INT;
00136   finali = tableColumn;
00137   k = (size1 + WINDOW_WIDTH - 2) / WINDOW_WIDTH;
00138   for (j = size2 - 1; j >= k; j--)
00139     if (DTWtable[finali][j + WINDOW_WIDTH].dist < minDistance)
00140     {
00141       minDistance = DTWtable[finali][j + WINDOW_WIDTH].dist;
00142       finalj = j + WINDOW_WIDTH;
00143     }
00144   *pathLength = DTWtable[finali][finalj].matchLength;  //match到的長度
00145   delDTWtable();
00146   return minDistance;
00147 }
00148 

產生日期:Tue Jul 11 11:52:19 2006, 專案:cbmr, 產生器:  doxygen 1.4.7