[英]Update Texture2D pixels from C++
在项目中,我正在通过DllImports使用Unity3D的C#脚本和C ++。 我的目标是游戏场景具有2个多维数据集(Cube & Cube2)
,其中一个多维数据集纹理通过我的便携式摄像机和Unity的webCamTexture.Play()
展示实时视频,另一个多维数据集纹理通过外部C ++函数显示处理后的视频ProcessImage()
。
代码上下文:
在C ++中,我定义为
struct Color32
{
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
};
而功能是
extern "C"
{
Color32* ProcessImage(Color32* raw, int width, int height);
}
...
Color32* ProcessImage(Color32* raw, int width, int height)
{
for(int i=0; i<width*height ;i++)
{
raw[i].r = raw[i].r-2;
raw[i].g = raw[i].g-2;
raw[i].b = raw[i].b-2;
raw[i].a = raw[i].a-2;
}
return raw;
}
C#:
声明和导入
public GameObject cube;
public GameObject cube2;
private Texture2D tx2D;
private WebCamTexture webCamTexture;
[DllImport("test22")] /*the name of Plugin is test22*/
private static extern Color32[] ProcessImage(Color32[] rawImg,
int width, int height);
获取摄像头情况并设置cube1,cube2纹理
void Start()
{
WebCamDevice[] wcd = WebCamTexture.devices;
if(wcd.Length==0)
{
print("Cannot find a camera");
Application.Quit();
}
else
{
webCamTexture = new WebCamTexture(wcd[0].name);
cube.GetComponent<Renderer>().material.mainTexture = webCamTexture;
tx2D = new Texture2D(webCamTexture.width, webCamTexture.height);
cube2.GetComponent<Renderer>().material.mainTexture = tx2D;
webCamTexture.Play();
}
}
通过DllImports
将数据发送到外部C ++函数,并使用Color32[] a
接收处理后的数据。 最后,我使用Unity的SetPixels32
设置tx2D
(Cube2)纹理:
void Update()
{
Color32[] rawImg = webCamTexture.GetPixels32();
System.Array.Reverse(rawImg);
Debug.Log("Test1");
Color32[] a = ProcessImage(rawImg, webCamTexture.width, webCamTexture.height);
Debug.Log("Test2");
tx2D.SetPixels32(a);
tx2D.Apply();
}
结果:
结果只是多维数据集1的纹理显示了实时视频,而无法显示使用多维数据集2的纹理处理的数据。
错误:
在数组UnityEngine.Texture2D:SetPixels32(Color32 [])Webcam:Update()中调用了无效像素数的SetPixels32(位于Assets / Scripts / Webcam.cs:45)
我不明白为什么在将数组a输入到SetPixels32时为什么数组中的像素数无效
有任何想法吗?
更新 (2018年10月10日)
感谢@Programmer,现在它可以通过引脚存储工作。
顺便说一句,我发现一些关于Unity Engine的小问题 。 当Unity Camera在0到1秒之间运行时,即使要求更大的图像(例如1280x720), webCamTexture.width
或webCamTexture.height
始终返回16x16
大小,然后它将在1秒后返回正确的大小。 (可能是几帧)因此,我引用了这篇文章,并延迟了2秒钟,以便在Update()
函数中运行Process()
并在Process()
函数中重置Texture2D大小。 它将正常工作:
delaytime = 0;
void Update()
{
delaytime = delaytime + Time.deltaTime;
Debug.Log(webCamTexture.width);
Debug.Log(webCamTexture.height);
if (delaytime >= 2f)
Process();
}
unsafe void Process()
{
...
if ((Test.width != webCamTexture.width) || Test.height != webCamTexture.height)
{
Test = new Texture2D(webCamTexture.width, webCamTexture.height, TextureFormat.ARGB32, false, false);
cube2.GetComponent<Renderer>().material.mainTexture = Test;
Debug.Log("Fixed Texture dimension");
}
...
}
C#不会返回您从C ++返回的Color32
对象。 如果您将返回类型设置为unsigned char*
然后在C#端使用Marshal.Copy
将返回的数据复制到字节数组中,然后使用Texture2D.LoadRawTextureData
将数组加载到Texture2D.LoadRawTextureData
,这将是Texture2D
。 这是一个从C#返回字节数组的示例。
我不建议您返回数据,因为这很昂贵。 填充要传递给函数的数组,然后只需将该数组重新分配给Texture2D
。
C ++:
extern "C"
{
void ProcessImage(unsigned char* raw, int width, int height);
}
...
void ProcessImage(unsigned char* raw, int width, int height)
{
for(int y=0; y < height; y++)
{
for(int x=0; x < width; x++)
{
unsigned char* pixel = raw + (y * width * 4 + x * 4);
pixel[0] = pixel[0]-(unsigned char)2; //R
pixel[1] = pixel[1]-(unsigned char)2; //G
pixel[2] = pixel[2]-(unsigned char)2; //B
pixel[3] = pixel[3]-(unsigned char)2; //Alpha
}
}
}
C#:
[DllImport("test22")]
private static extern void ProcessImage(IntPtr texData, int width, int height);
unsafe void ProcessImage(Texture2D texData)
{
Color32[] texDataColor = texData.GetPixels32();
System.Array.Reverse(texDataColor);
//Pin Memory
fixed (Color32* p = texDataColor)
{
ProcessImage((IntPtr)p, texData.width, texData.height);
}
//Update the Texture2D with array updated in C++
texData.SetPixels32(texDataColor);
texData.Apply();
}
使用方法:
public Texture2D tex;
void Update()
{
ProcessImage(tex);
}
如果你不想使用unsafe
和fixed
关键字,你也可以使用GCHandle.Alloc
它发送到C ++侧前针阵列GCHandle.AddrOfPinnedObject
。 请参阅这篇文章,了解如何执行此操作。
如果您遇到以下异常:
在数组UnityEngine.Texture2D:SetPixels32(Color32 [])Webcam:Update()中调用了无效像素数的SetPixels32(位于Assets / Scripts / Webcam.cs:45)
这意味着您要调用SetPixels32
的Texture2D
与WebCamTexture
纹理具有不同的大小或纹理尺寸。 要解决此问题,请在调用SetPixels32
之前,检查纹理尺寸是否已更改,然后调整目标纹理的大小以与WebCamTexture
匹配。
更换
tx2D.SetPixels32(rawImg);
tx2D.Apply();
同
//Fix texture dimension if it doesn't match with the web cam texture size
if ((tx2D.width != webCamTexture.width) || tx2D.height != webCamTexture.height)
{
tx2D = new Texture2D(webCamTexture.width, webCamTexture.height, TextureFormat.RGBA32, false, false);
Debug.Log("Fixed Texture dimension");
}
tx2D.SetPixels32(rawImg);
tx2D.Apply();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.