服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++ AnimeGAN实现照片一键动漫化

C++ AnimeGAN实现照片一键动漫化

2022-03-05 17:29知来者逆 C/C++

AnimeGAN是是由神经网络风格迁移加生成对抗网络(GAN)而成,它是基于CartoonGAN的改进,并提出了一个更加轻量级的生成器架构。本文将介绍如何运用AnimeGAN实现照片一键动漫化,需要的可以参考一下

前言

AnimeGAN是来自武汉大学和湖北工业大学的AI项目,是由神经网络风格迁移加生成对抗网络(GAN)而成,它是基于CartoonGAN的改进,并提出了一个更加轻量级的生成器架构。原理和训练代码转GithubPytorch版本。官方的有放出三个试玩的模型,有两个模型是针对人脸的,有一个是卡通效果,可以用来试试别的图像的,熟悉python和pytorch的直接git下来就可以本地部署了,就可以试玩了。

先看看人像的效果

我的demo里面的图像第一张是原图,第二第三张是人像模型,第四张是卡通效果。

C++ AnimeGAN实现照片一键动漫化

C++ AnimeGAN实现照片一键动漫化

风景的效果:

C++ AnimeGAN实现照片一键动漫化

C++ AnimeGAN实现照片一键动漫化

我这里用的是C++,环境是Win10,VS2019,OpenCV4.5,用的推理库是ncnn-20210720, 要用到GPU,所以要下VulkanSDK,GPU 是GTX1650。

 

环境安装

1.安装Vulkan各它的依赖库。

Vulkan 

版本:VulkanSDK-1.2.141.2

直接点击安装,把之后验证是否安装成功,运行xxx\VulkanSDK\1.2.141.2\Bin\vkcube.exe,出现下面图像代表安装成功。

C++ AnimeGAN实现照片一键动漫化

glfw

https://www.glfw.org/

把glfw-3.3.2.bin.WIN64复制到VulkanSDK\1.2.141.2\Third-Party

GLM

https://github.com/g-truc/glm/

把GLM复制到VulkanSDK\1.2.141.2\Third-Party

添加系统环境变量

C++ AnimeGAN实现照片一键动漫化

3.下载NCNN,可以直接下载对应自己IDE的relese版本的,免得编译麻烦,下载地址。

4.下载OpenCV, 4.0以上就可以。

 

C++推理

1.先从 GitHub 下载权重文件。然后按官方给的文档和脚本转成onnx模型。转成onnx之后也可以有用onnxruntime进行推理,我这里又把onnx转ncnn的推理模型,ncnn带有模型转换脚本,直接转就行。

2.把ncnn库,OpenCV,VulkanSDK的lib都加vs的库依赖里,然后加上OpenCV和VulkanSDK的动态库环境变量,就可以开始撸代码了。

3.测试代码:

#include <opencv2/opencv.hpp>
#include <ncnn/gpu.h>
#include <ncnn/net.h>

//模型路径
std::string celeba_model = "models/Celeba.bin";
std::string celeba_param = "models/Celeba.param";
std::string face_v1_model = "models/FacePointV1.bin";
std::string face_v1_param = "models/FacePointV1.param";
std::string face_v2_model = "models/FacePointV2.bin";
std::string face_v2_param = "models/FacePointV2.param";

//读取模型
int readModels(ncnn::Net& ncnn_net, std::string param_path, std::string model_path, bool use_gpu = true);

//推理,target_w,target_h为推理尺寸,越往大的改,细节保留就越多,也越吃GPU算力
int animeInference(const ncnn::Net& ncnn_net, const cv::Mat& cv_src, cv::Mat& cv_dst,int target_w = 512, int target_h = 512)
{
  cv::Mat cv_backup = cv_src.clone();
  const int w = cv_src.cols;
  const int h = cv_src.rows;

  const float mean_vals[3] = { 127.5f, 127.5f,  127.5f };
  const float norm_vals[3] = { 1 / 127.5f, 1 / 127.5f, 1 / 127.5f };
  ncnn::Mat in = ncnn::Mat::from_pixels_resize(cv_backup.data, ncnn::Mat::PIXEL_BGR2RGB, w, h, target_w, target_h);
  in.substract_mean_normalize(mean_vals, norm_vals);
  ncnn::Mat out;
  
  ncnn::Extractor ex = ncnn_net.create_extractor();

  ex.input("input", in);
  ex.extract("out", out);
  
  cv::Mat result(out.h, out.w, CV_32FC3);
  for (int i = 0; i < out.c; i++)
  {
      float* out_data = out.channel(i);
      for (int h = 0; h < out.h; h++)
      {
          for (int w = 0; w < out.w; w++)
          {
              result.at<cv::Vec3f>(h, w)[2 - i] = out_data[h * out.h + w];
          }
      }
  }
  cv::Mat result8U(out.h, out.w, CV_8UC3);
  result.convertTo(result8U, CV_8UC3, 255.0/2, 255.0/2);
  result8U.copyTo(cv_dst);
  cv::resize(cv_dst, cv_dst, cv_src.size());
  return 0;
}

//调用,三种风格
int styletransferResult(const cv::Mat& cv_src, std::vector<cv::Mat>& cv_dsts, ncnn::Net& face_v1_net, ncnn::Net& face_v2_net, ncnn::Net& celeba_net)
{
  animeInference(face_v1_net, cv_src, cv_dsts.at(0));
  animeInference(face_v2_net, cv_src, cv_dsts.at(1));
  animeInference(celeba_net, cv_src, cv_dsts.at(2));

}

int main(int argc, char** argv)
{
	//图像路径
  std::string path = "images";
  std::vector<std::string> filenames;
  cv::glob(path, filenames, false);

  ncnn::Net face_v1_net, face_v2_net, celeba_net;

  readModels(face_v1_net, face_v1_param, face_v1_model);
  readModels(face_v2_net, face_v1_param, face_v1_model);
  readModels(celeba_net, celeba_param, celeba_model);

  for(auto v : filenames)
  {

      cv::Mat cv_src = cv::imread(v, 1);

      std::vector<cv::Mat> cv_dsts(3);

      double start = static_cast<double>(cv::getTickCount());
      styletransferResult(cv_src, cv_dsts, face_v1_net, face_v2_net, celeba_net);
      double time = ((double)cv::getTickCount() - start) / cv::getTickFrequency();
      std::cout << "time:" << time << "(s)" << std::endl;


      cv_src.push_back(cv_dsts.at(0));
      cv_dsts.at(1).push_back(cv_dsts.at(2));

      cv::Mat des;
      des.create(cv_src.rows, cv_src.cols*2, cv_src.type());
      cv::Mat r1 = des(cv::Rect(0, 0, cv_src.cols, cv_src.rows));
      cv_src.copyTo(r1);

      cv::Mat r2 = des(cv::Rect(cv_src.cols, 0, cv_src.cols,cv_src.rows));
      cv_dsts.at(1).copyTo(r2);

      imshow("style", des);
      cv::imwrite(std::to_string(j)+".jpg", des);
      
    // cv::waitKey();
  }
  return 0;
}

int readModels(ncnn::Net& ncnn_net,std::string param_path,std::string model_path, bool use_gpu)
{
  bool has_gpu = false;

#if NCNN_VULKAN
  ncnn::create_gpu_instance();
  has_gpu = ncnn::get_gpu_count() > 0;
#endif

  bool to_use_gpu = has_gpu && use_gpu;
  ncnn_net.opt.use_vulkan_compute = to_use_gpu;

  int rp = ncnn_net.load_param(param_path.c_str());

  int rb = ncnn_net.load_model(model_path.c_str());

  if (rp < 0 || rb < 0)
  {
      return 1;
  }
  return 0;
}

 

运行结果

C++ AnimeGAN实现照片一键动漫化

C++ AnimeGAN实现照片一键动漫化

C++ AnimeGAN实现照片一键动漫化

C++ AnimeGAN实现照片一键动漫化

C++ AnimeGAN实现照片一键动漫化

C++ AnimeGAN实现照片一键动漫化

5.跑起来很费GPU,如果有好一些的GPU,推理尺寸可以开大一点,细节的保留会更完整些,如果是前两种风格,图像尽量大于512*512,人像人脸特征明显,因为算法是基本于人脸关键点做的。

6.源码和可执行文件以上传到csdn,下载下来,把自己想试的图像放在images目录下,运行.exe文件,就可以在当前的得到最终合并的效果图像。源码下载地址可执行文件地址

 以上就是C++ AnimeGAN实现照片一键动漫化的详细内容,更多关于C++ AnimeGAN照片动漫化的资料请关注服务器之家其它相关文章!

原文链接:https://blog.csdn.net/matt45m/article/details/121504379?utm_medium=distribute.pc_category.none-task-blog-hot-8.nonecase&depth_1-utm_source=distribute.pc_category.none-task-blog-hot-8.nonecase

延伸 · 阅读

精彩推荐
  • C/C++c/c++内存分配大小实例讲解

    c/c++内存分配大小实例讲解

    在本篇文章里小编给大家整理了一篇关于c/c++内存分配大小实例讲解内容,有需要的朋友们可以跟着学习参考下。...

    jihite5172022-02-22
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth6912021-05-16
  • C/C++C语言实现双人五子棋游戏

    C语言实现双人五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现双人五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    两片空白7312021-11-12
  • C/C++使用C++制作简单的web服务器(续)

    使用C++制作简单的web服务器(续)

    本文承接上文《使用C++制作简单的web服务器》,把web服务器做的功能稍微强大些,主要增加的功能是从文件中读取网页并返回给客户端,而不是把网页代码...

    C++教程网5492021-02-22
  • C/C++c/c++实现获取域名的IP地址

    c/c++实现获取域名的IP地址

    本文给大家汇总介绍了使用c/c++实现获取域名的IP地址的几种方法以及这些方法的核心函数gethostbyname的详细用法,非常的实用,有需要的小伙伴可以参考下...

    C++教程网10262021-03-16
  • C/C++OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    iteye_183805102021-07-29
  • C/C++关于C语言中E-R图的详解

    关于C语言中E-R图的详解

    今天小编就为大家分享一篇关于关于C语言中E-R图的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Struggler095962021-07-12
  • C/C++深入C++拷贝构造函数的总结详解

    深入C++拷贝构造函数的总结详解

    本篇文章是对C++中拷贝构造函数进行了总结与介绍。需要的朋友参考下...

    C++教程网5182020-11-30