ENGINEER BLOG

ENGINEER BLOG

今時は非接触でしょ♪ PCのマウス操作を非接触でやってみた

こんにちは。
イノベーション本部の田中です。

皆さんは、コロナ前と現在で意識的に変えた事ってありますか?
私はお店での支払いのほとんどを、QR・バーコード決済に変えました。
現金に比べてスムーズに会計ができますし、紙幣や硬貨に直接触れなくてよいので衛生面でも安心ですよね。
キャッシュレス以外にも、コロナ禍の現在は『非接触』をキーワードにしたサービスをよく見かけますね。

というわけで、私もチャレンジです。
今回はPCのマウスを非接触で操作してみたいと思います。

どうやってマウス操作するの?

PC内蔵のカメラでハンドトラッキングをして、その位置情報を活用することでマウス操作をします。


①ハンドトラッキング

ハンドトラッキングには、MediaPipeを使います。
MediaPipeはストリーミングメディアに対して推論を実行するMLパイプラインを構築するためのフレームワークです。
これを利用することで、顔検出や物体検出などを簡単に行うことができます。
以前に「Google MediaPipeでMLアプリ開発の紹介」でもご紹介していますので、こちらも是非ご覧下さい。


②マウス制御

今回はpythonで動かしますので、マウス制御はPyAutoGUIを使用します。
PyAutoGUIは、PythonのRPA開発などでも使われるライブラリです。



1. 環境

  • windows10
  • python3.7

2. インストール

MediaPipe と PyAutoGUIを使用するために事前準備をします。
※描画にOpenCVを使うため、必要な場合はOpenCVもインストールします。

  • MediaPipe

      pip install mediapipe
    
  • PyAutoGUI

      pip install pyautogui
    

3. 実装

MediaPipeの公式サイトにPython用のサンプルコードがあるので、今回はこちらを利用させて頂きます。
静止画像用とカメラ用の二種類の入力方法がありますが、今回はカメラ用を使います。

import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands


# For webcam input:
cap = cv2.VideoCapture(0)
with mp_hands.Hands(
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5) as hands:
  while cap.isOpened():
    success, image = cap.read()
    if not success:
      print("Ignoring empty camera frame.")
      # If loading a video, use 'break' instead of 'continue'.
      continue

    # Flip the image horizontally for a later selfie-view display, and convert
    # the BGR image to RGB.
    image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)
    # To improve performance, optionally mark the image as not writeable to
    # pass by reference.
    image.flags.writeable = False
    results = hands.process(image)

    # Draw the hand annotations on the image.
    image.flags.writeable = True
    image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
    if results.multi_hand_landmarks:
      for hand_landmarks in results.multi_hand_landmarks:
        mp_drawing.draw_landmarks(
            image, hand_landmarks, mp_hands.HAND_CONNECTIONS)
    cv2.imshow('MediaPipe Hands', image)
    if cv2.waitKey(5) & 0xFF == 27:
      break
cap.release()

上記のサンプルコードに、マウスを制御するためのコードを追記していきます。
今回は以下のような制御を行います。

  • 人差し指の座標値を使ってカーソル移動をする
  • 人差し指を曲げ、指先が第二関節より下になった時にダブルクリックをする
import pyautogui
import time
image_width, image_height = image.shape[1], image.shape[0]

# 人差し指(指先)の座標値(x,y)をカメラでキャプチャした画像に合わせる
index_finger_tip_x = int(hand_landmarks.landmark[8].x * image_width)
index_finger_tip_y = int(hand_landmarks.landmark[8].y * image_height)

# 人差し指(第二関節)の座標値(x,y)をカメラでキャプチャした画像に合わせる
index_finger_pip_x = int(hand_landmarks.landmark[6].x * image_width)
index_finger_pip_y = int(hand_landmarks.landmark[6].y * image_height)


# 人差し指を曲げたとき、ダブルクリックをする
if index_finger_tip_y > index_finger_pip_y:
  pyautogui.doubleClick(index_finger_pip_x,index_finger_pip_y)
  time.sleep(1)                        
                    
# 上記外は、カーソルを移動させる
else:
  pyautogui.moveTo(index_finger_pip_x,index_finger_pip_y)

実行結果

handTracking
mouseControl


しっかりと手を認識してくれてますね!
また、手の動きに対応してカーソル移動やダブルクリックもできていますね。
動かしているPCは、特段にスペックが高い訳ではありませんが、意外とサクサク動きます。

まとめ

MediaPipe と PyAutoGUIを使って簡単なマウス操作を非接触で行いました。
今回は、指先や関節の座標値でクリックの制御を行いましたが、
MediaPipeで取得した座標データを使って、
機械学習を行うことでグー・チョキ・パーなどの様々な手の形を判断することもできるので、今後試していきたいです。