个人资料

跳过导航链接首页 > 博客列表 > 博客正文

使用OpenCVSharp和animegan2 onnx实现照片的动漫化c#

:

使用onnxruntime、opencvsharp

onnxruntime利用animegan2 onnx(512x512 体积约8M)训练好的机器学习模型进行本机计算

同时使用opencv(opencvsharp)的L0smooth替代原来的nuget插件包

---

Nuget

dotnet add package AnimeGANv2_Onnx_Sharp --version 1.0.0

源代码:

songshizhao/AnimeGANv2_Sharp (github.com)

-----------

代码参考:

public class OnnxHelper
{
   private static InferenceSession _session;
   private static SessionOptions _option;
   private static List<NamedOnnxValue> container = new List<NamedOnnxValue>();
   public static async Task Init()
   {

      var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(@"ms-appx:///face_paint_512_v2_0.onnx"));


      var buffer = await FileIO.ReadBufferAsync(file);

      _option = new SessionOptions
      {
         LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_ERROR
      };
      _option.AppendExecutionProvider_CPU(0);
      //_option.AppendExecutionProvider_CoreML();
      _session = new InferenceSession(buffer.ToArray(), _option);

   }

   public static async Task Init2()
   {

      var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(@"ms-appx:///face_paint_512_v2_0.onnx"));


      var buffer = await FileIO.ReadBufferAsync(file);

      _option = new SessionOptions
      {
         LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_ERROR
      };
      _option.AppendExecutionProvider_CPU(0);
      //_option.AppendExecutionProvider_CoreML();
      _session = new InferenceSession(buffer.ToArray(), _option);





   }




   private static DenseTensor<float> PreInput(Mat mat)
   {

      var mat512 = new Mat();
      Cv2.Resize(mat, mat512, new Size(512, 512));

      Mat m512 = new Mat();

      Cv2.CvtColor(mat512, m512, ColorConversionCodes.BGR2RGB);

      //输入Tensor
      DenseTensor<float> input_tensor = new DenseTensor<float>(new[] { 1, 3, 512, 512 });
      // 输入Tensor
      for (int y = 0; y < m512.Height; y++)
      {
         for (int x = 0; x < m512.Width; x++)
         {

            input_tensor[0, 0, y, x] = (mat512.At<Vec3b>(y, x)[0] / 255f - 0.5f) / 0.5f;
            input_tensor[0, 1, y, x] = (mat512.At<Vec3b>(y, x)[1] / 255f - 0.5f) / 0.5f;
            input_tensor[0, 2, y, x] = (mat512.At<Vec3b>(y, x)[2] / 255f - 0.5f) / 0.5f;
         }
      }
      return input_tensor;
   }



   public static async Task<Mat> Smooth(Mat sourceMat, double lambda = 2e-2, double kappa = 2.0)
   {

      Mat output = new Mat();//sourceMat.Width,sourceMat.Height,MatType.CV_8UC4

      sourceMat = sourceMat.CvtColor(ColorConversionCodes.BGRA2BGR, 3);
      await Task.Run(() =>
      {


         OpenCvSharp.XImgProc.CvXImgProc.L0Smooth(sourceMat, output, lambda, kappa);

      });

      return output;

   }


   //

   public static Mat Bytes2Mat8UC3(int w, int h, byte[] bytes)
   {
      Mat mat = new Mat(h, w, MatType.CV_8UC4, bytes);
      mat = mat.CvtColor(ColorConversionCodes.BGRA2BGR, 3);
      return mat;
   }

   public static byte[] Mat2Bytes(Mat mat)
   {
      return mat.ToBytes();
   }


   public static async Task<Mat> RunB2M(int w, int h, byte[] bytes)
   {


      Mat mat = Bytes2Mat8UC3(w, h, bytes);

      var inputTensor = PreInput(mat);//DenseTensor<float> inputTensor
      Mat result_mat = new Mat();
      await Task.Run(() =>
      {

         container.Clear();
         container.Add(NamedOnnxValue.CreateFromTensor<float>("input_image", inputTensor));
         var results = _session.Run(container);
         var resultArrays = results.ToArray();

         var result_tensors = results[0].AsTensor<float>();

         var result_array = result_tensors.ToArray();

         float[] temp_r = new float[512 * 512];
         float[] temp_g = new float[512 * 512];
         float[] temp_b = new float[512 * 512];

         Array.Copy(result_array, temp_r, 512 * 512);
         Array.Copy(result_array, 512 * 512, temp_g, 0, 512 * 512);
         Array.Copy(result_array, 512 * 512 * 2, temp_b, 0, 512 * 512);

         Mat rmat = new Mat(512, 512, MatType.CV_32FC1, temp_r);
         Mat gmat = new Mat(512, 512, MatType.CV_32FC1, temp_g);
         Mat bmat = new Mat(512, 512, MatType.CV_32FC1, temp_b);

         rmat = (rmat + 1f) * 127.5f;
         gmat = (gmat + 1f) * 127.5f;
         bmat = (bmat + 1f) * 127.5f;


         Cv2.Merge(new Mat[] { rmat, gmat, bmat }, result_mat);
      });
      return result_mat;
   }

   public static async Task<byte[]> RunB2B(int w, int h, byte[] bytes)
   {



      Mat result_mat = new Mat();
      await Task.Run(() =>
      {
         Mat mat = Bytes2Mat8UC3(w, h, bytes);

         var inputTensor = PreInput(mat);


         container.Clear();
         container.Add(NamedOnnxValue.CreateFromTensor<float>("input_image", inputTensor));
         var results = _session.Run(container);
         var resultArrays = results.ToArray();

         var result_tensors = results[0].AsTensor<float>();

         var result_array = result_tensors.ToArray();

         float[] temp_r = new float[512 * 512];
         float[] temp_g = new float[512 * 512];
         float[] temp_b = new float[512 * 512];

         Array.Copy(result_array, temp_r, 512 * 512);
         Array.Copy(result_array, 512 * 512, temp_g, 0, 512 * 512);
         Array.Copy(result_array, 512 * 512 * 2, temp_b, 0, 512 * 512);

         Mat rmat = new Mat(512, 512, MatType.CV_32FC1, temp_r);
         Mat gmat = new Mat(512, 512, MatType.CV_32FC1, temp_g);
         Mat bmat = new Mat(512, 512, MatType.CV_32FC1, temp_b);

         rmat = (rmat + 1f) * 127.5f;
         gmat = (gmat + 1f) * 127.5f;
         bmat = (bmat + 1f) * 127.5f;


         Cv2.Merge(new Mat[] { rmat, gmat, bmat }, result_mat);
      });
      return result_mat.ToBytes();
   }

   public static async Task<Mat> RunM2M(Mat mat)
   {
      var inputTensor = PreInput(mat);//DenseTensor<float> inputTensor
      Mat result_mat = new Mat();
      await Task.Run(() =>
      {

         container.Clear();
         container.Add(NamedOnnxValue.CreateFromTensor<float>("input_image", inputTensor));
         var results = _session.Run(container);
         var resultArrays = results.ToArray();

         var result_tensors = results[0].AsTensor<float>();

         var result_array = result_tensors.ToArray();

         float[] temp_r = new float[512 * 512];
         float[] temp_g = new float[512 * 512];
         float[] temp_b = new float[512 * 512];

         Array.Copy(result_array, temp_r, 512 * 512);
         Array.Copy(result_array, 512 * 512, temp_g, 0, 512 * 512);
         Array.Copy(result_array, 512 * 512 * 2, temp_b, 0, 512 * 512);

         Mat rmat = new Mat(512, 512, MatType.CV_32FC1, temp_r);
         Mat gmat = new Mat(512, 512, MatType.CV_32FC1, temp_g);
         Mat bmat = new Mat(512, 512, MatType.CV_32FC1, temp_b);

         rmat = (rmat + 1f) * 127.5f;
         gmat = (gmat + 1f) * 127.5f;
         bmat = (bmat + 1f) * 127.5f;


         Cv2.Merge(new Mat[] { rmat, gmat, bmat }, result_mat);
      });
      return result_mat;
   }


}

-----------

点评:

opencv自带L0smooth的功能,可比我自己C#手写的无速度优化版本速度快多了,完全替代了我写的垃圾nuget

songshizhao
最初发表2023/12/5 11:03:32 最近更新2023/12/5 11:07:34 757
为此篇作品打分
10