当前位置: 首页 > news >正文

Unity使用PP-MattingV2实现人像分割

PP-MattingV2

https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.10/Matting/README_CN.md
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

主要代码

using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using Debug = UnityEngine.Debug;public class ppmatting : MonoBehaviour
{[Header("模型设置")]public string modelPath = "ppmattingv2_stdc1_human_512x512.onnx";public float confThreshold = 0.65f;[Header("输入设置")]public Texture2D inputTexture2D;[Header("输出设置")]public RawImage image;private InferenceSession session;private int inputWidth = 512;private int inputHeight = 512;// 输入输出节点名称private string inputName = "input";private string outputName = "output";// 处理结果public Texture2D resultTexture;void Start(){InitializeModel();// 如果设置了输入纹理,立即处理if (inputTexture2D != null){Stopwatch stopwatch = new Stopwatch();stopwatch.Start();image.texture = ProcessInputTexture();stopwatch.Stop();long lastInferenceTime = stopwatch.ElapsedMilliseconds;// 输出耗时信息Debug.Log($"推理完成!总耗时: {lastInferenceTime}ms");}}void InitializeModel(){try{// 加载模型var modelFullPath = System.IO.Path.Combine(Application.streamingAssetsPath, modelPath);var ortEnvInstance = OrtEnv.Instance();string[] aps = ortEnvInstance.GetAvailableProviders();foreach (var ap in aps){Debug.Log(ap);}var options = new SessionOptions();//options.AppendExecutionProvider_CPU();options.AppendExecutionProvider_CUDA();session = new InferenceSession(modelFullPath, options);// 获取输入形状var inputMeta = session.InputMetadata;foreach (var name in inputMeta.Keys){inputName = name;var shape = inputMeta[name].Dimensions;inputHeight = (int)shape[2];inputWidth = (int)shape[3];}Debug.Log($"模型加载成功: {modelPath}, 输入尺寸: {inputWidth}x{inputHeight}");}catch (Exception e){Debug.LogError($"模型加载失败: {e.Message}");}}void Update(){}/// <summary>/// 处理输入的Texture2D并返回结果Texture2D/// </summary>public Texture2D ProcessInputTexture(){if (inputTexture2D == null){Debug.LogWarning("输入纹理为空");return null;}if (session == null){Debug.LogError("模型未初始化");return null;}try{resultTexture = ProcessMatting(inputTexture2D);return resultTexture;}catch (Exception e){Debug.LogError($"处理失败: {e.Message}");return null;}}/// <summary>/// 处理外部传入的Texture2D/// </summary>public Texture2D ProcessTexture(Texture2D inputTex){if (inputTex == null || session == null){Debug.LogError("输入纹理为空或模型未初始化");return null;}try{return ProcessMatting(inputTex);}catch (Exception e){Debug.LogError($"处理失败: {e.Message}");return null;}}Texture2D ProcessMatting(Texture2D inputTexture){try{// 预处理var inputTensor = Preprocess(inputTexture);// 创建输入var inputs = new List<NamedOnnxValue>{NamedOnnxValue.CreateFromTensor(inputName, inputTensor)};// 推理using (var results = session.Run(inputs)){// 获取输出var outputTensor = results.First().AsTensor<float>();// 后处理return Postprocess(outputTensor, inputTexture.width, inputTexture.height);}}catch (Exception e){Debug.LogError($"人像抠图处理失败: {e.Message}");return inputTexture;}}Tensor<float> Preprocess(Texture2D texture){// 调整尺寸并转换为RGBvar resizedTexture = ResizeTexture(texture, inputWidth, inputHeight);Color32[] pixels = resizedTexture.GetPixels32();// 预先分配数据数组int totalElements = 1 * 3 * inputHeight * inputWidth;float[] dataArray = new float[totalElements];var shape = new int[] { 1, 3, inputHeight, inputWidth };// 使用明确的数据数组构造函数var tensor = new DenseTensor<float>(dataArray, shape, false);for (int y = 0; y < inputHeight; y++){for (int x = 0; x < inputWidth; x++){int index = y * inputWidth + x;var pixel = pixels[index];// 归一化并设置通道顺序 [R, G, B]tensor[0, 0, y, x] = pixel.r / 255.0f; // Rtensor[0, 1, y, x] = pixel.g / 255.0f; // Gtensor[0, 2, y, x] = pixel.b / 255.0f; // B}}// 清理临时纹理DestroyImmediate(resizedTexture);return tensor;}Texture2D Postprocess(Tensor<float> output, int originalWidth, int originalHeight){// 获取alpha通道 [1, 1, H, W] -> [H, W]var alphaMap = new float[inputHeight, inputWidth];for (int y = 0; y < inputHeight; y++){for (int x = 0; x < inputWidth; x++){alphaMap[y, x] = output[0, 0, y, x];}}// 调整到原始尺寸var resizedAlpha = ResizeAlphaMap(alphaMap, originalWidth, originalHeight);// 创建结果纹理(带透明通道的人像)var resultTexture = new Texture2D(originalWidth, originalHeight, TextureFormat.RGBA32, false);// 如果需要保留原始图像,可以传入原始纹理Color[] originalColors = null;if (inputTexture2D != null && inputTexture2D.width == originalWidth && inputTexture2D.height == originalHeight){originalColors = inputTexture2D.GetPixels();}for (int y = 0; y < originalHeight; y++){for (int x = 0; x < originalWidth; x++){float alpha = resizedAlpha[y, x];Color pixelColor;if (originalColors != null){// 使用原始图像颜色,根据alpha值设置透明度int index = y * originalWidth + x;pixelColor = originalColors[index];pixelColor.a = alpha > confThreshold ? 1.0f : 0.0f;}else{// 简单显示:人像区域白色,背景透明if (alpha > confThreshold){pixelColor = Color.white; // 人像区域}else{pixelColor = Color.clear; // 背景透明}}resultTexture.SetPixel(x, y, pixelColor);}}resultTexture.Apply();return resultTexture;}float[,] ResizeAlphaMap(float[,] alphaMap, int newWidth, int newHeight){var resized = new float[newHeight, newWidth];float scaleX = (float)inputWidth / newWidth;float scaleY = (float)inputHeight / newHeight;for (int y = 0; y < newHeight; y++){for (int x = 0; x < newWidth; x++){int srcX = Mathf.Clamp((int)(x * scaleX), 0, inputWidth - 1);int srcY = Mathf.Clamp((int)(y * scaleY), 0, inputHeight - 1);resized[y, x] = alphaMap[srcY, srcX];}}return resized;}Texture2D ResizeTexture(Texture2D source, int newWidth, int newHeight){var rt = RenderTexture.GetTemporary(newWidth, newHeight);Graphics.Blit(source, rt);var result = new Texture2D(newWidth, newHeight, TextureFormat.RGBA32, false);RenderTexture.active = rt;result.ReadPixels(new Rect(0, 0, newWidth, newHeight), 0, 0);result.Apply();RenderTexture.ReleaseTemporary(rt);return result;}/// <summary>/// 设置输入纹理/// </summary>public void SetInputTexture(Texture2D texture){inputTexture2D = texture;}/// <summary>/// 获取处理结果纹理/// </summary>public Texture2D GetResultTexture(){return resultTexture;}void OnDestroy(){session?.Dispose();// 清理结果纹理if (resultTexture != null){DestroyImmediate(resultTexture);}}
}

最后是工程地址

https://github.com/xue-fei/pp-matting-unity.git

http://www.dtcms.com/a/556700.html

相关文章:

  • 智能模型对齐(一致性)alignment
  • VSCode SSH远程连接失败 最速解决方案
  • 网站开发旅游前台模板临海建设规划局网站
  • 加载YOLO模型,处理mp4视频
  • 基于 GEE 利用 GHSL(100m)数据的区域建成区时空变化量化分析
  • day22_用户授权 头像上传
  • 网站识别爬虫(包括以浏览器插件形式运行的爬虫)主要通过分析请求特征、行为模式等差异来区分人类用户和自动化程序
  • 网站建设费用IPseo官网优化详细方法
  • 汽车OTA CDN HTTPS MQTT OCSP
  • python异步编程 -- 深入理解事件循环event-loop
  • 京津冀工业智能体赋能:重构产业链升级新篇章
  • AIGEO系统到底是什么?
  • 日志系统的介绍及前置技术
  • 安居客做网站广州建设网站公司哪家好
  • 【JUnit实战3_22】 第十三章:用 JUnit 5 做持续集成(下):Jenkins + JUnit 5 + Git 持续集成本地实战演练完整复盘
  • 【Linux】 CI/CD 管道优化:使用 GitHub Actions/GitLab CI 提速构建和部署
  • XML 与 XSLT:深入解析与实际应用
  • 关于maven中pom依赖冲突问题记录
  • 360提交网站入口怎么做能够让网站流量大
  • 三亚做网站哪家好做网站推广的难点、
  • 做一家购物网站要多少钱天津网站建设哪家好
  • ps制作网站效果图有没有做任务拿佣金的网站
  • 国内网站设计案例欣赏自己的网站怎么做商城
  • 建设好的网站怎么分享门户cms
  • h5语言网站制作网站应急响应机制建设情况
  • qq刷赞网站怎么做的石家庄栾城区建设局网站
  • 滁州seo网站排名优化湛江网站建设皆选小罗24专业
  • 门户网站建设评标办法wordpress页面链接跳转
  • 做代码的网站做展示型网站多少钱
  • 国外网站后缀WordPress无法删除插件