Dynamic time warping with python (final mapping)

梦想的初衷 提交于 2019-12-11 01:05:37

问题


I need to align two sound signals in order to map one into the other (both signals corresponds to the same behavior). I try to implement the python code from: https://nipunbatra.github.io/blog/2014/dtw.html

as a function to be called by my code. An example:

#time warping sound function trial

import numpy as np
import matplotlib.pyplot as plt
from pylab import *

my_path ='/home/...'
def time_warping (x,y,fs,name):

    distances             = np.zeros((len(y), len(x)))
    accumulated_cost      = np.zeros((len(y), len(x)))
    accumulated_cost[0,0] = distances[0,0]

    def distance_cost_plot(distances):
                #function to visualize the distance matrix      
        im = plt.imshow(distances, interpolation='nearest', cmap='Reds') 
        plt.gca().invert_yaxis()
        plt.xlabel("X")
        plt.ylabel("Y")
        plt.grid()
        plt.colorbar();
        #plt.show()
        plt.close()

    def path_cost(x, y, accumulated_cost, distances):
        #this is like mlpy.dtw_std (I gues..)
        path = [[len(x)-1, len(y)-1]]
        cost = 0
        i = len(y)-1
        j = len(x)-1
        while i>0 and j>0:
            if i==0:
                j = j - 1
            elif j==0:
                i = i - 1
            else:
                if accumulated_cost[i-1, j] == min(accumulated_cost[i-1, j-1], accumulated_cost[i-1, j], accumulated_cost[i, j-1]):
                    i = i - 1
                elif accumulated_cost[i, j-1] == min(accumulated_cost[i-1, j-1], accumulated_cost[i-1, j], accumulated_cost[i, j-1]):
                    j = j-1
                else:
                    i = i - 1
                    j= j- 1
            path.append([j, i])
        path.append([0,0])
        for [y, x] in path:
            cost = cost +distances[x, y]
        return path, cost

    #Here I apply the function over function x and y
    path, cost = path_cost(x, y, accumulated_cost, distances)   

    for i in range(len(y)):
        for j in range(len(x)):
            distances[i,j] = (x[j]-y[i])**2

    #Here I plot the distance   
    g=distance_cost_plot(distances)

    accumulated_cost      = np.zeros((len(y), len(x)))
    accumulated_cost[0,0] = distances[0,0]

    for i in range(1, len(y)):
        accumulated_cost[i,0] = distances[i, 0] + accumulated_cost[i-1, 0]
    for i in range(1, len(x)):
        accumulated_cost[0,i] = distances[0,i] + accumulated_cost[0, i-1] 
    for i in range(1, len(y)):
        for j in range(1, len(x)):
            accumulated_cost[i, j] = min(accumulated_cost[i-1, j-1], accumulated_cost[i-1, j], accumulated_cost[i, j-1]) + distances[i, j]

    #empy list for the maping

    map_x_final   =[]
    map_y_final   =[]
    map_x_f_final =[]
    map_y_f_final =[]

    paths         = path_cost(x, y, accumulated_cost, distances)[0] #no entiendo la sintaxis de esta linea

    print 'path',paths
    print 'accumulated_cost',accumulated_cost
    print 'distances',distances

    #print 'paths.shape',path.shape

    plt.figure(figsize=(14,8)) # 8 plots in one
    plt.subplot(2,1,1)
    grid(True)

    map_x_fx         =[]
    map_y_fy         =[]        
        map_y_fy_newlist =[]
    for [map_x, map_y] in paths:

        #print map_x, x[map_x], ":", map_y, y[map_y]

        plt.plot([map_x*float(1)/float(fs), map_y*float(1)/float(fs)], [x[map_x], y[map_y]], 'r')
        #plt.plot([map_x, map_y], [x[map_x], y[map_y]], 'r')

        #saving in empy list        

        map_x_fx.append([map_x,x[map_x]])
            map_y_fy.append([map_x,y[map_y]])

        map_x_final.append(map_x)
        map_y_final.append(map_y)

        map_x_f_final.append(x[map_x])
        map_y_f_final.append(y[map_y])

        dif_a_sumar = (map_y-map_x)*float(1)/float(fs)      

    map_x_final     = np.asarray(map_x_final)
    map_y_final     = np.asarray(map_y_final)
    map_x_f_final   = np.asarray(map_x_f_final)
    map_y_f_final   = np.asarray(map_y_f_final)

    ####
    map_x_final_vec     = np.asarray(map_x_fx)
    map_y_final_vec     = np.asarray(map_y_fy)

    #Erase the elements that has been alrady map

    lista_aux=[]
    for j,[a,b] in enumerate(map_y_fy):
        print j,':', [a,b]
        print  len( map_x_final[:j])
        if a not in map_x_final[:j]:
            lista_aux.append([a,b])
        else:
            pass  
    print'++++++'
    print'lista aux len: ',len(lista_aux)

    map_y_final_vec_    =np.asarray(lista_aux)

    print'++++'
    print 'map_y_fy',len(map_y_fy)
    print'*************************'
    #print ' a veer map_x_fx: ',map_x_fx
    #print ' a veer map_x_fx type: ',type(map_x_fx)
    #print ' map_y_f_final_vec shape',map_y_f_final_vec.shape
    #print ' a veer map_x_final_vec: ',map_x_final_vec
    #print ' a veer map_x_final_vec[0]: ',map_x_final_vec[0]
    print'*************************'
    print 'x shape',x.shape
    print 'y shape',y.shape
    print 'map_x_f_final',map_x_f_final.shape
    print 'map_y_f_final',map_y_f_final.shape

    print 'map_y_final_vec shape',map_y_final_vec.shape
    print 'map_y_final_vec_ shape',map_y_final_vec_.shape
    print'*************************'

    #print map_x_final.size, map_y_final.size, map_x_f_final.size, map_y_f_final.size

    time_x     = np.arange(x.size)*float(1)/float(fs)
    time_y     = np.arange(y.size)*float(1)/float(fs)
        time_map_x = np.arange(map_x_f_final.size)*float(1)/float(fs)
    time_map_y = np.arange(map_y_f_final.size)*float(1)/float(fs)

    plt.plot(time_x,x, 'bo-',linewidth=1 ,label='funcion target: X ')#'bo-'
    plt.plot(time_y,y, 'go-',linewidth=1,markersize=3, label = 'funcion a proyectar :Y')#'g^-'

    plt.legend(fontsize= 'small')       
    plt.ylabel('Signal')
    plt.xlabel('time [s]') 
    plt.subplot(2,1,2) #los graficos mapeados
    grid(True)

    plt.plot(time_x,x, 'b',linewidth=1 ,label='funcion target: X sonido-vs')#o-
    plt.plot(time_y,y, 'g',linewidth=1,markersize=3, label = 'funcion a proyectar :Y sonido-p')#'g^-'

    plt.plot(map_y_final_vec_[:, 0]*float(1)/float(fs), map_y_final_vec_[:,1],'yo-',markersize=5, label='funcion Y mapeada donde convergen con DTW sobre X')#'m^'
    plt.ylabel('Signal')
    plt.xlabel('time [s]')          
    plt.legend(fontsize= 'small')       
    figname = "%s.jpg"%('alineado_dtw_'+name)
    plt.savefig(my_path+figname,dpi=200)    
    #plt.show()
        plt.close()
    mapeo_time      = map_y_final_vec_[:, 0]*float(1)/float(fs)
    mapeo_amplitude =  map_y_final_vec_[:,1]

    return mapeo_time, mapeo_amplitude

I am able to obtain the distance between both signals: But I'm not sure with the final mapping. Am I doing something wrong with my mapping? I need to project one signal over the other, rescaling the first one with the other. I also tried with these two real signals: I try to compare with:https://pypi.python.org/pypi/fastdtw and also with mlp library, but I get different signal mapping.

I also put everything on https://github.com/katejarne/dtw with the data set to generate the last figure and the mapping.

来源:https://stackoverflow.com/questions/36152229/dynamic-time-warping-with-python-final-mapping

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!