特征转移的核心 是 AdaIN
AdaIN 函数(实例归一化特征转移):
//自适应实例正则化 内容 和 风格 深度(维度)必须相同,宽,高可以不同
void AdaIN(卷积层 & 内容,卷积层 & 风格)
{
if(内容.depth != 风格.depth)
cout<<"出错了!内容和风格的维度必须相同!"<<endl;
vl_Norm(&内容); //AdaIN 的括号内部分 <--------这里
float eps = 1e-5f;
float u, std;// 均值 方差
float * s =风格.data;
float * n =内容.data;
float p;
int WH = 风格.height * 风格.width;
int wh = 内容.height * 内容.width;
for (int c=0; c<风格.depth; ++c)//对每个通道分别计算和处理
{
//先求均值
u=0;
std=0;
for (int i=0; i<WH; ++i)
{
p = *s++;
u += p;//和
std += p*p;//平方
}
u /= WH; //均值
std=sqrt(std/WH-u*u+eps);//方差
for (int i=0; i<wh; ++i)
{
p = *n;
*n++ = p*std+u; //AdaIN 的括号外部分 <--------这里
}
}
}
这部分只要维度相同就可以了,宽,高可以不同
下面的风格控制,则除维度必须相同,宽,高也要相同。
风格控制:
// 目标特征 = 目标特征 * 混合比 + (1 - 混合比) * 内容特征
void 风格控制(卷积层 & 内容特征,卷积层 & 目标特征,float alpha)
{
int WHD = 内容特征.height * 内容特征.width*内容特征.depth;
float * s = 内容特征.data;
float * d = 目标特征.data;
for (int c=0; c<WHD; ++c)//对每个通道每个点作相同处理
{
*d++ = alpha * (*d) + (1 - alpha) * (*s++);
}
}
混合比0.5 的效果:
修改后,基本达到《AdaIN-style-master》的效果,
上面是decoder-content-similar.t7生成的。
还有decoder.t7生成:
这个是按风格图来的。
AdaIN 函数并不要求内容和风格图像一样大小,所以在混合比 1.0 时,可以不用正方形图:
void Resizeloadjpg(char * jpgname)
{
#if 1
loadimage(&jpg,jpgname,0,0,true);//
int w=jpg.getwidth();
int h=jpg.getheight();
//大于512则缩小到512
int maxwh=max(w,h);
if (maxwh>512)
{
float s=((float)maxwh)/512.0f;
w=(int)(((float)w)/s);
h=(int)(((float)h)/s);
}
//把图像处理成8的倍数,去掉余数
w=(w-w % 8);
h=(h-h % 8);
loadimage(&jpg,jpgname,w,h,true);
#else
loadimage(&jpg,jpgname,512,512);//正方形
//loadimage(&jpg,jpgname,224,224);//
#endif
}
为了美观一点人上身部分用原图ps了一下
下载:
可以使用任意风格图的风格转换程序
使用AdaIN-style 的模型编译的win32风格转换程序,可以使用任意你自己的风格图来转换,有两种转换方式和混合比。是ps图像的利器。
https://download.youkuaiyun.com/download/juebai123/11002200
结束。
--------------------------分隔线----------------------------------------------
如果你下载后,觉得这个转换程序还可以,只是换风格图有点麻烦:
可以到后面的《黑白图像自动上色(颜色迁移版)》一文的下载,其中有一个简单的换图工具,也可以用在这里。