您现在的位置是:首页 >技术交流 >C# - 图片抠像 - RVM - 含模型 - 完整可运行网站首页技术交流

C# - 图片抠像 - RVM - 含模型 - 完整可运行

行人- 2025-04-19 00:01:02
简介C# - 图片抠像 - RVM - 含模型 - 完整可运行

环境

.NET Framework 4.6.2 , X64 , VS2022


依赖 

OpenCvSharp.dll,OpenCvSharp.Extensions.dll,Microsoft.ML.OnnxRuntime.dll,rvm_resnet50_fp32.onnx


效果


页面

全部逻辑代码

    public partial class Form1 : Form
    {
        private string imgFile = "";
        private int process_wd = 360;
        private int process_ht = 640;
        private InferenceSession session;
        private static readonly SimpleObjectPool<List<NamedOnnxValue>> _inputsPool =
            new SimpleObjectPool<List<NamedOnnxValue>>(() => new List<NamedOnnxValue>());
        private static DenseTensor<float> _emptyTensor;
        private static DenseTensor<float> _downsampleRatio;
        private static Mat _resizedMat;
        private static Mat _normalizedMat;
        private static Mat[] _channels;
        private static DenseTensor<float> _preprocessTensor;
        private static float[] _channelData = new float[0];


        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                ofd.Filter = "图像文件|*.jpg;*.png;";
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    imgFile = ofd.FileName;
                }
            }
            if (string.IsNullOrEmpty(imgFile))
            {
                return;
            }

            do_rec();
        }

        private async void do_rec()
        {
            var imgBs = File.ReadAllBytes(imgFile);
            var imgInit = Image.FromStream(new MemoryStream(imgBs)) as Bitmap;
            pb_init.Image = imgInit;
            Application.DoEvents();

            if (session == null)
            {
                load_removebg();
            }

            var imgRst = await Task.Run(() =>
               removebg(imgBs)
            );
            pb_rst.Image = imgRst;
            Application.DoEvents();
        }

        private void load_removebg()
        {
            session = new InferenceSession(AppDomain.CurrentDomain.BaseDirectory + "model\rvm_resnet50_fp32.onnx"); 
        }

        private Bitmap removebg(byte[] imgbs)
        {
            var image = Cv2.ImDecode(imgbs, ImreadModes.Color);

            try
            {
                if (_emptyTensor == null)
                {
                    _emptyTensor = new DenseTensor<float>(new[] { 1, 1, 1, 1 });
                    _downsampleRatio = new DenseTensor<float>(new[] { 1 });
                    _downsampleRatio.Buffer.Span[0] = 1f;
                }

                var inputs = _inputsPool.Get();
                try
                {
                    var input = PreprocessFrame(image);
                    inputs.Add(NamedOnnxValue.CreateFromTensor("src", input));
                    inputs.Add(NamedOnnxValue.CreateFromTensor("downsample_ratio", _downsampleRatio));

                    inputs.Add(NamedOnnxValue.CreateFromTensor("r1i", _emptyTensor));
                    inputs.Add(NamedOnnxValue.CreateFromTensor("r2i", _emptyTensor));
                    inputs.Add(NamedOnnxValue.CreateFromTensor("r3i", _emptyTensor));
                    inputs.Add(NamedOnnxValue.CreateFromTensor("r4i", _emptyTensor));

                    var outputs = session.Run(inputs);
                    var fgr = outputs.First(x => x.Name == "fgr").AsEnumerable<float>().ToArray();
                    var pha = outputs.First(x => x.Name == "pha").AsEnumerable<float>().ToArray();
                    return PostprocessFrame(image, fgr, pha).ToBitmap();
                }
                finally
                {
                    inputs.Clear();
                    _inputsPool.Return(inputs);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error in ProcessFrame: {ex.Message}");
                Console.WriteLine($"Stack trace: {ex.StackTrace}");
                throw;
            }
        }

        private Tensor<float> PreprocessFrame(Mat frame)
        {
            try
            {
                {
                    process_wd = 512;
                    process_ht = (int)Math.Round(frame.Height / (double)frame.Width * process_wd);
                    _channelData = new float[process_ht * process_wd];

                    _resizedMat = new Mat();
                    _normalizedMat = new Mat();
                    _channels = new Mat[3];
                    _preprocessTensor = new DenseTensor<float>(new[] { 1, 3, process_ht, process_wd });
                }

                Cv2.Resize(frame, _resizedMat, new OpenCvSharp.Size(process_wd, process_ht));
                _resizedMat.ConvertTo(_normalizedMat, MatType.CV_32F, 1.0 / 255.0);

                Cv2.Split(_normalizedMat, out _channels);
                var tensorSpan = _preprocessTensor.Buffer.Span;

                unsafe
                {
                    for (int c = 0; c < 3; c++)
                    {
                        Marshal.Copy(_channels[2 - c].Ptr(0), _channelData, 0, _channelData.Length);
                        int channelOffset = c * process_ht * process_wd;

                        fixed (void* channelDataPtr = &_channelData[0])
                        {
                            var floatPtr = (float*)channelDataPtr;
                            for (int i = 0; i < process_ht * process_wd; i++)
                            {
                                tensorSpan[channelOffset + i] = floatPtr[i];
                            }
                        }
                    }
                }

                return _preprocessTensor;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error in PreprocessFrame: {ex.Message}");
                Console.WriteLine($"Stack trace: {ex.StackTrace}");
                throw;
            }
        }

        private Mat PostprocessFrame(Mat original, float[] fgr, float[] pha)
        {
            try
            {
                using (var fgrMat = new Mat(process_ht, process_wd, MatType.CV_32FC3))
                using (var phaMat = new Mat(process_ht, process_wd, MatType.CV_32FC1))
                {
                    unsafe
                    {
                        fixed (float* fgrPtr = fgr)
                        fixed (float* phaPtr = pha)
                        {
                            using (var tempFgr = new Mat(process_ht, process_wd, MatType.CV_32FC3, (IntPtr)fgrPtr))
                            using (var tempPha = new Mat(process_ht, process_wd, MatType.CV_32FC1, (IntPtr)phaPtr))
                            {
                                tempFgr.CopyTo(fgrMat);
                                tempPha.CopyTo(phaMat);

                            }
                        }
                    }


                    using (var fgr8U = new Mat())
                    using (var pha8U = new Mat())
                    {
                        fgrMat.ConvertTo(fgr8U, MatType.CV_8UC3, 255.0);
                        phaMat.ConvertTo(pha8U, MatType.CV_8UC1, 255.0);

                        var result = new Mat(new OpenCvSharp.Size(process_wd, process_ht), MatType.CV_8UC3);

                        using (var resizedOriginal = new Mat())
                        using (var alpha3C = new Mat())
                        using (var inverseAlpha3C = new Mat())
                        using (var bgMat = new Mat(process_ht, process_wd, MatType.CV_8UC3, new Scalar(0, 255, 0))) // 绿色背景
                        {
                            Cv2.Resize(original, resizedOriginal, new OpenCvSharp.Size(process_wd, process_ht));

                            Cv2.Merge(new[] { pha8U, pha8U, pha8U }, alpha3C);
                            alpha3C.ConvertTo(alpha3C, MatType.CV_32FC3, 1.0 / 255.0);

                            Cv2.Subtract(new Scalar(1.0, 1.0, 1.0), alpha3C, inverseAlpha3C);

                            Cv2.Multiply(resizedOriginal, alpha3C, resizedOriginal, 1.0, MatType.CV_8UC3);
                            Cv2.Multiply(bgMat, inverseAlpha3C, bgMat, 1.0, MatType.CV_8UC3);
                            Cv2.Add(resizedOriginal, bgMat, result);
                        }

                        return result;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error in PostprocessFrame: {ex.Message}");
                Console.WriteLine($"Stack trace: {ex.StackTrace}");
                throw;
            }
        }

    }
     
    public class SimpleObjectPool<T>
    {
        private readonly ConcurrentBag<T> _objects;
        private readonly Func<T> _objectGenerator;

        public SimpleObjectPool(Func<T> objectGenerator)
        {
            _objects = new ConcurrentBag<T>();
            _objectGenerator = objectGenerator;
        }

        public T Get()
        {
            return _objects.TryTake(out T item) ? item : _objectGenerator();
        }

        public void Return(T item)
        {
            _objects.Add(item);
        }
    }

Demo 下载地址:

https://download.csdn.net/download/xuezhandansha/90358871

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。