哪个上采样层实际上并不是用反卷积来实现的,从超分辨重建部分知道,反卷积相当于插零值+卷积。
这里用邻近插值4倍放大+步长为2的卷积(2倍缩小) 代替 2倍放大的反向卷积 : 4-2=2
邻近插值放大 从博文《最近邻内插值与双线性插值》拿来修改一下在这里使用:
//最近邻插值
void NearestInsert(const float *OriImage_c, int OriWidth, int OriHeight,float *OutImage_c, int Width, int Height)
{
double fx = (double)OriHeight / (double)Height;//height方向上的比值
double fy = (double)OriWidth / (double)Width;//width方向上的比值
for (int x = 0; x < Height; x++)
{
for(int y = 0; y < Width; y++)
{
int out = x * Width + y ;
int ori = (int)(fx * x) * OriWidth + (int)(fy * y) ;
OutImage_c[out] = OriImage_c[ori];
}
}
}
这是一个通道插值(已去掉原方法中的多通道插值<混合数据,我们这里是分离的>)
再用到我们这里:
void 最近邻插值(卷积层 & si,卷积层 & di)
{
int wh_s=si.width*si.height;
int wh_d=di.width*di.height;
for(int p=0;p<si.depth;p++)//每个通道分别插值
NearestInsert(si.data+ p * wh_s, si.width, si.height,di.data+p * wh_d, di.width, di.height);
}
加上步长2 的卷积会总:
void resize_conv2d(卷积层 & si,卷积层 & di,层数据 * 层)
{
int new_height = si.height*4;//height * strides * 2
int new_width = si.width*4;//width * strides * 2
卷积层 new_tmp(new_width,new_height,si.depth);//
new_tmp.data=new float[new_width*new_height*si.depth];
//x_resized = tf.image.resize_images(x,[new_height,new_width],tf.image.ResizeMethod.NEAREST_NEIGHBOR)
最近邻插值( si,new_tmp);
//return conv2d(x_resized,input_filters,output_filters,kernel,strides)
vl_nnconv(&new_tmp,&di,层 ,2,2,1,1,1,1);
del卷积层(new_tmp);
}
由于这里有点4倍放大,全部程序中这里用到内存最大
全部已经结束,如有未尽之处当在超分辨重建部分
mosaic风格模型效果图:
原图
转换图
再来一张:
原图
转换图
下载:
win32位编译的 mosaic图风格转换(style)
win32位编译的 风格转换(style)的应用程序,是mosaic风格模型,使用了OpenBLAS加速,详细情况参看博客
地址:
https://download.csdn.net/download/juebai123/10835972
其它6种风格图模型效果:
下载:
https://pan.baidu.com/s/1rudcbncxyfIl8UXqUv1CWA
下载后放到一起,用一个批文件(bat)切换(按说明)
结束。