前言
视频流以图片形式通过网络协议发送到unity,每帧的byte[]表示一张图片,unity需将byte[]转为texture2d。由于opencv图像经过python压缩处理,texture.LoadImage()方法解析失败,现有以下解决方法。
实现方式
1、导入插件OpenCVForUnity
(多说一句,还查到有另外一种方式,是引用OpenCvSharp库,但是我在Nuget里安装完后还是不能引用它的接口,如果有哪位大佬成功了可以在这里留言,一起学习下)
2、代码实现
需要引用OpenCVForUnity提供的命名空间
using System.Collections;
using System.Collections.Generic;
using System;
using System.Runtime.InteropServices;
using OpenCVForUnity.UtilsModule;
using OpenCVForUnity.CoreModule;
using OpenCVForUnity.UnityUtils;
using OpenCVForUnity.ImgcodecsModule;
//byte[]为经过压缩处理的数据
private void Convert2Texture(byte[] textureBytes)
{
MatOfByte matOfByte = new MatOfByte(textureBytes);
Mat rgbaMat = Imgcodecs.imdecode(matOfByte, Imgcodecs.IMREAD_COLOR);
Color32[] colors = new Color32[width * height];
Texture2D texture = new Texture2D(width, height);
//图像为RGB三通道TextureFormat为RGB24,如果是RGBA四通道TextureFormat为RGBA32
texture.Resize(rgbaMat.cols(), rgbaMat.rows(), TextureFormat.RGB24, false);
Utils.matToTexture2D(rgbaMat, texture,colors);
transform.GetComponent<RawImage>().texture = texture;
matOfByte.Dispose();
rgbaMat.Dispose();
Texture2D.Destroy(texture);
}
[MarshalAs(UnmanagedType.AsAny)]
private IntPtr openCvRawData;
//byte[]为opencv图像原始数据rawdata
private void Rawdata2Texture(byte[] textureBytes)
{
// 将openCvTextureData转换为IntPtr类型并保存到openCvRawData属性中
GCHandle pinnedArray = GCHandle.Alloc(textureBytes, GCHandleType.Pinned);
openCvRawData = pinnedArray.AddrOfPinnedObject();
pinnedArray.Free();
if(openCvRawData != IntPtr.Zero)
{
Color32[] colors = new Color32[width * height];
//图像为RGB三通道CvType为CV_8UC3,如果是RGBA四通道CvType为CV_8UC4
Mat rgbaMat = new Mat(height, width, CvType.CV_8UC3, new Scalar(0, 0, 0, 255));
Texture2D texture = new Texture2D(width, height);
MatUtils.copyToMat(openCvRawData, rgbaMat);
Utils.matToTexture2D(rgbaMat, texture, colors);
Sprite sprite = Sprite.Create(texture, new UnityEngine.Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
transform.GetComponent<Image>().sprite = sprite;
rgbaMat.Dispose();
Texture2D.Destroy(texture);
}
}