tf17: “声音大挪移”

来源:互联网 发布:经典英文电影片段知乎 编辑:程序博客网 时间:2024/04/25 19:19

看见本帖标题,你可能会问:“声音大挪移”是什么鬼玩意,和张无忌有什么关系。

如果你没看过鬼畜,先温习两个:【元首】粉红的回忆、【圣地亚哥金曲】客官不可以。(本帖内容和鬼畜关系不大)

前文《实现谷歌Deep Dream》可生成带有艺术感的图片。其实,还有另一种合成图片的方式,洋文叫Style Transfer,这种方法需要用到两张图片,如下图:

皮特  + picasso_selfport1907 = pitt_picasso_content_5_style_10
皮特 + Style = 皮特 Style

Style Transfer的原始论文:https://arxiv.org/abs/1508.06576;基于Torch的代码实现:neural-style

本帖只是在音频上应用Style Transfer,应该能生成非常搞笑的玩意。

代码:

[python] view plain copy
  1. import tensorflow as tf  
  2. import librosa  # 用来提取音频文件, 参看<中文语音识别>  
  3. import numpy as np  
  4. import os  
  5. #import shlex  # python2 pipes  
  6.    
  7. # 音频文件路径  
  8. content_audio = "./Traveling_Light.mp3"  
  9. style_audio = "./东风破.mp3"  
  10. # 为洋文歌曲<Traveling Light>添加周杰伦风味  
  11.    
  12. # 剪辑一段音频, 默认取开头的10s, 太大内存吃不消  
  13. def cut_audio(filename, start_pos='00:00:00', lens=10):  
  14.     newfile = os.path.splitext(os.path.basename(filename))[0] + '_' + str(lens) + 's.mp3'  
  15.     # 确保系统中已安装ffmpeg  
  16.     cmd = "ffmpeg -i {} -ss {} -t {} {}".format(filename, start_pos, lens, newfile)  
  17.     os.system(cmd)  
  18.     return newfile  
  19.    
  20. content_audio_10s = cut_audio(content_audio, start_pos='00:00:33')  
  21. style_audio_10s = cut_audio(style_audio, start_pos='00:00:38')  
  22.    
  23. # Short Time Fourier Transform音频转spectrogram(把1维信号转为2维, 可以被视作图像)  
  24. # https://en.wikipedia.org/wiki/Short-time_Fourier_transform  
  25. N_FFT = 2048  
  26. def read_audio(filename):  
  27.     x, fs = librosa.load(filename)  
  28.     S = librosa.stft(x, N_FFT)  
  29.     p = np.angle(S)  
  30.    
  31.     S = np.log1p(np.abs(S[:,:430]))  
  32.     return S, fs  
  33.    
  34. content_data, _ = read_audio(content_audio_10s)  
  35. style_data, fs = read_audio(style_audio_10s)  
  36.    
  37. samples_n = content_data.shape[1]  # 430  
  38. channels_n = style_data.shape[0]   # 1025  
  39.    
  40. style_data = style_data[:channels_n, :samples_n]  
  41.    
  42. content_data_tf = np.ascontiguousarray(content_data.T[None,None,:,:])  
  43. style_data_tf = np.ascontiguousarray(style_data.T[None,None,:,:])  
  44.    
  45. # filter shape "[filter_height, filter_width, in_channels, out_channels]"  
  46. N_FILTERS = 4096  
  47. std = np.sqrt(2) * np.sqrt(2.0 / ((channels_n + N_FILTERS) * 11))  
  48. kernel = np.random.randn(111, channels_n, N_FILTERS)*std  
  49.    
  50. # content and style features  
  51. g = tf.Graph()  
  52. with g.as_default(), g.device('/cpu:0'), tf.Session() as sess:  
  53.     # data shape "[batch, in_height, in_width, in_channels]",  
  54.     x = tf.placeholder('float32', [11, samples_n, channels_n], name="x")  
  55.    
  56.     kernel_tf = tf.constant(kernel, name="kernel", dtype='float32')  
  57.     conv = tf.nn.conv2d(x, kernel_tf, strides=[1111], padding="VALID", name="conv")  
  58.    
  59.     net = tf.nn.relu(conv)  
  60.    
  61.     content_features = net.eval(feed_dict={x: content_data_tf})  
  62.     style_features = net.eval(feed_dict={x: style_data_tf})  
  63.    
  64.     features = np.reshape(style_features, (-1, N_FILTERS))  
  65.     style_gram = np.matmul(features.T, features) / samples_n  
  66.    
  67. # Optimize  
  68. ALPHA= 0.01   # ALPHA越大,content越占主导; 如果ALPHA为0,表示没有content  
  69. result = None  
  70. with tf.Graph().as_default():  
  71.     learning_rate= 0.001  
  72.     x = tf.Variable(np.random.randn(11, samples_n, channels_n).astype(np.float32)*learning_rate, name="x")  
  73.     kernel_tf = tf.constant(kernel, name="kernel", dtype='float32')  
  74.     conv = tf.nn.conv2d(x, kernel_tf, strides=[1111], padding="VALID", name="conv")  
  75.    
  76.     net = tf.nn.relu(conv)  
  77.    
  78.     content_loss = ALPHA * 2 * tf.nn.l2_loss(net - content_features)  
  79.     style_loss = 0  
  80.    
  81.     _, height, width, number = map(lambda i: i.value, net.get_shape())  
  82.    
  83.     size = height * width * number  
  84.     feats = tf.reshape(net, (-1, number))  
  85.     gram = tf.matmul(tf.transpose(feats), feats)  / samples_n  
  86.     style_loss = 2 * tf.nn.l2_loss(gram - style_gram)  
  87.    
  88.     # loss  
  89.     loss = content_loss + style_loss  
  90.     opt = tf.contrib.opt.ScipyOptimizerInterface(loss, method='L-BFGS-B', options={'maxiter'300})  
  91.    
  92.     # Optimization  
  93.     with tf.Session() as sess:  
  94.         sess.run(tf.global_variables_initializer())  
  95.         opt.minimize(sess)  
  96.         result = x.eval()  
  97.    
  98. # 把spectrogram转回wav音频  
  99. audio = np.zeros_like(content_data)  
  100. audio[:channels_n,:] = np.exp(result[0,0].T) - 1  
  101.    
  102. p = 2 * np.pi * np.random.random_sample(audio.shape) - np.pi  
  103. for i in range(500):  
  104.     S = audio * np.exp(1j*p)  
  105.     x = librosa.istft(S)  
  106.     p = np.angle(librosa.stft(x, N_FFT))  
  107.    
  108. librosa.output.write_wav("output.mp3", x, fs)  

生成的文件:output.mp3

相关资源

  • https://github.com/DmitryUlyanov/neural-style-audio-torch
  • https://github.com/anishathalye/neural-style
  • https://gitxiv.com/posts/jG46ukGod8R7Rdtud/a-neural-algorithm-of-artistic-style
  • https://gist.github.com/genekogan/d61c8010d470e1dbe15d

原创粉丝点击