private IEnumerator ExecuteModelAsync()
{
if(Lock)
{
yield return null;
}
// Create input and Execute model
yield return _worker.StartManualSchedule(inputs);
if (!Lock)
{
// Get outputs
for (var i = 2; i < _model.outputs.Count; i++)
{
b_outputs[i] = _worker.PeekOutput(_model.outputs[i]);
}
// Get data from outputs
//heatMap2D = b_outputs[0].data.Download(b_outputs[0].shape);
//offset2D = b_outputs[1].data.Download(b_outputs[1].shape);
offset3D = b_outputs[2].data.Download(b_outputs[2].shape);
heatMap3D = b_outputs[3].data.Download(b_outputs[3].shape);
PredictPose();
fpsCounter++;
}
}
Вызывается в цикле Update():
ОбновитьVNectModel();
И UpdateVNectModel = new UpdateVNectModelDelegate(UpdateVNectAsync); Делегат вызывает UpdateVNectAsync
Сопрограмма ExecuteModelAsync включена в UpdateVNectAsync,
Эта сопрограмма использует оператор yield return для возврата результата типа IEnumerable. Оператор yield return не прерывает выполнение метода, а приостанавливает выполнение метода и возвращает вызывающему объекту текущее значение. Когда вызывающий объект снова запрашивает следующее значение, метод продолжает выполнение с того места, где он остановился, пока не встретит следующий оператор yield return или конец метода.
_worker.StartManualSchedule(inputs) анализирует модель, а inputs представляет собой набор видеоизображений.
_worker.StartManualSchedule, после завершения вывод будет сохранен в _worker, а вывод будет извлечен вызовом _worker.PeekOutput и помещен в b_outputs
В соответствии с формой каждого вывода загрузите его данные в соответствующий массив с плавающей запятой (offset3D и heatMap3D).
Вызовите метод PredictPose, вычислите трехмерные координаты каждой точки стыка по значениям в массивах offset3D иheatMap3D и сохраните их в массивеjointPoints.
Наконец, добавьте единицу в переменную fpsCounter, указывающую, что модель была выполнена один раз. Эта переменная может использоваться для подсчета частоты выполнения модели.
-------------------------------------------------- -------------------------------------------------- --------------------------
Функция метода PredictPose заключается в прогнозировании трехмерного положения человеческого тела на основе трехмерного смещения и тепловой карты, выводимых моделью, а также в фильтрации и сглаживании положения каждой точки соединения. В частности, он выполняет следующие действия:
- Сначала определяются некоторые переменные, такие как score, filterWindow, cubeOffsetSquared и т. д., для последующих вычислений.
- Затем используйте цикл для обхода каждой точки соединения (JointNum = 19) и найдите позицию максимальной вероятности (maxXIndex, maxYIndex, maxZIndex) каждой точки соединения на трехмерной тепловой карте. Затем по трехмерному массиву смещений (offset3D) и размеру тепловой карты (HeatMapCol = 32) вычислить координаты каждой точки стыка в трехмерном пространстве (jp.Now3D.x, jp.Now3D.y, jp.Now3D.z) и добавьте его в фильтр. При этом значение вероятности (jp.Score3D) каждой совместной точки накапливается и используется для расчета среднего балла (EstimatedScore).
- Затем, основываясь на некоторых известных положениях точек сочленения, рассчитайте положение некоторых неизвестных точек сочленений, таких как бедро, шея, голова и позвоночник. Здесь используются некоторые простые геометрические методы, такие как взятие середины двух точек или вычисление вектора нормали треугольника (TriangleNormal).
- Наконец, положение каждой точки соединения фильтруется и сглаживается с помощью фильтра Калмана (KalmanUpdate) и фильтра нижних частот (NOrderLPF), а также обновляется видимость (jp.Visibled) каждой точки соединения. Затем по углу ориентации человеческого тела (frwdAngle) оценивается необходимость обновления модели позы человеческого тела (VNectModel.IsPoseUpdate) и устанавливаются соответствующие пороги (ForwardThreshold и BackwardThreshold).