tf27: Deep Dream—应用到视频

本帖就基于前一贴的代码在视频上应用Deep Dream,应该能生成比较抽的视频。

代码逻辑:

  1. 使用ffmpeg从视频中提取帧
  2. 为每一帧图像应用Deep Dream
  3. 使用ffmpeg把帧图像重新组合成视频,最后和音频合并
  • 生成的视频效果(https://youtu.be/Sy9PXSXfEOA)
  • 原始视频:http://www.bilibili.com/video/av7336429

撇脚的代码:

# -*- coding: utf-8 -*-
# 斗大的熊猫 <blog.topspeedsnail.com>
 
import tensorflow as tf
import numpy as np
import cv2
import sys
import os
import argparse
import shutil
 
inception_model = 'tensorflow_inception_graph.pb'
 
# 加载模型
graph = tf.Graph()
sess = tf.InteractiveSession(graph=graph)
 
X = tf.placeholder(np.float32, name='input')
with tf.gfile.FastGFile(inception_model, 'rb') as f:
	graph_def = tf.GraphDef()
	graph_def.ParseFromString(f.read())
imagenet_mean = 117.0
preprocessed = tf.expand_dims(X-imagenet_mean, 0)
tf.import_graph_def(graph_def, {'input':preprocessed})
 
layers = [op.name for op in graph.get_operations() if op.type=='Conv2D' and 'import/' in op.name]
feature_nums = [int(graph.get_tensor_by_name(name+':0').get_shape()[-1]) for name in layers]
 
print('layers:', len(layers))   # 59
print('feature:', sum(feature_nums))  # 7548
 
def tffunc(*argtypes):
	placeholders = list(map(tf.placeholder, argtypes))
	def wrap(f):
		out = f(*placeholders)
		def wrapper(*args, **kw):
			return out.eval(dict(zip(placeholders, args)), session=kw.get('session'))
		return wrapper
	return wrap
def resize(img, size):
	img = tf.expand_dims(img, 0)
	return tf.image.resize_bilinear(img, size)[0,:,:,:]
 
# 选择层
layer = 'mixed4c'
resize = tffunc(np.float32, np.int32)(resize)
score = tf.reduce_mean(tf.square(graph.get_tensor_by_name("import/%s:0"%layer)))
gradi = tf.gradients(score, X)[0]
# Deep Dream
def deep_dream(img_noise, iter_n=10, step=1.5, octave_n=4, octave_scale=1.4):
 
	img = img_noise
	octaves = []
 
	for _ in range(octave_n-1):
		hw = img.shape[:2]
		lo = resize(img, np.int32(np.float32(hw)/octave_scale))
		hi = img-resize(lo, hw)
		img = lo
		octaves.append(hi)
        # tile
	def calc_grad_tiled(img, t_grad, tile_size=512):
		sz = tile_size
		h, w = img.shape[:2]
		sx, sy = np.random.randint(sz, size=2)
		img_shift = np.roll(np.roll(img, sx, 1), sy, 0)
		grad = np.zeros_like(img)
		for y in range(0, max(h-sz//2, sz),sz):
			for x in range(0, max(w-sz//2, sz),sz):
				sub = img_shift[y:y+sz,x:x+sz]
				g = sess.run(t_grad, {X:sub})
				grad[y:y+sz,x:x+sz] = g
		return np.roll(np.roll(grad, -sx, 1), -sy, 0)   
 
	res = None
	for octave in range(octave_n):
		if octave > 0:
			hi = octaves[-octave]
			img = resize(img, hi.shape[:2])+hi
		for _ in range(iter_n):
			g = calc_grad_tiled(img, gradi)
			img += g*(step / (np.abs(g).mean()+1e-7))
 
		res = img
	return res
#####################################
 
parser = argparse.ArgumentParser(description='Deep Video Videos.')
parser.add_argument('-i','--input', help='inupt mp4 Video File Path', required=True)
parser.add_argument('-o','--output', help='output mp4 Video File Path', required=True)
 
args = parser.parse_args()
print(args)
 
if not os.path.exists(args.input):
	print("please input video")
	sys.exit(0)
 
# 我使用ffmpeg把视频转为帧
def video_to_frames(video_path, frames_path):
	if not os.path.exists(frames_path):
		os.makedirs(frames_path)
		output_file = frames_path + "/%08d.jpg"
		print("ffmpeg -i {} -f image2 {}".format(video_path, output_file))
		os.system("ffmpeg -i {} -f image2 {}".format(video_path, output_file))
 
# 临时目录
tmp_path = './tmp'
 
if not os.path.exists(tmp_path):
	os.makedirs(tmp_path)
	video_to_frames(args.input, tmp_path+'/frames_input')
	# deep dream每一帧
	frames =[name for name in os.listdir(tmp_path+'/frames_input') if os.path.isfile(os.path.join(tmp_path+'/frames_input', name))]
	frames.sort()
	print("要处理的帧数:", len(frames))
	for frame in frames:
		print('正在转换: ', frame)
		img_frame = cv2.imread(tmp_path+'/frames_input/' + frame)
		img = deep_dream(img_noise=img_frame)
		if not os.path.exists(tmp_path+'/frames_output'):
			os.makedirs(tmp_path+'/frames_output')
		cv2.imwrite(tmp_path+'/frames_output/' + frame, img)
else:
	print("TODO: 从前一次退出的地方继续执行")
 
# TODO: 使用ffmpeg把帧转回视频
"""
# 帧率
ffprobe -show_streams -select_streams v -i args.input 2>/dev/null | grep "r_frame_rate" | cut -d'=' -f2
ffmpeg -framerate [FPS] -i ./tmp/frames_output/%08d.jpg -c:v libx264 -vf "fps=[FPS],format=yuv420p" -tune fastdecode -tune zerolatency -profile:v baseline ./tmp/tmp.mp4 -y
ffmpeg -i args.input -strict -2 ./tmp/tmp.aac -y
ffmpeg -i ./tmp/tmp.aac -i ./tmp/tmp.mp4 -strict -2 -c:v copy -movflags faststart -shortest args.output
"""
 
#shutil.rmtree(tmp_path)
 
# 啊, 代码真够烂

自行尝试使用不同的layer和参数组合。

后续练习:把Styler Transfer应用到视频上

ps. Python 3.6已正式发布

Share the post "TensorFlow练习21: 把Deep Dream应用到视频上"

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏刘望舒

算法(一)时间复杂度

前言 算法很重要,但是一般情况下做移动开发并不经常用到,所以很多同学早就将算法打了个大礼包送还给了老师了,况且很多同学并没有学习过算法。这个系列就让对算法头疼的...

1978
来自专栏趣学算法

数据结构 第2讲 算法复杂性

该内容来源于本人著作《趣学算法》在线章节:http://www.epubit.com.cn/book/details/4825

1242
来自专栏WOLFRAM

用 Mathematica 生成正多面体链环

3327
来自专栏BestSDK

目前深度学习最强框架——PyTorch

PyTorch由于使用了强大的GPU加速的Tensor计算(类似numpy)和基于磁带的自动系统的深度神经网络。这使得今年一月份被开源的PyTorch成为了深度...

5575
来自专栏封碎

当今世界最为经典的十大算法 博客分类: 经典文章转载 算法数据结构网络应用数据挖掘J#

本文转载自July CSDN博客:http://blog.csdn.net/v_JULY_v/archive/2011/03/07/6228235.aspx

2272
来自专栏趣学算法

算法之美——算法复杂性

《趣学算法》在线章节:http://www.epubit.com.cn/book/details/4825

2851
来自专栏程序员宝库

码农也要学算法

当“人工智能”、“AlphaGo”、“无人驾驶”、“智能投顾”等词语不断在人们视野中出现的时候,意味着我们正步入一个算法的时代。计算机通过提供给人类每天要面临的...

49210
来自专栏小樱的经验随笔

模拟退火算法从原理到实战【基础篇】

  模拟退火算法来源于固体退火原理,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达...

4206
来自专栏互联网大杂烩

机器学习面试

线性回归的因变量是连续变量,自变量可以是连续变量,也可以是分类变量。如果只有一个自变量,且只有两类,那这个回归就等同于t检验。如果只有一个自变量,且有三类或更多...

1104
来自专栏AI研习社

问答 | 如何理解 NVIDIA 新 GPU 架构 Turing 的 Tensor Core?

问:如何理解 NVIDIA 新 GPU 架构 Turing 的 Tensor Core?

1954

扫码关注云+社区

领取腾讯云代金券