SciSharp/Numpy.NET

how can i convert python code into .net

choigawoon opened this issue · 3 comments

not good at english, any help will be appreciated.

my development environment,

  • windows11
  • unity 2020.3.23f1 + numpy.net + mediapipe + opencvforunity

i have the c# script converted from python`s.
my unity editor have no response after calling this line in c#.

var angle = np.arccos(np.einsum("nt,nt->n",input));

at that time, the call stack.

image

my c# script in unity,

        //joint = np.zeros((21, 3))
        var joint = np.zeros((21, 3), np.float32);
        try
        {
            //for j, lm in enumerate(res.landmark):
            //    joint[j] = [lm.x, lm.y, lm.z]
            for (var j = 0; j < 21; ++j)
            {
                joint[j] = new float[] { jointList.Landmark[j].X, jointList.Landmark[j].Y, jointList.Landmark[j].Z };
            }
      //# Compute angles between joints
      //v1 = joint[[0, 1, 2, 3, 0, 5, 6, 7, 0, 9, 10, 11, 0, 13, 14, 15, 0, 17, 18, 19],:] # Parent joint
      //v2 = joint[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],:] # Child joint
      //v = v2 - v1 # [20,3]
      //# Normalize v
      //v = v / np.linalg.norm(v, axis = 1)[:, np.newaxis]
      var v = np.zeros((20, 3), np.float32);
      for (var i = 0; i < 20; ++i)
      {
        v[i] = joint[childJointIndex[i]] - joint[parentJointIndex[i]];
      }
      var unitv = np.linalg.norm(v, axis: 1);
      //var unitv2 = unitv[":,np.newaxis"];
      var unitv2 = np.zeros((20, 1), np.float32);
      for (var i = 0; i < 20; ++i)
        unitv2[i] = unitv[i];
        //var unitv2 = np.array()
        v = v / unitv2;

      var input1 = np.zeros((15,3));
      var input2 = np.zeros((15,3));
      for (var i = 0; i < 15; ++i)
      {
        input1[i] = v[v1Index[i]];
        input2[i] = v[v2Index[i]];
      }
      var input = new NDarray[] { input1, input2 };

            //# Get angle using arcos of dot product
            //angle = np.arccos(np.einsum('nt,nt->n',
            //  v[[0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18],:],
            //  v[[1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18, 19],:])) # [15,]
            var angle = np.arccos(np.einsum("nt,nt->n",
                  input));

            //angle = np.degrees(angle) # Convert radian to degree
            angle = np.degrees(angle);
            NLogModuleWrapper.mediaPipeLogger.Info($"knn, angle({JsonConvert.SerializeObject(angle.GetData<float>(), Formatting.Indented)})");

            //# Inference gesture
            //data = np.array([angle], dtype = np.float32)
            var rawdata = np.array(angle, np.float32); // [1,15]

here's my python code.

            joint = np.zeros((21, 3))
            for j, lm in enumerate(res.landmark):
                joint[j] = [lm.x, lm.y, lm.z]

            # Compute angles between joints
            v1 = joint[[0,1,2,3,0,5,6,7,0,9,10,11,0,13,14,15,0,17,18,19],:] # Parent joint
            v2 = joint[[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],:] # Child joint
            v = v2 - v1 # [20,3]
            # Normalize v
            unitv = np.linalg.norm(v, axis=1)
            unitv2 = unitv[:, np.newaxis]
            v = v / unitv2

            input1 = v[[0,1,2,4,5,6,8,9,10,12,13,14,16,17,18],:]
            input2 = v[[1,2,3,5,6,7,9,10,11,13,14,15,17,18,19],:]
            # Get angle using arcos of dot product
            angle = np.arccos(np.einsum('nt,nt->n',
                input1,input2 
                )) # [15,]

            angle = np.degrees(angle) # Convert radian to degree

            # Inference gesture, 손이 무슨 모양인지 추론해보기
            data = np.array([angle], dtype=np.float32)
henon commented

Sorry I don't have time to look at your code. I can only tell you to read the Readme about Deadlocks and how to avoid them.

Sorry I don't have time to look at your code. I can only tell you to read the Readme about Deadlocks and how to avoid them.

thanks a lot, i've just added one line at the very beginning of my function and my problem is gone.

using var gil = Py.GIL();

at the startup, i do initialize intentionally

public static class MainProcess
{
  [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
  static void InitModules()
  {
    //Application.targetFrameRate = 60;
    NLogModuleWrapper.InitModule();
    if (false == PythonEngine.IsInitialized)
    {
      PythonEngine.AddShutdownHandler(() =>
      {
        Debug.LogError($"PythonEngine Shutdown");
      });

      //https://github.com/SciSharp/Numpy.NET#multi-threading-must-read
      //np쪽에서 뭔가 자동으로 초기화하는듯하니 이렇게 호출하지말고 다르게..
      //PythonEngine.Initialize();
      np.arange(1);
      PythonEngine.BeginAllowThreads();
      
      Debug.LogError($"PythonEngine Initialize");
    }
    else
    {
      Debug.LogError($"PythonEngine Already Initialized");
    }
  }

  static bool quit = false;
  public static void ShutDown()
  {
    if (PythonEngine.IsInitialized)
    {
      if (false == quit)
      {
        // crash here
        //PythonEngine.Shutdown();
        quit = true;
      }
      Debug.LogError($"PythonEngine Shutdown, {quit}");
    }

    Debug.LogError($"MainProcess Shutdown, {quit}");
  }
}