来源: 日本中二少年教你用姿势估计把自己变成3D人物,动作实时同步,iOS上也能实现
// Properties for onnx and estimationprivate Net Onnx;private Mat[] outputs = new Mat[4];private const int inputImageSize = 224;private const int JointNum = 24;private const int HeatMapCol = 14;private const int HeatMapCol_Squared = 14 * 14;private const int HeatMapCol_Cube = 14 * 14 * 14;char[] heatMap2Dbuf = new char[JointNum * HeatMapCol_Squared * 4];float[] heatMap2D = new float[JointNum * HeatMapCol_Squared];char[] offset2Dbuf = new char[JointNum * HeatMapCol_Squared * 2 * 4];float[] offset2D = new float[JointNum * HeatMapCol_Squared * 2];char[] heatMap3Dbuf = new char[JointNum * HeatMapCol_Cube * 4];float[] heatMap3D = new float[JointNum * HeatMapCol_Cube];char[] offset3Dbuf = new char[JointNum * HeatMapCol_Cube * 3 * 4];float[] offset3D = new float[JointNum * HeatMapCol_Cube * 3];public void InitONNX(){Onnx = Net.ReadNetFromONNX(Application.dataPath + @"\MobileNet3D2.onnx");for (var i = 0; i < 4; i++) outputs[i] = new Mat();}/// <summary>/// Predict/// </summary>/// <param name="img"></param>public void Predict(Mat img){var blob = CvDnn.BlobFromImage(img, 1.0 / 255.0, new OpenCvSharp.Size(inputImageSize, inputImageSize), 0.0, false, false);Onnx.SetInput(blob);Onnx.Forward(outputs, new string[] { "369", "373", "361", "365" });// copy 2D outputsMarshal.Copy(outputs[2].Data, heatMap2Dbuf, 0, heatMap2Dbuf.Length);Buffer.BlockCopy(heatMap2Dbuf, 0, heatMap2D, 0, heatMap2Dbuf.Length);Marshal.Copy(outputs[3].Data, offset2Dbuf, 0, offset2Dbuf.Length);Buffer.BlockCopy(offset2Dbuf, 0, offset2D, 0, offset2Dbuf.Length);for (var j = 0; j < JointNum; j++){var maxXIndex = 0;var maxYIndex = 0;jointPoints[j].score2D = 0.0f;for (var y = 0; y < HeatMapCol; y++){for (var x = 0; x < HeatMapCol; x++){var l = new List<int>();var v = heatMap2D[(HeatMapCol_Squared) * j + HeatMapCol * y + x];if (v > jointPoints[j].score2D){jointPoints[j].score2D = v;maxXIndex = x;maxYIndex = y;}}}jointPoints[j].Pos2D.x = (offset2D[HeatMapCol_Squared * j + HeatMapCol * maxYIndex + maxXIndex] + maxXIndex / (float)HeatMapCol) * (float)inputImageSize;jointPoints[j].Pos2D.y = (offset2D[HeatMapCol_Squared * (j + JointNum) + HeatMapCol * maxYIndex + maxXIndex] + maxYIndex / (float)HeatMapCol) * (float)inputImageSize;}// copy 3D outputsMarshal.Copy(outputs[0].Data, heatMap3Dbuf, 0, heatMap3Dbuf.Length);Buffer.BlockCopy(heatMap3Dbuf, 0, heatMap3D, 0, heatMap3Dbuf.Length);Marshal.Copy(outputs[1].Data, offset3Dbuf, 0, offset3Dbuf.Length);Buffer.BlockCopy(offset3Dbuf, 0, offset3D, 0, offset3Dbuf.Length);for (var j = 0; j < JointNum; j++){var maxXIndex = 0;var maxYIndex = 0;var maxZIndex = 0;jointPoints[j].score3D = 0.0f;for (var z = 0; z < HeatMapCol; z++){for (var y = 0; y < HeatMapCol; y++){for (var x = 0; x < HeatMapCol; x++){float v = heatMap3D[HeatMapCol_Cube * j + HeatMapCol_Squared * z + HeatMapCol * y + x];if (v > jointPoints[j].score3D){jointPoints[j].score3D = v;maxXIndex = x;maxYIndex = y;maxZIndex = z;}}}}jointPoints[j].Now3D.x = (offset3D[HeatMapCol_Cube * j + HeatMapCol_Squared * maxZIndex + HeatMapCol * maxYIndex + maxXIndex] + (float)maxXIndex / (float)HeatMapCol) * (float)inputImageSize;jointPoints[j].Now3D.y = (float)inputImageSize - (offset3D[HeatMapCol_Cube * (j + JointNum) + HeatMapCol_Squared * maxZIndex + HeatMapCol * maxYIndex + maxXIndex] + (float)maxYIndex / (float)HeatMapCol) * (float)inputImageSize;jointPoints[j].Now3D.z = (offset3D[HeatMapCol_Cube * (j + JointNum * 2) + HeatMapCol_Squared * maxZIndex + HeatMapCol * maxYIndex + maxXIndex] + (float)(maxZIndex - 7) / (float)HeatMapCol) * (float)inputImageSize;}}
public void InitONNX(){Onnx = Net.ReadNetFromONNX(Application.dataPath + @"\MobileNet3D2.onnx");for (var i = 0; i < 4; i++) outputs[i] = new Mat();}
public void Predict(Mat img){var blob = CvDnn.BlobFromImage(img, 1.0 / 255.0, new OpenCvSharp.Size(inputImageSize, inputImageSize), 0.0, false, false);Onnx.SetInput(blob);Onnx.Forward(outputs, new string[] { "369", "373", "361", "365" });// copy 2D outputsMarshal.Copy(outputs[2].Data, heatMap2Dbuf, 0, heatMap2Dbuf.Length);Buffer.BlockCopy(heatMap2Dbuf, 0, heatMap2D, 0, heatMap2Dbuf.Length);Marshal.Copy(outputs[3].Data, offset2Dbuf, 0, offset2Dbuf.Length);Buffer.BlockCopy(offset2Dbuf, 0, offset2D, 0, offset2Dbuf.Length);
Mikel