Unity3D的OpenCV dll调用导致FPS下降
OpenCV dll calls from Unity3D lead to FPS drop
我想在Unity3D中识别ArUco标记,并在它们的位置上附加一个GameObject。我知道资产商店里有软件包,但当其他人使用它时,我正在寻找一个免费的现有解决方案,或者自己尝试。
ArucoUnity检测效果很好,但Unity在访问rvecs
、tvecs
的数据时崩溃。当c++方法au_cv_Vec3d_get(CppPtr, i, CppPtr);
被称为时,错误发生在Vec3d
类的Get(int i)
中的某个位置
OpenCv加Unity这个实现似乎并不完整,因为不存在EstimatePoseSingleMarker
或类似的函数来获得rvecs
和tvecs
。最后一次更新也是在2019年1月。
由于Unity(C#(提供了访问非托管代码的可能性,我遵循了这篇很棒的教程,并将cv::VideoCaputre
流转发给了Unity。唯一出现的问题是FPS下降到35-40左右,而通常我会达到90-100左右。
C#代码:
void Update()
{
MatToTexture2D();
image.texture = tex;
}
void MatToTexture2D()
{
OpenCVInterop.GetRawImageBytes(pixelPtr);
//Update the Texture2D with array updated in C++
tex.SetPixels32(pixel32);
tex.Apply();
}
C++代码:
extern "C" void __declspec(dllexport) __stdcall GetRawImageBytes(unsigned char* data)
{
_capture >> _currentFrame;
cv::Mat resizedMat(camHeight, camWidth, _currentFrame.type());
cv::resize(_currentFrame, resizedMat, resizedMat.size(), cv::INTER_CUBIC);
//Convert from RGB to ARGB
cv::Mat argb_img;
cv::cvtColor(resizedMat, argb_img, cv::COLOR_BGR2BGRA);
std::vector<cv::Mat> bgra;
cv::split(argb_img, bgra);
std::swap(bgra[0], bgra[3]);
std::swap(bgra[1], bgra[2]);
std::memcpy(data, argb_img.data, argb_img.total() * argb_img.elemSize());
}
原因似乎是第一行_capture >> _currentFrame;
,但由于其他项目也必须这样做(至少我想是这样(,我想知道是否还有其他原因。如果我不能设法解决这个问题,我必须寻找其他方法。
只是添加到火星上/在火星上建造的答案:
对于线程问题,我实际上会使用线程保存ConcurrentStack<Color32[]>
。堆栈是"后进|先出"的,因此返回的第一个项始终是线程添加的最后一个图像数据。
- 线程使用
Push(pixel32)
添加带有图像数据的新条目 - 在
Update
中,仅使用最新条目(TryPop
(来更新纹理 - 您忽略的其余部分(
Clear
(
所以类似的东西
// the OpenCV thread will add(push) entries
// the Unity main thread will work on the entries
private ConcurrentStack<Color32[]> stack = new ConcurrentStack<Color32[]>();
public RawImage image;
public Texture2D tex;
private Thread thread;
void Start()
{
// Wherever you get your tex from
tex = new Texture2D(...);
// it should be enough to do this only once
// the texture stays the same, you only update its content
image.texture = tex;
}
// do things in OnEnable so everytime the object gets enabled start the thread
void OnEnable()
{
stack.Clear();
if(thread != null)
{
thread.Abort();
}
thread = new Thread(MatToTexture2D);
thread.Start();
}
void Update()
{
// here in the main thread work the stack
if (stack.TryPop(out var pixels32))
{
// Only use SetPixels and Apply when really needed
tex.SetPixels32(pixels32);
tex.Apply();
}
// Erase older data
stack.Clear();
}
// Make sure to terminate the thread everytime this object gets disabled
private void OnDisable()
{
if(thread == null) return;
thread.Abort();
thread = null;
}
// Runs in a thread!
void MatToTexture2D()
{
while(true)
{
try
{
// Do what you already have
OpenCVInterop.GetRawImageBytes(pixelPtr);
// However you convert the pixelPtr into Color32
Color32[] pixel32 = GetColorArrayFromPtr(pixelPtr);
// Now add this data to the stack
stack.Push(pixel32);
}
catch (ThreadAbortException ex)
{
// This exception is thrown when calling Abort on the thread
// -> ignore the exception since it is produced on purpose
}
}
}
如果我没有记错的话,用于获取图像(_capture >> _currentFrame;
(的C++调用是阻塞/同步的,这意味着代码在实际检索图像之前不会继续。您可能希望异步运行MatToTexture2D
代码。※这意味着你的帧速率将高于你的图像检索率。
根据需要连续运行MatToTexture2D
函数,更新tex
。然后继续将纹理设置为最新的tex
,这可能是连续2-3帧的相同值。
编辑:@对于编程方面,derHugo的答案要可靠得多,所以我将隐藏这一部分。上面解释了基本问题,derHugo的工作比我的伪代码好得多:(
- 在main()之外初始化std::vector会导致性能下降(多线程)
- phytec phyBOARD iMX-6在从闪存而不是SD卡运行qt5 opengles应用程序时表现不佳(FPS减半
- 海湾合作委员会 ARM 性能下降
- 使用 sfml 计算 FPS
- 从 OpenCV 3 切换到 OpenCV 4 会导致网络摄像头以最大 5 fps 的速度录制,而不是通常的 30 f
- 使用双包装器类进行位操作(C++、clang)修复性能下降问题
- 当相机接近模型时,SSAO样本内核会导致性能下降?
- Unity3D的OpenCV dll调用导致FPS下降
- 弄清楚这段代码是怎么回事(递归下降案例研究)
- 直接显示返回错误的帧速率 FPS
- 当我在每一帧中多次使用正则表达式时,FPS 下降了
- C++、OpenCV和Kinect:处理速度下降
- 如何在 GLFW 窗口中以固定的 FPS 渲染?
- Opencv:相同的捕获代码在高端笔记本电脑上提供低 FPS,在 TX1 上提供高 FPS
- (可选)下降嵌套结构
- 为什么我的梯度下降算法不收敛?(用于逻辑回归)
- 从BEAST.1.0.0-B66到BOOST.1.67.0.BEAST的端口上的性能下降
- DirectX矩阵:相对于面向方向的转换(例如在FPS中)
- QTREEWIDGET子分类,停止下降指示器显示给定有不必要的DropIndicatorPosition
- c++ 11:为什么这个范围循环会使FPS下降35