携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第33天,点击查看活动详情
项目需求
趁着双休,有属于自己的时间了,赶紧给自己做几张“搞怪”画风照片(本文后面会附上照片),现在需求如下:
- 输入自己的照片;
- 通过某种手段可以获得到比较搞怪画风的照片;
- 这种手段具备一定的泛化能力。
注意事项: 本文着重于实践操作,不过讲解源理,望见晾!
需求分析
上述需求不禁让我想起了初学GAN时候的风格迁移网络,该类型的网络可以正好满足上述需求,于是自己在网上搜刮下来了一些训练好的权重给自己使用。(双休在家,无GPU训练)
实践步骤逻辑:
- CV读取图像;
- 读取网络Net;
- 调整图像的尺寸和格式;
- 计算网络对原图像处理的结果;
- 输出结果的尺寸和通道数;
- 将输出结果存放到图像中去;
- 获取原图像的通道数及均值;
- 恢复图像剔除掉的均值;
- 对输出图像进行归一化;
- 显示结果搞怪图
实践调试
在电脑里面找到了自己以前做人脸检测的样图,现在正好可以拿来使用以下: 在centos7中运行如下代码,创建CMakeLists.txt 进行cmake和make即可获取下面的图像。
#include <opencv2/opencv.hpp>
#include <iostream>
#include<vector>
#include<string>
using namespace cv;
using namespace cv::dnn;
using namespace std;
int main()
{
Mat image = imread("/home/kiven/Demo/Imgs/lena.png");
String models[5] = { "Net1.t7","Net2.t7","Net3.t7","Net4.t7","Net5.t7" };
for (int i = 0; i < 5; i++)
{
Net net = readNet(models[i]);
Scalar imgaeMean = mean(image);
Mat blobImage = blobFromImage(image, 1.0, Size(256, 256), imgaeMean, false, false);
net.setInput(blobImage);
Mat output = net.forward();
int outputChannels = output.size[1];
int outputRows = output.size[2];
int outputCols = output.size[3];
Mat result = Mat::zeros(Size(outputCols, outputRows), CV_32FC3);
float* data = output.ptr<float>();
for (int channel = 0; channel < outputChannels; channel++)
{
for (int row = 0; row < outputRows; row++)
{
for (int col = 0; col < outputCols; col++)
{
result.at<Vec3f>(row, col)[channel] = *data++;
}
}
}
result = result + imgaeMean;
result = result / 255.0;
resize(result, result, image.size());
//显示结果
string OutImgName = format("/home/kiven/Demo/SaveImgs/%d.jpg", i);
imwrite(OutImgName, result);
}
return 0;
}