项目需求
趁着双休,有属于自己的时间了,赶紧给自己做几张“搞怪”画风照片(本文后面会附上照片),现在需求如下:
- 输入自己的照片;
- 通过某种手段可以获得到比较搞怪画风的照片;
- 这种手段具备一定的泛化能力。
注意事项: 本文着重于实践操作,不过讲解源理,望见晾!
需求分析
上述需求不禁让我想起了初学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; } 复制代码