在 Android 上使用 OpenCV 和 Unity
Using OpenCV with Unity on Android
我在Android上使用OpenCV和Unity时遇到问题。我使用OpenCV库本机c ++插件(.so文件(我想检测魔方和立方体的颜色。
因此,我将数据从Unity的网络摄像头纹理传递给OpenCV。当网络摄像头纹理的宽度和高度较小(320x240(时,它很好用。但是当网络摄像头纹理的宽度和高度很大(480x640(时,它会遇到问题。当网络摄像头纹理的分辨率设置为全屏时(在本例中我设置为 800x1280(,应用程序将停止。
我尝试调试。当我使用Marshal.Copy函数将数据从OpenCV复制到Unity时,它停止了。我该如何解决这个问题?
在此处输入图像描述
(分辨率为320x240(
[案例1(分辨率为 320x240(]
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;
using System;
public class Controller : MonoBehaviour {
public float RotateSpeed = 0.5f;
public RawImage InImage;
public RawImage OutImage;
WebCamTexture wct;
Texture2D outTexture;
void Awake()
{
#if UNITY_EDITOR
int width = 1280;
int height = 720;
#else
int width = 320;
int height = 240;
#endif
NativeLibAdapter.InitCV(width, height);
outTexture = new Texture2D(width, height, TextureFormat.RGBA32, false);
wct = new WebCamTexture(width, height);
wct.Play();
// Ignore it.
Debug.LogWarning("Foo Value in C++ is " + NativeLibAdapter.FooTest());
}
void Update()
{
if (wct.width > 100 && wct.height > 100)
{
Color32[] pixels = wct.GetPixels32();
GCHandle pixelHandle = GCHandle.Alloc(pixels, GCHandleType.Pinned);
IntPtr results = NativeLibAdapter.SubmitFrame(wct.width, wct.height, pixelHandle.AddrOfPinnedObject());
int bufferSize = wct.width * wct.height * 4;
byte[] rawData = new byte[bufferSize];
if (results != IntPtr.Zero)
{
Marshal.Copy(results, rawData, 0, bufferSize);
outTexture.LoadRawTextureData(rawData);
outTexture.Apply();
}
OutImage.texture = outTexture;
rawData = null;
pixelHandle.Free();
}
}
}
在此处输入图像描述 (其分辨率为 480x640。有很多噪音。
[案例2(分辨率为 480x640(]
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;
using System;
public class Controller : MonoBehaviour {
public float RotateSpeed = 0.5f;
public RawImage InImage;
public RawImage OutImage;
WebCamTexture wct;
Texture2D outTexture;
void Awake()
{
#if UNITY_EDITOR
int width = 1280;
int height = 720;
#else
int width = 480;
int height = 640;
#endif
NativeLibAdapter.InitCV(width, height);
outTexture = new Texture2D(width, height, TextureFormat.RGBA32, false);
wct = new WebCamTexture(width, height);
wct.Play();
// Ignore it.
Debug.LogWarning("Foo Value in C++ is " + NativeLibAdapter.FooTest());
}
void Update()
{
if (wct.width > 100 && wct.height > 100)
{
Color32[] pixels = wct.GetPixels32();
GCHandle pixelHandle = GCHandle.Alloc(pixels, GCHandleType.Pinned);
IntPtr results = NativeLibAdapter.SubmitFrame(wct.width, wct.height, pixelHandle.AddrOfPinnedObject());
int bufferSize = wct.width * wct.height * 4;
byte[] rawData = new byte[bufferSize];
if (results != IntPtr.Zero)
{
Marshal.Copy(results, rawData, 0, bufferSize);
outTexture.LoadRawTextureData(rawData);
outTexture.Apply();
}
OutImage.texture = outTexture;
rawData = null;
pixelHandle.Free();
}
}
}
它只是改变宽度和高度变量。
[情况3(设备上的分辨率为全屏(]
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;
using System;
public class Controller : MonoBehaviour {
public float RotateSpeed = 0.5f;
public RawImage InImage;
public RawImage OutImage;
WebCamTexture wct;
Texture2D outTexture;
void Awake()
{
#if UNITY_EDITOR
int width = 1280;
int height = 720;
#else
int width = 480;
int height = 640;
#endif
NativeLibAdapter.InitCV(Screen.width, Screen.height);
outTexture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGBA32, false);
wct = new WebCamTexture(Screen.width, Screen.height);
wct.Play();
// Ignore it.
Debug.LogWarning("Foo Value in C++ is " + NativeLibAdapter.FooTest());
}
void Update()
{
if (wct.width > 100 && wct.height > 100)
{
Color32[] pixels = wct.GetPixels32();
GCHandle pixelHandle = GCHandle.Alloc(pixels, GCHandleType.Pinned);
IntPtr results = NativeLibAdapter.SubmitFrame(wct.width, wct.height, pixelHandle.AddrOfPinnedObject());
int bufferSize = wct.width * wct.height * 4;
byte[] rawData = new byte[bufferSize];
if (results != IntPtr.Zero)
{
// here! App stops. I don't know why App stops.
Marshal.Copy(results, rawData, 0, bufferSize);
outTexture.LoadRawTextureData(rawData);
outTexture.Apply();
}
OutImage.texture = outTexture;
rawData = null;
pixelHandle.Free();
}
}
}
我正在使用:
- 集成开发地址
- 团结 2018.1.19f
- 安卓工作室 3.4.2
- OpenCV 3.4.3
您有以下代码初始化 CV 缓冲区:
#if UNITY_EDITOR
int width = 1280;
int height = 720;
#else
int width = 480;
int height = 640;
#endif
NativeLibAdapter.InitCV(Screen.width, Screen.height);
CV 缓冲区的初始化不足以处理 800x1280,因此内存可能不足。预计性能会随着大小的增加而下降,因为内存消耗更大(640x480 是 320x240 的 4 倍数据,因此每帧的垃圾收集和数据处理要多得多(。在将数据输入 CV 之前,您需要增加宽度和高度以包含最大分辨率,或限制从 GetPixels(( 检索的像素。
相关文章:
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 尝试导入pybind-opencv模块时出现libgtk错误
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 将OpenCV C++重写为EmguCV C#-如何使用指针
- OpenCV C++.快速计算混淆矩阵
- Unity在虚幻引擎4中的"Vector3.Slerp"等效C++?
- 在C++代码中包含opencv时,使用ctypes创建.so文件
- 哪些库可以通过Opencv调整曝光率
- 是什么导致了Unity 3D中的"错误线程异常"?
- 安装opencv失败-粘贴CMakeError.log的内容
- C++中的openCV Mat访问冲突
- OpenCV Android C++ imwrite not found
- 未定义的引用 .. 使用 OpenCV 编译 C++ 代码时,从命令行
- 将 OpenCV 与 CMAKE 中的项目一起构建为第三方库的正确方法
- 在 Android 上使用 OpenCV 和 Unity
- 如何在 Unity Android 应用程序中的 OpenCV 中使用 ARCore 相机图像
- 将图像从 Unity 传递到 opencv
- 为什么 Unity 在与 OpenCV 链接时无法加载安卓原生库