🦔

パソコンの前で集中していないと煽られるLINE Botの作り方

2021/07/28に公開

できること

デスクトップの内臓カメラを使い定期的に顔検出を行うことにより画面の前で作業をしているかの判定を行います。
判定結果を定期的に通知することで、サボりを通知します。

言語

python

用意するもの

  • Line Notifyのアクセストークン
  • カメラ(作業時に顔を検出できる必要あり)

実装

必要なライブラリの読み込み

import cv2
import requests
import time
import schedule

openCVは顔検出に利用し、今回はscheduleを使って定期的な処理を行います。

顔検出

CASCADE_PATH = "./haarcascades/"
CASCADE = cv2.CascadeClassifier(CASCADE_PATH + 'haarcascade_frontalface_default.xml')


# OpenCVのカスケードファイルを指定
def face_position(gray_img):
    faces = CASCADE.detectMultiScale(gray_img, minSize=(100, 100))
    return faces


def check_face_in_front_fo_monitor():
    # デバイスのカメラから映像を取得
    cap = cv2.VideoCapture(0)
    ret, frame = cap.read()

openCVが配布する顔検出用の分類器
のhaarcascade_frontalface_default.xmlをhaarcascadesディレクトリの中に配置して利用しています。

内臓カメラを利用して画面内に顔があるかどうかをチェック

def check_face_in_front_fo_monitor():
    # 利用するカメラによって引数を変更
    cap = cv2.VideoCapture(0)
    ret, frame = cap.read()

    if not ret:
        raise Exception("Capture Error")

    # 今回は適当に30回判定
    for i in range(1, 30):
        ret, frame = cap.read()
        if not ret:
            break
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        if len(face_position(gray)) != 0:
            return True

    return False

内臓カメラで撮った画像を判定しており、30回顔検出を行い一回も顔が検出できなければFalseを返すようにしています。
ここは適宜回数を調整したりsleepを挟んでも良いかもしれません。

Line Notifyでの通知

Line Notify
からアクセストークンを発行します。

def send_line_notify(notification_message):
    line_notify_token = '自分のアクセストークン'
    line_notify_api = 'https://notify-api.line.me/api/notify'
    headers = {'Authorization': f'Bearer {line_notify_token}'}
    data = {'message': f'message: {notification_message}'}
    requests.post(line_notify_api, headers=headers, data=data)

定期的に実行する関数

def job():
    if check_face_in_front_fo_monitor():
        send_line_notify("集中できてるね!この調子!")
    else:
        send_line_notify("はい集中切れた〜!アウト〜!!")

定期的に行いたいジョブを作成します。

スケジュールのセッティング

send_line_notify("勉強を始めたよ")
schedule.every(10).minutes.do(job)

while True:
    schedule.run_pending()
    time.sleep(1)

適当に10分ごとに設定しています。
shcedule

最終的なコード

import cv2
import requests
import time
import schedule

CASCADE_PATH = "./haarcascades/"
CASCADE = cv2.CascadeClassifier(CASCADE_PATH + 'haarcascade_frontalface_default.xml')


# OpenCVのカスケードファイルを指定
def face_position(gray_img):
    faces = CASCADE.detectMultiScale(gray_img, minSize=(100, 100))
    return faces


def check_face_in_front_fo_monitor():
    cap = cv2.VideoCapture(0)
    ret, frame = cap.read()

    if not ret:
        raise Exception("Capture Error")

    for i in range(1, 30):
        ret, frame = cap.read()
        if not ret:
            break
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        if len(face_position(gray)) != 0:
            return True

    return False


def send_line_notify(notification_message):
    line_notify_token = '自分のトークン'
    line_notify_api = 'https://notify-api.line.me/api/notify'
    headers = {'Authorization': f'Bearer {line_notify_token}'}
    data = {'message': f'message: {notification_message}'}
    requests.post(line_notify_api, headers=headers, data=data)


def job():
    if check_face_in_front_fo_monitor():
        send_line_notify("集中できてるね!この調子!")
    else:
        send_line_notify("はい集中切れた〜!アウト〜!!")


send_line_notify("勉強を始めたよ")
schedule.every(1).minutes.do(job)

while True:
    schedule.run_pending()
    time.sleep(1)

最後に


ネットサーフィンをしていても顔は検出されてしまうのが難点。
しかしネットサーフィン時と作業時に判定できるほどの表情の変化があれば(例:ネットサーフィン時はめちゃくちゃニヤニヤしているなど)表情検出が可能かもしれません。

Discussion