.net使用PaddleGAN模型使照片动漫化

paddleGAN是百度飞桨(‌PaddlePaddle)‌的一个图像生成开发套件,‌它集成了多种先进的算法和预训练模型,‌包括风格迁移、‌超分辨率、‌动漫画生成、‌图片上色、‌人脸属性编辑、‌妆容迁移等算法。

AnimeGANv2 照片动漫化

以下是paddleGAN在gitee上对AnimeGANv2的介绍与模型的训练和测试(docs/zh_CN/tutorials/animegan.md · PaddlePaddle/PaddleGAN - Gitee.com

1.1 原理介绍

AnimeGAN基于2018年CVPR论文CartoonGAN基础上对其进行了一些改进,主要消除了过度风格化以及颜色伪影区域的问题。对于具体原理可以参见作者知乎文章。AnimeGANv2是作者在AnimeGAN的基础上添加了total variation loss的新模型。

1.2 如何使用

1.2.1 快速体验

安装PaddleGAN之后运行如下代码即生成风格化后的图像output_dir/anime.png,其中PATH_OF_IMAGE为你需要转换的图像路径。

from ppgan.apps import AnimeGANPredictor
predictor = AnimeGANPredictor()
predictor.run(PATH_OF_IMAGE)

或者在终端中运行如下命令,也可获得相同结果:

python applications/tools/animeganv2.py --input_image ${PATH_OF_IMAGE}
1.2.2 数据准备

我们下载作者提供的训练数据,训练数据可以从这里下载。 下载后解压到data目录下:

wget https://github.com/TachibanaYoshino/AnimeGAN/releases/download/dataset-1/dataset.zip
cd PaddleGAN
unzip YOUR_DATASET_DIR/dataset.zip -d data/animedataset

解压完成后数据分布如下所示:

animedataset
├── Hayao
│   ├── smooth
│   └── style
├── Paprika
│   ├── smooth
│   └── style
├── Shinkai
│   ├── smooth
│   └── style
├── SummerWar
│   ├── smooth
│   └── style
├── test
│   ├── HR_photo
│   ├── label_map
│   ├── real
│   ├── test_photo
│   └── test_photo256
├── train_photo
└── val
1.2.3 训练

示例以训练Hayao风格的数据为例。

为了保证模型具备生成原图的效果,需要预热模型:

python tools/main.py --config-file configs/animeganv2_pretrain.yaml

预热模型完成后,训练风格迁移模型: 注意: 必须先修改在configs/animeganv2.yaml中的pretrain_ckpt参数,确保指向正确的 预热模型权重路径 设置batch size=4,learning rate=0.0002,在一个 GTX2060S GPU上训练30个epoch即可获得较好的效果,其他超参数请参考configs/animeganv2.yaml。

python tools/main.py --config-file configs/animeganv2.yaml

改变目标图像的风格 修改configs/animeganv2.yaml中的style参数即可改变风格(目前可选择Hayao,Paprika,Shinkai,SummerWar)。如果您想使用自己的数据集,可以在配置文件中修改数据集为您自己的数据集。

注意: 修改目标风格后,必须计算目标风格数据集的像素均值,并修改configs/animeganv2.yaml中的transform_anime->Add->value参数。

如下例子展示了如何获得Hayao风格图像的像素均值:

python tools/animegan_picmean.py --dataset data/animedataset/Hayao/style
image_num: 1792
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1792/1792 [00:04<00:00, 444.95it/s]
RGB mean diff
[-4.4346957 -8.665916  13.100612 ]
1.2.3 测试

测试模型:

python tools/main.py --config-file configs/animeganv2.yaml --evaluate-only --load ${PATH_OF_WEIGHT}

1.3 结果展示

c#封装

以上例子都是python的我们就用c#来封装一下,使用他已经转好的onnx模型。下面是模型所在的地址信息

c#效果图

以下是最终的效果展示

c#代码

下面是核心代码拿来就可以直接使用

public void SetPicture()
 {
     if (pictureBox1.Image == null)
     {
         MessageBox.Show("请先选择图片");
         return;
     }
     Bitmap bitmap = new Bitmap(pictureBox1.Image);
     Mat srcResize = bitmap.ToMat();
     Size size;
     Tensor<float> inputTensors = ProcessImage(srcResize.ToImage<Bgr, float>(), out size, true);

     var inputs = new List<NamedOnnxValue>
     {
         NamedOnnxValue.CreateFromTensor("generator_input:0", inputTensors)
     };

     SessionOptions opdeb = new SessionOptions();
     opdeb.GraphOptimizationLevel = GraphOptimizationLevel.ORT_ENABLE_EXTENDED;
     opdeb.InterOpNumThreads = 1;
     opdeb.IntraOpNumThreads = 1;

     using (InferenceSession debNets = new InferenceSession($@"{AppDomain.CurrentDomain.BaseDirectory}Shinkai_53.onnx"))
     {
         var sss = debNets.InputMetadata;
         IDisposableReadOnlyCollection<DisposableNamedOnnxValue> results = debNets.Run(inputs);
         {
             var resultsArray = results.ToArray();
             var predData = resultsArray[0].AsTensor<float>();
             var image = TensorToImage(predData, size);
             pictureBox2.Image = image.ToBitmap();
             srcResize.Dispose();


         }

     }

 }


 
 public static Tensor<float> ProcessImage(Image<Bgr, float> img, out Size size, bool x32 = true)
 {
     int h = img.Height;
     int w = img.Width;

     if (x32)
     {
         Func<int, int> to_32s = (int x) =>
         {
             return 256 > x ? 256 : x - x % 32;
         };
         img = img.Resize(to_32s(w), to_32s(h), Inter.Linear);
     }
     size = img.Size;
     Image<Bgr, float> processedImg = img / 127.5 - 1.0;

     var bitmap = processedImg.ToBitmap();
     var tensor = new DenseTensor<float>(new[] { 1, bitmap.Height, bitmap.Width, 3 });
     var array = new float[1, bitmap.Height, bitmap.Width, 3];
     for (int y = 0; y < bitmap.Height; y++)
     {
         for (int x = 0; x < bitmap.Width; x++)
         {

             tensor[0, y, x, 0] = processedImg.Data[y, x, 2];
             tensor[0, y, x, 1] = processedImg.Data[y, x, 1];
             tensor[0, y, x, 2] = processedImg.Data[y, x, 0];

         }
     }
     return tensor;
 }
 
 
 public static Image<Bgr, float> TensorToImage(Tensor<float> tensor, Size size)
 {
     int height = size.Height;
     int width = size.Width;
     Image<Bgr, float> img = new Image<Bgr, float>(width, height);

     for (int y = 0; y < height; y++)
     {
         for (int x = 0; x < width; x++)
         {
             float b = Math.Min(Math.Max((tensor[0, y, x, 0] + 1f) / 2f * 255f, 0f), 255f);
             float g = Math.Min(Math.Max((tensor[0, y, x, 1] + 1f) / 2f * 255f, 0f), 255f);
             float r = Math.Min(Math.Max((tensor[0, y, x, 2] + 1f) / 2f * 255f, 0f), 255f);
             img.Data[y, x, 2] = b;
             img.Data[y, x, 1] = g;
             img.Data[y, x, 0] = r;
         }
     }
     return img;
 }
  • 24
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值