C++实现AdaIN 风格转换(一)编码、解码器 和 主流程

前面,材料已经准备得差不多了,现在可以开始。

首先是编码器,就是一个'预处理卷积'+VGG19的开头到 relu4-1 层。

'预处理卷积' 等同'@./helpers/preprocess.lua',

这个文件 <fast-neural-style-master>中有:

M.vgg = {}

local vgg_mean = {103.939, 116.779, 123.68}

--[[
在传递给VGG模型之前预处理图像。我们需要重新缩放
[0,1]到[0,255],从RGB转换为BGR,并减去平均值。

输入:
- img:形状张量(N,C,H,W)给出一批图像。图片
]]
function M.vgg.preprocess(img)
  check_input(img)
  local mean = img.new(vgg_mean):view(1, 3, 1, 1):expandAs(img)
  local perm = torch.LongTensor{3, 2, 1}
  return img:index(2, perm):mul(255):add(-1, mean)
end

从这里看出需要[0,1]的RGB数据。

编码器定义:

struct 编码器 //由 Vgg19 的 relu4-1 层输出
{

	层数据 * PreprocessConv;//1 预处理卷积层
	层数据 * Conv1;//2 //组
	层数据 * Conv2;//2
	层数据 * Conv3;//4
	层数据 * Conv4;//1

	
	//构造函数
	编码器();

};

编码器::编码器()
{

	int size;
	层数据 * 层;

	//用于一层(宏)
	/*输入维度,输出维度,核宽*/
	#define 初始化ONE层(IN,OUT,KW) \
	\
	层->输入维度=IN;\
	层->输出维度=OUT;\
	层->核宽=KW;\
	层->权重长度=层->输出维度*层->输入维度*层->核宽*层->核宽;\
	层->权重_数据=(float*)malloc(sizeof(float) * 层->权重长度);\
	层->偏移长度=层->输出维度;\
	层->偏移_数据=(float*)malloc(sizeof(float) * 层->偏移长度);\
\
	层++;\

	//用于一组(宏)
	/*组名称,输入维度,输出维度,核宽,组中层数*/
	#define 初始化层(ConvX,IN,OUT,KW,Num) \
	size = sizeof(层数据)*Num;\
\
	层=ConvX =(层数据 *)malloc(size);\
	初始化ONE层(IN,OUT,KW)\
	for (int i=0;i<Num-1 ;i++ )\
	{\
		初始化ONE层(OUT,OUT,KW)\
	}\

	//预处理层
	/*名称,输入维度,输出维度,核宽,组中层数*/
	初始化层(PreprocessConv,3,3,1,1)

	//Conv1: 2层
	初始化层(Conv1,3,64,3,2) 

	//Conv2: 2层
	初始化层(Conv2,64,128,3,2)

	//Conv3: 4层
	初始化层(Conv3,128,256,3,4)

	//Conv4: 4层
	初始化层(Conv4,256,512,3,1)

}

解码器:

struct 解码器 //输入层 维度,大小 由 Vgg19 的 relu4-1 层输出 决定
{
    //组

	层数据 * Conv1;//1
	层数据 * Conv2;//4
	层数据 * Conv3;//2
	层数据 * Conv4;//2

	
	//构造函数
	解码器();

};

解码器::解码器()
{
	int size;
	层数据 * 层;

	#define 初始化解层(ConvX,IN,OUT,KW,Num) \
	size = sizeof(层数据)*Num;\
\
	层=ConvX =(层数据 *)malloc(size);\
	for (int i=0;i<Num-1 ;i++ )\
	{\
		初始化ONE层(IN,IN,KW)\
	}\
	初始化ONE层(IN,OUT,KW)\
	//Conv1: 1层
	/*名称,输入维度,输出维度,核宽,组中层数*/
	初始化解层(Conv1,512,256,3,1) 

	//Conv2: 4层
	初始化解层(Conv2,256,128,3,4)

	//Conv3: 2层
	初始化解层(Conv3,128,64,3,2)

	//Conv4: 2层
	初始化解层(Conv4,64,3,3,2)
}

主流程:

1。内容图-->编码-->内容特征,

2。风格图-->编码-->风格特征,

3。内容特征,风格特征-->AdaIN-->目标特征,

4。目标特征 * 混合比 + (1 - 混合比) * 内容特征-->混合特征,(风格控制)

5。混合特征-->解码-->风格图。

C++主流程:

	//载入图片
	//缩放至 512x512 的图像 (VGG19 分类 224x224)
	Resizeloadjpg(jpgname);//也可以原始大小,但不能太小,不然池化后...,太大费时.


	编码器 encoder;

	//从t7模型文件加载数据
	loadt7Model(&encoder);

   //取得特征层  (图像由全局变量jpg输入)
	卷积层 * content=vgg(encoder);

	卷积层 content_copy(content->width,content->height,content->depth);
	content_copy.data=new float[content_copy.width*content_copy.height*content_copy.depth];
	卷积层复制(content,&content_copy);

	//载入风格图
	Resizeloadjpg(Style_Name);
	卷积层 * style=vgg(encoder);

	AdaIN(*content,* style);

	float alpha=0.5f;//混合比
	风格控制(content_copy,*content,alpha);

	解码器 decoder;	
	


	//loadModel(&decoder);//文本载入
	//saveModel2进制(&decoder);//二进制保存

	loadModel2进制(&decoder);//二进制载入

		
	//生成风格图
	Decoding("Adain-style", decoder,content);//保存输出风格名称,解码器参数,输入
    	//save_卷积层2jpg(style,);

效果图:

 

生成512x512,需要56秒。

这部分结束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值