gesture_recognizer.py 34 KB
Newer Older
import mediapipe as mp
import cv2

def gesture_search(fingers_statuses: dict, finger_count: dict) -> dict:
  """
  Функция определяет, какой жест показывает каждая из рук

  Параметры
  ----------
  fingers_statuses: словарь, хранящий информацию о том согнут ли палец
  finger_count: cловарь для хранения кол-ва пальцев, которые не согнуты,
    на каждой из рук 

  Возвращаемые значения
  ----------
  hands_gestures: словарь, содержащий информацию о том, какой жест показывает 
    каждая из рук
  """    
    
  hands_labels = ['RIGHT', 'LEFT']
    
  # Cловарь, содержащий информацию о том, какой жест показан для каждой из рук
  hands_gestures = {'RIGHT': "UNKNOWN", 'LEFT': "UNKNOWN"}
  
  for hand_index, hand_label in enumerate(hands_labels):  # Проходим по всем 
                                                          # найденным рукам

    if (finger_count[hand_label] == 2 and  # Если 2 пальца "открыты", и это
        fingers_statuses[hand_label+'_MIDDLE'] and  # средний и указательный
        fingers_statuses[hand_label+'_INDEX']):    
      hands_gestures[hand_label] = "V sign"  # Значит показывается жест виктория

    elif (finger_count[hand_label] == 3 and  # Если 3 пальца "открыты", и это
          fingers_statuses[hand_label+'_INDEX'] and  # указательный,
          fingers_statuses[hand_label+'_MIDDLE'] and  # средний и безымянный
          fingers_statuses[hand_label+'_RING']):
      hands_gestures[hand_label] = "Three"  # Значит показываются 3 пальца 

    elif (finger_count[hand_label] == 4 and  # Если 4 пальца "открыты", и это 
          fingers_statuses[hand_label+'_INDEX'] and  # указательный,
          fingers_statuses[hand_label+'_MIDDLE'] and  # средний,  
          fingers_statuses[hand_label+'_RING'] and  # безымянный и мизинец
          fingers_statuses[hand_label+'_PINKY']):
      hands_gestures[hand_label] = "Four"  # Значит показываются 4 пальца      

    elif (finger_count[hand_label] == 1 and  # Если 1 палец "открыт" и это 
          fingers_statuses[hand_label+'_INDEX']):  # указательный палец
      # Значит на что-то показывают пальцем
      hands_gestures[hand_label] = "Pointing with index finger" 

    elif ((finger_count[hand_label] == 2 and  # Если 2 пальца "открыты" и это
           fingers_statuses[hand_label+'_INDEX'] and  # указательный и большой
           fingers_statuses[hand_label+'_THUMB']) or  # или 
          (finger_count[hand_label] == 3 and  # 3 пальца "открыты" и это
           fingers_statuses[hand_label+'_INDEX'] and  # указательный,
           fingers_statuses[hand_label+'_MIDDLE'] and  # средний и большой 
           fingers_statuses[hand_label+'_THUMB'] )):
      hands_gestures[hand_label] = "Finger gun"  # Значит показывается пистолет

    elif finger_count[hand_label] == 5:  # Если "открыты" 5 пальцев 
      hands_gestures[hand_label] = "Five"  # Значит показываются 5 пальцев
                                           # (знак "Дай пять!")
            
  return hands_gestures

def finger_counter(lect_height: int,
                   lect_width: int,
                   found_hands: type,
                   mp_hands) -> tuple:
  """
  Функция определяет, какие пальцы "открыты", а какие нет, в зависимости
    от положения рук

  Параметры
  ----------
  lect_height: высота видео
  lect_width: ширина видео
  found_hands: найденные ориентиры рук
  mp_hands: класс рук в mediapipe

  Возвращаемые значения
  ----------
  finger_count: кол-во "открытых" пальцев для каждой из рук
  fingers_statuses: указание на то "открыт" или "закрыт" палец для каждого 
    пальца каждой руки
  """    

  finger_count = {'RIGHT': 0, 'LEFT': 0}  # Словарь для хранения кол-ва 
                                          # "открытых" пальцев на каждой из рук 
                                     
  # Храним индексы кончиков пальцев (кроме большого) в списке 
  fingers_tips_ids = [mp_hands.HandLandmark.INDEX_FINGER_TIP,
                        mp_hands.HandLandmark.MIDDLE_FINGER_TIP,
                        mp_hands.HandLandmark.RING_FINGER_TIP,
                        mp_hands.HandLandmark.PINKY_TIP]

  # Словарь, хранящий информацию о том согнут ли палец
  fingers_statuses = {'RIGHT_THUMB': False, 'RIGHT_INDEX': False,
                        'RIGHT_MIDDLE': False, 'RIGHT_RING': False,
                        'RIGHT_PINKY': False, 'LEFT_THUMB': False, 
                        'LEFT_INDEX': False, 'LEFT_MIDDLE': False,
                        'LEFT_RING': False, 'LEFT_PINKY': False}
    
  # Проходим по всем найдем рукам 
  for hand_i, hand_inf in enumerate(found_hands.multi_handedness):

    hand_label = hand_inf.classification[0].label  #Right или Left
    hand_landmarks =  found_hands.multi_hand_landmarks[hand_i]  # Ориентиры 
                                                                # найденной руки 

    #Записываем ориентиры, которые будем в дальнейшем использовать
    thumb_tip = hand_landmarks.landmark[mp_hands.HandLandmark.THUMB_TIP]
    thumb_cmc = hand_landmarks.landmark[mp_hands.HandLandmark.THUMB_CMC]
    thumb_mcp = hand_landmarks.landmark[mp_hands.HandLandmark.THUMB_MCP]
    wrist = hand_landmarks.landmark[mp_hands.HandLandmark.WRIST]
    midle_tip = hand_landmarks.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_TIP]
    pinky_tip = hand_landmarks.landmark[mp_hands.HandLandmark.PINKY_TIP]

    # Проходим по индексам кончиков пальцев (кроме большого)
    for tip_i in fingers_tips_ids:

      finger_name = tip_i.name.split("_")[0]  # Название текущего пальца 
            
      if (hand_label=='Right' and  # Если рука правая, развернута ладонью
          thumb_cmc.x < wrist.x and  # по направлению к камере и указательный
          midle_tip.y < wrist.y):  # палец направлен наверх
        if (hand_landmarks.landmark[tip_i].y <  # Проверяем, что палец не согнут
            hand_landmarks.landmark[tip_i - 2].y):
          fingers_statuses[hand_label.upper()+"_"+finger_name] = True                
          finger_count[hand_label.upper()] += 1

      elif (hand_label=='Right' and  # Если рука правая, развернута обратной 
            wrist.x < thumb_cmc.x  and  # стороной ладони на камеру и 
            wrist.y < midle_tip.y):  # указательный палец направлен вниз 
        if (hand_landmarks.landmark[tip_i].y >  # Проверяем, что палец не согнут
            hand_landmarks.landmark[tip_i - 2].y):  
          fingers_statuses[hand_label.upper()+"_"+finger_name] = True                
          finger_count[hand_label.upper()] += 1

      elif (hand_label=='Right' and  # Если рука правая, развернута обратной
            wrist.x < thumb_cmc.x  and  # стороной ладони на камеру и 
            midle_tip.y < wrist.y):  # указательный палец направлен наверх
        if (hand_landmarks.landmark[tip_i].y <  # Проверяем, что палец не согнут
            hand_landmarks.landmark[tip_i - 2].y):
          fingers_statuses[hand_label.upper()+"_"+finger_name] = True                
          finger_count[hand_label.upper()] += 1

      elif (hand_label=='Right' and  # Если рука правая, развернута ладонью
            wrist.x > thumb_cmc.x  and  # по направлению к камере и указательный
            midle_tip.y > wrist.y):  # палец направлен вниз
        if (hand_landmarks.landmark[tip_i].y >  # Проверяем, что палец не согнут 
            hand_landmarks.landmark[tip_i - 2].y):
          fingers_statuses[hand_label.upper()+"_"+finger_name] = True                
          finger_count[hand_label.upper()] += 1

      elif (hand_label=='Left' and  # Если рука левая, развернута ладонью
            thumb_cmc.x > wrist.x and  # по направлению к камере и указательный
            midle_tip.y < wrist.y):  # палец направлен вверх
        if (hand_landmarks.landmark[tip_i].y <  # Проверяем, что палец не согнут
            hand_landmarks.landmark[tip_i - 2].y):
          fingers_statuses[hand_label.upper()+"_"+finger_name] = True                
          finger_count[hand_label.upper()] += 1

      elif (hand_label=='Left' and  # Если рука левая, развернута ладонью от
            wrist.x > thumb_cmc.x and  # камеры и указательный палец
            wrist.y < midle_tip.y):  # направлен вниз
        if (hand_landmarks.landmark[tip_i].y >  # Проверяем, что палец не согнут
            hand_landmarks.landmark[tip_i - 2].y):  
          fingers_statuses[hand_label.upper()+"_"+finger_name] = True                
          finger_count[hand_label.upper()] += 1

      elif (hand_label=='Left' and  # Если рука левая, развернута ладонью от
            wrist.x > thumb_cmc.x  and  # камеры и указательный палец
            midle_tip.y < wrist.y):  # направлен вверх
        if (hand_landmarks.landmark[tip_i].y <  # Проверяем, что палец не согнут
            hand_landmarks.landmark[tip_i - 2].y):
          fingers_statuses[hand_label.upper()+"_"+finger_name] = True                
          finger_count[hand_label.upper()] += 1

      elif (hand_label=='Left' and  # Если рука левая, развернута ладонью к
            wrist.x < thumb_cmc.x  and  # камере и указательный палец
            midle_tip.y > wrist.y):  #  направлен вниз
        if (hand_landmarks.landmark[tip_i].y >  # Проверяем, что палец не согнут
            hand_landmarks.landmark[tip_i - 2].y):
          fingers_statuses[hand_label.upper()+"_"+finger_name] = True                
          finger_count[hand_label.upper()] += 1

    if (hand_label=='Right' and  # Если рука правая, развернута ладонью к камере
        thumb_cmc.x < wrist.x and  # и указательный палец направлен вверх
        midle_tip.y < wrist.y):
      if thumb_tip.x < thumb_mcp.x:  # Проверяем, что большой палец не согнут
        fingers_statuses[hand_label.upper()+"_THUMB"] = True    
        finger_count[hand_label.upper()] += 1

    elif (hand_label=='Right' and  # Если рука правая, развернута обратной 
          wrist.x < thumb_cmc.x and  # стороной ладони на камеру и   
          midle_tip.y > wrist.y):  # указательный палец направлен вниз 
      if thumb_mcp.x > thumb_tip.x:  # Проверяем, что большой палец не согнут
        fingers_statuses[hand_label.upper()+"_THUMB"] = True    
        finger_count[hand_label.upper()] += 1

    elif (hand_label=='Right' and  # Если рука правая, развернута обратной  
          wrist.x < thumb_cmc.x  and  # стороной ладони на камеру и 
          midle_tip.y < wrist.y):  # указательный палец направлен вверх
      if thumb_mcp.x < thumb_tip.x:  # Проверяем, что большой палец не согнут
        fingers_statuses[hand_label.upper()+"_THUMB"] = True    
        finger_count[hand_label.upper()] += 1

    elif (hand_label=='Right' and  # Если рука правая, развернута ладонью
          wrist.x > thumb_cmc.x  and  # по направлению к камере и указательный
          midle_tip.y > wrist.y):  # палец направлен вниз
      if thumb_mcp.x < thumb_tip.x:  # Проверяем, что большой палец не согнут
        fingers_statuses[hand_label.upper()+"_THUMB"] = True    
        finger_count[hand_label.upper()] += 1

    elif (hand_label=='Left' and  # Если рука левая, развернута ладонью 
          thumb_cmc.x > wrist.x and  # по направлению к камере и указательный
          midle_tip.y < wrist.y):  # палец направлен вверх
      if thumb_tip.x > thumb_mcp.x:  # Проверяем, что большой палец не согнут
        fingers_statuses[hand_label.upper()+"_THUMB"] = True    
        finger_count[hand_label.upper()] += 1

    elif (hand_label=='Left' and  # Если рука левая, развернута ладонью от  
          wrist.x > thumb_cmc.x and  # камеры и указательный палец
          midle_tip.y > wrist.y):  # направлен вниз
      if thumb_mcp.x < thumb_tip.x:  # Проверяем, что большой палец не согнут
        fingers_statuses[hand_label.upper()+"_THUMB"] = True    
        finger_count[hand_label.upper()] += 1

    elif (hand_label=='Left' and  # Если рука левая, развернута ладонью от
          wrist.x > thumb_cmc.x  and  # камеры и указательный палец
          midle_tip.y < wrist.y):  # направлен вверх
      if thumb_mcp.x > thumb_tip.x:  # Проверяем, что большой палец не согнут
        fingers_statuses[hand_label.upper()+"_THUMB"] = True    
        finger_count[hand_label.upper()] += 1

    elif (hand_label=='Left' and  # Если рука левая, развернута ладонью к
          wrist.x < thumb_cmc.x and  # камере и указательный палец
          midle_tip.y > wrist.y):  # направлен вниз 
      if thumb_mcp.x > thumb_tip.x:  # Проверяем, что большой палец не согнут
        fingers_statuses[hand_label.upper()+"_THUMB"] = True    
        finger_count[hand_label.upper()] += 1

  return finger_count, fingers_statuses

def codec_selection(res_video_name: str, res_video_codec: str) -> int:
  """
  Функция позволяет выбрать подходящий кодек для записи результируещего видео

  Параметры
  ----------
  res_video_name: имя видео с отмеченными жестами
  res_video_codec: кодек для записи видео с отмеченными жестами

  Возвращаемые значения
  ----------
  fourcc-код для кодека
  """

  _, res_vid_extension = res_video_name.split(".")  # Расширение видео

  if res_video_codec is None:  # Задаем кодеки видео с выделенными 
                               # границами и лицом для основных
                               # расширений по умолчанию
    if res_vid_extension == 'mp4':
      return cv2.VideoWriter_fourcc(*'mp4v')
    elif res_vid_extension == 'avi':
      return cv2.VideoWriter_fourcc(*'MJPG')
    elif res_vid_extension == 'webm':
      return cv2.VideoWriter_fourcc(*'VP80')
    else: 
      return None
  else:
    return cv2.VideoWriter_fourcc(*res_video_codec)

def time_calculation(start_frame: int, fps: float) -> tuple:
  """
  По числу кадров вычисляется временной промежуток,
  в который лектор начинает показывать жест

  Параметры
  ----------
  start_frame: номер кадра, в который лектор начинает показывать жест
  fps: число кадров в секунде видео

  Возвращаемые значения
  ----------
  start_time: строка, содержащая время, в которое лектор начинает 
    показывать жест
  """

  start_hours = int((start_frame / fps) // 60 // 60)
  start_minutes = int((start_frame / fps) // 60 - start_hours * 60)
  start_seconds = int(round((start_frame / fps)
                      - start_minutes * 60
                      - start_hours * 60 * 60))
  

  
  start_time = (str(start_hours) 
                + ':' + str(start_minutes) 
                + ':' + str(start_seconds))

  return start_time

def gesture_recognizer2(
    name_of_video: str, 
    pos_time_w_gesture: float = 0.2,
    num_of_fr_per_step: int = 1,
    save_video: bool = False,
    res_video_name: str = None,  
    res_video_codec: str = None
    ) -> list:
  """
  В функции совершается проход по всем кадрам видео и определяется есть ли на 
  них руки. Если рука есть в кадре, то происходит подсчет открытых пальцев на 
  каждой из рук, а затем определяется показан ли какой-то жест. Далее 
  вычисляется время, в которое показан жест. Видео с выделенными руками и 
  сообщениями о показанных жестах в кадре, если нужно, сохраняется. 

  Параметры
  ----------
  name_of_video : имя видео, включающее расширение
  pos_time_w_gesture: кол-во секунд, которое должно пройти, чтобы жест
    считался показанным
  num_of_fr_per_step: число кадров считывающихся из видео за шаг цикла
  save_video: параметр отвечающий за то, будет ли записываться видео с
    найденными руками
  res_video_name: имя видео с найденными руками, включающее расширение
  res_video_codec: кодек для записи видео с отмеченными руками


  Возвращаемые значения
  ----------
  list_of_times: список строк, содержащих время видео, в которое
    показывается жест
  """
  res = [] #список строк, содержащих время и жест
  list_of_times = {'Left hand': [],'Right hand': []}
  input_lect = cv2.VideoCapture(name_of_video) 
  fps = input_lect.get(cv2.CAP_PROP_FPS)  # Число кадров в секунде видео
  frames_w_gesture_r = -1  # Число кадров с жестом,
                           # идущих подряд для правой руки
  frames_w_gesture_r_st = 0  # Первый кадр с жестом
                             # в текущем наборе для правой руки
  insignificant_frames_w_gesture_r = 0  # Число "неважных" кадров
                                        # с жестом для правой руки
  frames_without_gesture_r = -1  # Число кадров без жеста,
                                 # идущих подряд для правой руки
  frames_without_gesture_r_st = 0  # Первый кадр без жеста
                                   # в текущем наборе для правой руки
  insignificant_frames_without_gesture_r = 0  # Число "неважных" кадров
                                              # без жеста для правой руки
  frames_w_gesture_l = -1  # Число кадров с жестом,
                           # идущих подряд для левой руки
  frames_w_gesture_l_st = 0  # Первый кадр с жестом
                             # в текущем наборе для левой руки
  insignificant_frames_w_gesture_l = 0  # Число "неважных" кадров
                                        # с жестом для левой руки
  frames_without_gesture_l = -1  # Число кадров без жеста,
                                 # идущих подряд для левой руки 
  frames_without_gesture_l_st = 0  # Первый кадр без жеста
                                   # в текущем наборе для левой руки
  insignificant_frames_without_gesture_l = 0  # Число "неважных" кадров
                                              # без жеста для левой руки
  lect_height = int(input_lect.get(cv2.CAP_PROP_FRAME_HEIGHT))  # Длина кадра
  lect_width = int(input_lect.get(cv2.CAP_PROP_FRAME_WIDTH))  # Ширина кадра
  pos_num_of_frames = int(fps * pos_time_w_gesture)  # Кол-во кадров,
                                                     # которое 
                                                     # должно быть считано,
                                                     # чтобы жест считался 
                                                     # показанным 
  if save_video == True:  
    if res_video_name is None:  # Задаем имя видео с выделенными границами 
                                # и лицом по умолчанию
      res_video_name = 'answer_' + name_of_video
  
    fourcc = codec_selection(res_video_name, res_video_codec)  # Подбор кодека

    if fourcc is None:
      print("Try again. Specify video extension.")  # Если не удалось подобрать 
      return None                                   # кодек для записи, то 
                                                    # завершаем выполнение       
    
    result_vid = cv2.VideoWriter(res_video_name, 
                                 fourcc,           
                                 fps,
                                 (int(lect_width), int(lect_height)))

  last_frame_r = 0  # С жестом или нет был последний кадр для правой руки
  last_frame_l = 0  # С жестом или нет был последний кадр для левой руки
  number_of_frame = 0  # Номер текущего кадра

  mp_hands = mp.solutions.hands  # Инициализируем mediapipe класс рук


  hands = mp_hands.Hands(static_image_mode=True,  # Настраиваем ф-ию для 
                        max_num_hands=2,          # поиска рук
                        min_detection_confidence=0.8,
                        min_tracking_confidence=0.8)
  
  mpDraw = mp.solutions.drawing_utils  # Инициализируем mediapipe класс рисунка

  last_gesture_r = 'UNKNOWN'
  last_gesture_l = 'UNKNOWN'

  while True:  # Проходим в цикле по всем кадрам исходного видео

    number_of_frame += num_of_fr_per_step 

    for i in range(num_of_fr_per_step):  # Считываем нужное число кадров
      ret, frame = input_lect.read()     # из видео 

    if ret == False:  # Когда доходим до конца видео, прерываем цикл
      break

    rgb_frame = frame[:, :, ::-1]  # Преобразовываем изображение из формата
                                   # BGR, который использует OpenCV, в формат
                                   # RGB, который использует mediapipe  

    found_hands = hands.process(rgb_frame)  # Находим руки на кадре



    if found_hands.multi_hand_landmarks:  # Если руки нашлись 

      # Вызываем функцию определения "открытости" пальцев и подсчета "открытых"
      finger_count, fingers_statuses = finger_counter(lect_height,
                                                      lect_width,
                                                      found_hands, 
                                                      mp_hands)
      # Вызываем функцию определения жестов
      hands_gestures = gesture_search(fingers_statuses, finger_count)

      if hands_gestures['RIGHT'] != 'UNKNOWN':  # Если жесты 
                                                # найдены на правой руке
        if last_gesture_r != hands_gestures['RIGHT']:
          last_gesture_r = hands_gestures['RIGHT']
          frames_w_gesture_r = -1
          frames_w_gesture_r_st = 0     
          insignificant_frames_w_gesture_r = 0
          insignificant_frames_without_gesture_r = 0
          frames_without_gesture_r = -1
          frames_without_gesture_r_st = 0    

        last_frame_r = -1  # Последний кадр считаем c жестом на правой руке
        if frames_w_gesture_r == -1: 
          frames_w_gesture_r_st = number_of_frame
        frames_w_gesture_r += num_of_fr_per_step

        if (frames_without_gesture_r != -1 and
            frames_without_gesture_r <= pos_num_of_frames and
            frames_without_gesture_r_st != num_of_fr_per_step):
          frames_without_gesture_r = -1 
          frames_without_gesture_r_st = 0
          frames_w_gesture_r += insignificant_frames_without_gesture_r
          insignificant_frames_without_gesture_r = 0
        
        if frames_w_gesture_r <= pos_num_of_frames:
          insignificant_frames_w_gesture_r = frames_w_gesture_r
        else:
          insignificant_frames_w_gesture_r = 0

      else:   # Если жесты не найдены на правой руке

          if frames_without_gesture_r == -1: 
            frames_frames_without_gesture_r = number_of_frame
          frames_without_gesture_r += num_of_fr_per_step

          if (frames_w_gesture_r != -1 and
              frames_w_gesture_r <= pos_num_of_frames and
              frames_w_gesture_r_st != num_of_fr_per_step):
            frames_w_gesture_r = -1 
            frames_w_gesture_r_st = 0
            frames_without_gesture_r += insignificant_frames_w_gesture_r
            insignificant_frames_w_gesture_r = 0
          
          if frames_without_gesture_r <= pos_num_of_frames:
            insignificant_frames_without_gesture_r = frames_without_gesture_r
          else:
            insignificant_frames_without_gesture_r = 0
        
          if (frames_w_gesture_r > pos_num_of_frames and 
             frames_without_gesture_r > pos_num_of_frames):
            last_frame_r = 1  # Последний кадр считаем с не найденным
                              # жестом на правой руке
            # Рассчитываем время появления жеста
            gesture_time_r = time_calculation(frames_w_gesture_r_st, fps)
            list_of_times['Right hand'].append(gesture_time_r)  # Записываем время в список
            #print('Right hand: ' + last_gesture_r + ' at',gesture_time_r)
            res.append(('Right hand: ' + last_gesture_r + ' at',
                  gesture_time_r))  #записываем время появления жеста и сам жест
            frames_w_gesture_r = -1
            frames_w_gesture_r_st = 0     
            insignificant_frames_w_gesture_r = 0
            insignificant_frames_without_gesture_r = 0

      if hands_gestures['LEFT'] != 'UNKNOWN':  # Если жесты 
                                                 # найдены на левой руке
        if last_gesture_l != hands_gestures['LEFT']:
          last_gesture_l = hands_gestures['LEFT']
          frames_w_gesture_l = -1
          frames_w_gesture_l_st = 0     
          insignificant_frames_w_gesture_l = 0
          insignificant_frames_without_gesture_l = 0
          frames_without_gesture_l = -1
          frames_without_gesture_l_st = 0    
          
        last_frame_l = -1  # Последний кадр считаем c жестом на левой руке
        if frames_w_gesture_l == -1: 
          frames_w_gesture_l_st = number_of_frame
        frames_w_gesture_l += num_of_fr_per_step

        if (frames_without_gesture_l != -1 and
            frames_without_gesture_l <= pos_num_of_frames and
            frames_without_gesture_l_st != num_of_fr_per_step):
          frames_without_gesture_l = -1 
          frames_without_gesture_l_st = 0
          frames_w_gesture_l += insignificant_frames_without_gesture_l
          insignificant_frames_without_gesture_l = 0
        
        if frames_w_gesture_l <= pos_num_of_frames:
          insignificant_frames_w_gesture_l = frames_w_gesture_l
        else:
          insignificant_frames_w_gesture_l = 0
      else:   # Если жесты не найдены на правой

          if frames_without_gesture_l == -1: 
            frames_frames_without_gesture_l = number_of_frame
          frames_without_gesture_l += num_of_fr_per_step

          if (frames_w_gesture_l != -1 and
              frames_w_gesture_l <= pos_num_of_frames and
              frames_w_gesture_l_st != num_of_fr_per_step):
            frames_w_gesture_l = -1 
            frames_w_gesture_l_st = 0
            frames_without_gesture_l += insignificant_frames_w_gesture_l
            insignificant_frames_w_gesture_l = 0
          
          if frames_without_gesture_l <= pos_num_of_frames:
            insignificant_frames_without_gesture_l = frames_without_gesture_l
          else:
            insignificant_frames_without_gesture_l = 0
        
          if (frames_w_gesture_l > pos_num_of_frames and 
             frames_without_gesture_l > pos_num_of_frames):
            last_frame_l = 1  # Последний кадр считаем с не найденным
                              # жестом на правой руке
            # Рассчитываем время появления жеста
            gesture_time_l = time_calculation(frames_w_gesture_l_st, fps)
            list_of_times['Left hand'].append(gesture_time_l)  # Записываем время в список
            #print('Left hand: ' + last_gesture_l + ' at',gesture_time_l)
            res.append(('Left hand: ' + last_gesture_l + ' at',
                  gesture_time_l))  #записываем время появления жеста и сам жест
            frames_w_gesture_l = -1
            frames_w_gesture_l_st = 0     
            insignificant_frames_w_gesture_l = 0
            insignificant_frames_without_gesture_l = 0    

      if save_video == True:  
        # Записываем имя жеста на кадре
        cv2.putText(frame, 'RIGHT' +': '+ hands_gestures['RIGHT'],
                    (10, 60),
                    cv2.FONT_HERSHEY_PLAIN,
                    2,
                    (255, 0, 0),
                    6)
        
        cv2.putText(frame, 'LEFT' +': '+ hands_gestures['LEFT'],
                    (10, 120),
                    cv2.FONT_HERSHEY_PLAIN,
                    2,
                    (0, 0, 255),
                    6)

        # Отрисовываем руки на кадре
        for handLms in found_hands.multi_hand_landmarks:
          for id, lm in enumerate(handLms.landmark):
            cx, cy = int(lm.x*lect_width), int(lm.y*lect_height)
            cv2.circle(frame, (cx,cy), 3, (255,0,255), cv2.FILLED)

          mpDraw.draw_landmarks(frame, handLms, mp_hands.HAND_CONNECTIONS)


        #cv2.putText(frame, 
        #            str(sum(finger_count.values())),
        #            (lect_width//2-150,240),
        #            cv2.FONT_HERSHEY_SIMPLEX,
        #            8.9,
        #            (20,255,155),
        #            10,
        #            10)

    if save_video == True:  
      result_vid.write(cv2.resize(frame,(lect_width, lect_height)))

  if save_video == True:  
    result_vid.release()

  if last_frame_r == -1 and frames_w_gesture_r >= pos_num_of_frames : 
    # Вычисляем время появления жеста
    gesture_time_r = time_calculation(frames_w_gesture_r_st, fps)
    list_of_times['Right hand'].append(gesture_time_r)  # Записываем время появления жеста
    #print('Right hand: ' + last_gesture_r + ' at',  #записываем время появления жеста и сам жестgesture_time_r)
    res.append(('Right hand: ' + last_gesture_r + ' at',
          gesture_time_r))#записываем время появления жеста и сам жест

  if last_frame_l == -1 and frames_w_gesture_l >= pos_num_of_frames:
    # Вычисляем время появления жеста
    gesture_time_l = time_calculation(frames_w_gesture_l_st, fps)
    list_of_times['Left hand'].append(gesture_time_l)  # Записываем время появления жеста
    #print('Left hand: ' + last_gesture_l + ' at', gesture_time_l) #записываем время появления жеста и сам жест
    res.append(('Left hand: ' + last_gesture_l + ' at',   #записываем время появления жеста и сам жест
          gesture_time_l))

  return res