C# 从C++; 项目中,我使用UNIGIS3D的C脚本和C++通过DLIMPOUNT。我的目标是游戏场景有2个立方体(立方体和CuBe2)< /> >这一个立方体纹理通过我的笔记本电脑和Unity的 WebCAMPrime.Pror()/Cudio显示了现场视频,另一个立方体纹理显示了外部C++函数 PrimeSimeAGE()/处理过的视频。
代码上下文:C# 从C++; 项目中,我使用UNIGIS3D的C脚本和C++通过DLIMPOUNT。我的目标是游戏场景有2个立方体(立方体和CuBe2)< /> >这一个立方体纹理通过我的笔记本电脑和Unity的 WebCAMPrime.Pror()/Cudio显示了现场视频,另一个立方体纹理显示了外部C++函数 PrimeSimeAGE()/处理过的视频。,c#,c++,unity3d,pinvoke,C#,C++,Unity3d,Pinvoke,代码上下文: 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++) {
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
}
}
}
[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();
}
在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;
}
获取相机位置并设置立方体1、立方体2纹理
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();
}
}
结果:
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
}
}
}
[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();
}
结果是立方体1的纹理仅显示实时视频,而无法使用立方体2的纹理显示处理后的数据
错误:
使用数组中无效的像素数调用SetPixels32
UnityEngine.Texture2D:SetPixels32(Color32[])网络摄像头:更新()(位于
资产/脚本/网络摄像头。cs:45)
我不明白为什么当我将数组a输入到SetPixels32时,数组中的像素数无效
有什么想法吗
更新(2018年10月10日)
多亏了@Programmer,现在它可以通过pin内存工作了 顺便说一句,我发现了一些关于Unity引擎的小东西。当Unity摄像头在0到1秒之间运行时,
webCamTexture.width
或webCamTexture.height
始终返回16x16
大小,即使请求更大的图像,例如1280x720,它也会在1秒后返回正确的大小。因此,我引用此函数并延迟2秒运行Update()
函数中的Process()
,并在Process()
函数中重置纹理2D大小。它可以很好地工作:
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");
}
...
}
delaytime=0;
无效更新()
{
delaytime=delaytime+Time.deltaTime;
Log(webCamTexture.width);
Log(webCamTexture.height);
如果(延迟时间>=2f)
过程();
}
不安全的无效进程()
{
...
if((Test.width!=webCamTexture.width)| | Test.height!=webCamTexture.height)
{
测试=新纹理2D(webCamTexture.width、webCamTexture.height、TextureFormat.ARGB32、false、false);
cube2.GetComponent().material.mainTexture=测试;
Log(“固定纹理维度”);
}
...
}
c不返回理解C++中的<代码> COLL32 对象。如果将返回类型设置为unsigned char*
,然后在C端使用marshall.Copy
将返回的数据复制到字节数组中,然后使用将数组加载到Texture2D
中,则此方法会起作用。是一个从C#返回字节数组的示例
我不建议您返回数据,因为这很昂贵。填充传递给函数的数组,然后将该数组重新分配给
纹理2D
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
}
}
}
[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);
}
如果不想使用<代码>不安全的< /代码>和<代码>固定< /COD>关键字,也可以使用<代码> GCHANDLE。ALC/C >代码之前,将其发送到C++端,并使用“代码> GCHANDLE”。如何做到这一点,请参阅帖子
如果您遇到以下异常: 使用数组中无效的像素数调用SetPixels32 UnityEngine.Texture2D:SetPixels32(Color32[])网络摄像头:更新()(位于 资产/脚本/网络摄像头。cs:45) 这意味着您正在调用的
SetPixels32
上的Texture2D
与WebCamTexture
纹理具有不同的大小或纹理维度。要解决此问题,请在调用SetPixels32
之前,检查纹理维度是否已更改,然后调整目标纹理的大小以与WebCamTexture
匹配
替换
tx2D.SetPixels32(rawImg);
tx2D.Apply();
与
您能否共享定义和初始化Texture2D tx2D变量的代码?Texture2D tx2D初始化新的Texture2D(webCamTexture.width,webCamTexture.height)
代码已上载,您可以在此网站上观看[链接:谢谢你的回复。不幸的是,我引用了你的建议,思考并修改了代码。它也出现了相同的错误消息。如果你想查看代码的详细信息,我已经上传到这个网站:对答案进行了编辑以解决该错误。请查看。如果仍然存在问题,请告诉我。别忘了访问acc如果您的问题通过单击我答案上的绿色复选标记得到解决,请接受答案。感谢@Programmer,现在它可以通过pin内存工作。但是,我有一个小问题,如果我使用OpenCV库处理图像。有关详细信息,请参阅我的“更新”帖子对不起,这不是它在这里的工作原理。这个帖子不是关于OpenCV和关于从C++更新Trutu2D像素的原始帖子。我想问题现在已经解决了。当你问一个问题,它被解决了,但是你想做不同的事情,并遇到问题,你接受当前的答案,然后创建新的问题。你应该Cre。在OpenCV帖子中添加新问题。请确保在新问题中也标记OpenCV。您可能希望删除对此问题所做的OpenCV编辑。