效果
项目
VS2022+.net4.8+OpenCvSharp4+Sdcb.PaddleInference
包含4个分割模型
modnet-hrnet_w18
modnet-mobilenetv2
ppmatting-hrnet_w18-human_512
ppmattingv2-stdc1-human_512
代码
using OpenCvSharp;
using Sdcb.PaddleInference;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using YamlDotNet.RepresentationModel;
namespace PaddleInference.PP_HumanSeg_人像分割_替换背景色
{
public class PaddleSeger : IDisposable
{
private readonly PaddlePredictor _p;
public PaddleSeger(PaddleConfig config, string deployYamlPath)
: this(config.CreatePredictor(), deployYamlPath)
{
}
public PaddleSeger(PaddlePredictor predictor, string deployYamlPath)
{
_p = predictor;
var yaml = new YamlStream();
using (FileStream ymlFile = File.OpenRead(deployYamlPath))
yaml.Load(new StreamReader(ymlFile));
YamlDocument doc = yaml.Documents[0];
}
public PaddleSeger(string modelDir) : this(PaddleConfig.FromModelFiles(
Path.Combine(modelDir, "model.pdmodel"),
Path.Combine(modelDir, "model.pdiparams")).Apply(PaddleDevice.Mkldnn()),
Path.Combine(modelDir, "deploy.yaml"))
{
}
public Mat Run(Mat src)
{
Mat dest;
using (PaddleTensor input = _p.GetInputTensor(_p.InputNames[0]))
{
Mat bgr = src.CvtColor(ColorConversionCodes.BGR2RGB);
Mat normalized = Normalize(bgr);
float[] data = ExtractMat(normalized);
normalized.Dispose();
bgr.Dispose();
input.Shape = new int[] { 1, 3, src.Rows, src.Cols };
input.SetData(data);
}
if (!_p.Run())
{
throw new Exception("PaddlePredictor(Seger) run failed.");
}
using (PaddleTensor output = _p.GetOutputTensor(_p.OutputNames[0]))
{
float[] rawData = output.GetData<float>();
byte[] data = Array.ConvertAll(rawData, d => (byte)(d * 255));
GCHandle gc = GCHandle.Alloc(data, GCHandleType.Pinned);
dest = new Mat(output.Shape[2], output.Shape[3], MatType.CV_8UC1, gc.AddrOfPinnedObject());
gc.Free();
}
return dest;
}
private static Mat Normalize(Mat src)
{
Mat normalized = new Mat();
src.ConvertTo(normalized, MatType.CV_32FC3, 1.0 / 255);
Mat[] bgr = normalized.Split();
float[] scales = new[] { 2.0f, 2.0f, 2.0f };
float[] means = new[] { 0.5f, 0.5f, 0.5f };
for (int i = 0; i < bgr.Length; ++i)
{
bgr[i].ConvertTo(bgr[i], MatType.CV_32FC1, 1.0 * scales[i], (0.0 - means[i]) * scales[i]);
}
normalized.Dispose();
Mat dest = new Mat();
Cv2.Merge(bgr, dest);
foreach (Mat channel in bgr)
{
channel.Dispose();
}
return dest;
}
internal static float[] ExtractMat(Mat src)
{
int rows = src.Rows;
int cols = src.Cols;
float[] result = new float[rows * cols * 3];
GCHandle resultHandle = default;
try
{
resultHandle = GCHandle.Alloc(result, GCHandleType.Pinned);
IntPtr resultPtr = resultHandle.AddrOfPinnedObject();
for (int i = 0; i < src.Channels(); ++i)
{
Mat dest = new Mat(rows, cols, MatType.CV_32FC1, resultPtr + i * rows * cols * sizeof(float));
Cv2.ExtractChannel(src, dest, i);
dest.Dispose();
}
}
finally
{
resultHandle.Free();
}
return result;
}
public void Dispose()
{
_p.Dispose();
}
}
}