C# PaddleInference.PP-HumanSeg 人像分割 替换背景色

效果

项目

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();
        }
    }
}

下载

源码下载

相关推荐
飞哥数智坊18 小时前
我的“龙虾”罢工了!正好对比下GLM、MiniMax、Kimi 3家谁更香
人工智能
风象南19 小时前
很多人说,AI 让技术平权了,小白也能乱杀老师傅 ?
人工智能·后端
董董灿是个攻城狮20 小时前
大模型连载1:了解 Token
人工智能
RoyLin1 天前
沉睡三十年的标准:HTTP 402、生成式 UI 与智能体原生软件的时代
人工智能
needn1 天前
TRAE为什么要发布SOLO版本?
人工智能·ai编程
毅航1 天前
自然语言处理发展史:从规则、统计到深度学习
人工智能·后端
前端付豪1 天前
LangChain链 写一篇完美推文?用SequencialChain链接不同的组件
人工智能·python·langchain
ursazoo1 天前
写了一份 7000字指南,让 AI 帮我消化每天的信息流
人工智能·开源·github
_志哥_1 天前
Superpowers 技术指南:让 AI 编程助手拥有超能力
人工智能·ai编程·测试
YongGit1 天前
OpenClaw 本地 AI 助手完全指南:飞书接入 + 远程部署实战
人工智能