Обнаружение кулака с помощью Leap Motion SDK V2

Я хочу проверить, является ли рука в кадре скачкообразного движения кулаком.

Обычно предлагаемый метод состоит в том, чтобы искать hand.grabStrength со значением 1. Проблема в том, что значение прыгает до 1 даже с «Коготьподобной» рукой или чем-либо еще с очень слегка согнутыми пальцами.

Другой подход состоит в том, чтобы проверить на каждом пальце, является ли он extended. Но у этого есть аналогичная проблема: пальцы считаются вытянутыми, только если они полностью прямые. Поэтому, даже если я проверю, что все пальцы не вытянуты, возникает та же проблема, что и выше (когтеобразные руки распознаются как схваченные).

Объединение этих двух методов также не решает проблему, что неудивительно, учитывая, что они оба страдают от одних и тех же проблем.

Теперь у нас есть все кости каждого пальца с позициями и всем остальным. Но я понятия не имею, с чего начать с математики, чтобы определить, скручен ли палец.

В основном у меня есть эта установка на данный момент:

var controller = Leap.loop(function(frame){
   if(frame.hands.length>0){
       //we only look at the first available hand
       var hand = frame.hands[0];
       //we get the index finger only, but later on we should look at all 5 fingers.
       var index = hands.fingers[1];
       //after that we get the positions of the joints between the bones in a hand
       //the position of the metacarpal bone (i.e. the base of your hand)
       var carp = index.carpPosition;
       //the position of the joint on the knuckle of your hand
       var mcp = index.mcpPosition;
       //the position of the following joint, between the proximal and the intermediate bones
       var pip = index.pipPosition;
       //the position of the distal bone (the very tip of your finger)
       var dip = index.dipPosition;

       //and now we need the angle between each of those positions, which is where i'm stuck
   }
});

Итак, как мне получить угол между двумя этими позициями (карп к мкп, мкп к зернышку, зернышку к падению)? Любые идеи?


person Community    schedule 30.10.2014    source источник


Ответы (3)


Хорошо, я думаю, что нашел своего рода рабочий подход для обнаружения настоящего кулака, а не когтя.

Во-первых, вместо положения суставов нам нужны векторы расстояния для каждой кости.

Затем мы вычисляем скалярное произведение между пястной и проксимальной костью, а также скалярное произведение между проксимальной и промежуточной костью. Мы можем игнорировать дистальную кость, это не сильно меняет результат.

Суммируем все рассчитанные скалярные произведения (всего 10) и вычисляем среднее значение (делим на 10). Это даст нам значение от 0 до 1. Кулак меньше 0,5, а все, что выше, в основном не кулак.

Кроме того, вы также можете проверить количество вытянутых пальцев на руке и проверить, равно ли оно 0. Это гарантирует, что «большой палец вверх» и аналогичные позы с 1 цифрой не будут распознаны как кулак.

Вот моя реализация:

const minValue = 0.5;

var controller = Leap.loop(function(frame){
   if(frame.hands.length>0)
   {
      var hand = frame.hands[0];
      var isFist = checkFist(hand);
   }
});

function getExtendedFingers(hand){
   var f = 0;
   for(var i=0;i<hand.fingers.length;i++){
      if(hand.fingers[i].extended){
         f++;
      }
   }
   return f;
}

function checkFist(hand){
   var sum = 0;
   for(var i=0;i<hand.fingers.length;i++){
      var finger = hand.fingers[i];
      var meta = finger.bones[0].direction();
      var proxi = finger.bones[1].direction();
      var inter = finger.bones[2].direction();
      var dMetaProxi = Leap.vec3.dot(meta,proxi);
      var dProxiInter = Leap.vec3.dot(proxi,inter);
      sum += dMetaProxi;
      sum += dProxiInter
   }
   sum = sum/10;

   if(sum<=minValue && getExtendedFingers(hand)==0){
       return true;
   }else{
       return false;
   }
}

Хотя это работает так, как должно, я сомневаюсь, что это правильный и лучший подход для обнаружения Кулака. Поэтому, пожалуйста, если вы знаете лучший способ, опубликуйте его.


Решение работает отлично, есть ли шанс, что вы могли бы объяснить, почему вы делите на 10 и почему minValue равно 0,5? Спасибо!

Ну, это не очень хорошо работает, если честно. Скоро я начну работать над небольшим проектом, целью которого является улучшение обнаружения кулаков с помощью Leap Motion.

Что касается ваших вопросов, мы делим сумму на 10, потому что у нас есть 2 костных сустава на палец, с 5 пальцами. Нам нужно среднее значение из суммы всех этих вычислений, потому что не все пальцы будут расположены под одинаковым углом. Итак, нам нужно какое-то значение, которое объединяет все эти значения в одно: среднее значение. Учитывая, что всего у нас 10 вычислений (по 2 на каждый палец, 5 пальцев), делим сумму этих вычислений и готово. Мы получим значение от 0 до 1.

Относительно minValue: метод проб и ошибок. В моем проекте вместо этого я использовал значение 0,6. Это еще одна проблема этого подхода: в идеале плоская рука должна иметь значение почти 0, а кулак должен быть равен 1.

person Community    schedule 30.10.2014
comment
Не будет ли при этом также проходить сломанные в суставе пальцы, указывающие под углом противоположное направление, необходимое для сжатия кулака (как будто полностью не ограниченного диапазоном сустава)? : Д. съежиться - person Zéychin; 30.10.2014
comment
Я полагаю, что да, но эта математика слишком сложна для меня. :П - person ; 30.10.2014
comment
Я нашел хорошее решение, используя расстояние между каждым пальцем и ладонью. Подсчитайте сумму этих расстояний и проверьте, не ниже ли она определенного порога. - person whoabackoff; 27.04.2015
comment
@whoabackoff Опубликуйте то, что вы сделали, это может быть полезно для будущих читателей! - person FutureCake; 25.07.2018

Я знаю, что это старая тема, но если вы, ребята, все еще вокруг, ответ может быть проще, просто используя sphereRadius() ;

person Sam Poperyta    schedule 05.05.2019

Я обнаружил, что "grabStrength" хорош

person windyberry    schedule 25.05.2020
comment
Он довольно конкретно указал, что метод grabStrength не является хорошим подходом для его требований. Этот вопрос также довольно старый. Если что-то изменилось с 2014 года, пожалуйста, объясните, почему это работает сейчас. Прямо сейчас ваш ответ слишком короток, чтобы быть полезным для других... - person Pauloco; 25.05.2020