Я пытаюсь выполнить некоторую обработку изображений в Unity и OpenCV в фоновом режиме, потому что для ее завершения требуется около 60 мс-100 мс, и приложение сильно замедляется при выполнении в главном потоке.
Я делаю это внутриобратный вызов «доступен кадр камеры», который выполняется 30 раз в секунду.Я использую «Параллель задач» из хранилища активов.
Код C #
private const int numMaximumThreads = 3;
private volatile int currentNumberOfWorkingThreads = 0;
unsafe private void OnRawVideoFrameAvailableYUV(MLCameraResultExtras resultExtras, YUVFrameInfo frameInfo, MLCameraFrameMetadata frameMetadata)
{
//only have a maximum of 3 threads
if(currentNumberOfWorkingThreads < numMaximumThreads)
{
//run on background
UnityTask.Run(() =>
{
currentNumberOfWorkingThreads++;
MLCamera.GetFramePose(resultExtras.VcamTimestampUs * 1000, out translationMatrix);
float x = 0, y = 0, z = 0, rx = 0, ry = 0, rz = 0;
//fix the bytearray for OpenCV on c++ side
fixed (byte* yBuffer = frameInfo.Y.Data)//camera uses YUV instead of RGB
{
fixed (byte* uBuffer = frameInfo.U.Data)
{
fixed (byte* vBuffer = frameInfo.V.Data)
{ //call OpenCV / c++ function
Interop.Detect((IntPtr)yBuffer, (IntPtr)uBuffer, (IntPtr)vBuffer, camWidth, camHeight, ref x, ref y, ref z, ref rx, ref ry, ref rz);
}
}
}
//r to rz are translation and rotation vectors that OpenCV returns
return new float[6] { x, y, z, rx, ry, rz };
//after completion, move gameobjects on unity main thread
}).ContinueOnUIThread((r) =>
{
if (!(r.Result[0] == 0 && r.Result[3] == 0))//very probably not detected when x and rx are 0
{
Utils.UpdatePosition(r.Result[0], r.Result[1], r.Result[2]);
Utils.UpdateRotation(r.Result[3], r.Result[4], r.Result[5]);
Utils.PlaceArucoObject(markerCube, virtualCamera, translationMatrix);
}
currentNumberOfWorkingThreads--;
});
}
}
Моя функция взаимодействия выглядит следующим образом:
C # Code
[DllImport("ml_aruco_api")]
internal static extern void Detect(IntPtr yBuffer, IntPtr uBuffer, IntPtr vBuffer, int width, int height, ref float x, ref float y, ref float z, ref float rx, ref float ry, ref float rz);
И, наконец, сторона OpenCV C ++ (сокращенная)
extern "C" void Detect(unsigned char* yBuffer, unsigned char* uBuffer, unsigned char* vBuffer, int width, int height, float& x, float& y, float& z, float& rx, float& ry, float& rz) {
//(reconstruct image and detect markers on it...)
if (detected) {
x = m4.Tvec.at<float>(0, 0);
y = m4.Tvec.at<float>(0, 1);
z = m4.Tvec.at<float>(0, 2);
rx = m4.Rvec.at<float>(0, 0);
ry = m4.Rvec.at<float>(0, 1);
rz = m4.Rvec.at<float>(0, 2);
}
else {
x = y = z = rx = ry = rz = 0;
}
}
Все это работает в течение нескольких секунд, а затем вылетает,И он не работает на скорости 60 кадров в секунду, а сильно колеблется около 15-30 кадров в секунду.Я не очень разбираюсь в обработке памяти между C # и C ++, так что, возможно, здесь проблема.Я также не понимаю, почему приложение работает так медленно, когда оно предположительно работает в фоновом потоке.Я также попробовал систему работы Unity безрезультатно, она работала без сбоев, но медленно.
Может ли кто-нибудь указать мне правильное направление?
Редактировать: я ограничил количество максимальных потоковк 1, и это остановило сбой.FPS сейчас около 30-40, и мне интересно, почему он не на 60 кадров в секунду.Комментирование функции Interop.Detect () дает мне 60. Должен ли я выполнять потоковую обработку самой функции OpenCV?