ゲームプログラマーの寄り道

ゲームプログラマの寄り道

ソースコード公開系ブログ

ソースコード公開系ブログ

ドンキの例のWiFiカメラ(スマモッチャー)を遊んでみた

スマモッチャー とは

f:id:shin--go:20200224205720j:plain

簡単に表すと  

非公式modが公開

  • modにより以下が拡張される
    • クラウドサービス(中華)への通信なし
    • RTSP / onvifサーバー
    • SSHサーバー
    • Telnetサーバー
    • busyboxのアップデート
    • うなり音が減少
    • WebUIアクセス
    • FTPサーバー github.com

IPアドレスを調べる

$ arp -a

コマンドプロンプトから同一LANに繋いでいるIPアドレスが見れるので、どれかがカメラになります。
同じMACアドレスを見たら分かるかも

ストリーミング再生

f:id:shin--go:20200224152941p:plain

RTSP認証を求められた場合

  • 比較的新しい個体は認証が求められる
    • ユーザー名:admin
    • パスワード:なし
      f:id:shin--go:20200224153232p:plain

顔認識してみる

  • スマモッチャーからRTSPで取得した映像から顔認識する
  • PythonOpenCVでお手軽に出来るはず

OpenCVをインストール

$ pip install opencv-python

ソースコード

import sys
import cv2 # OpenCV のインポート

cap = cv2.VideoCapture("rtsp://admin:@192.168.x.xx:554/") # 配信のURLを指定

if cap.isOpened() is False:
    print("can not open camera")
    sys.exit()

# 評価器を読み込み
# https://github.com/opencv/opencv/tree/master/data/haarcascades
cascade = cv2.CascadeClassifier('path') #haarcascade_frontalface_alt2.xmlのパス
eye_cascade = cv2.CascadeClassifier('path') #haarcascade_eye_tree_eyeglasses.xmlのパス

def mosaic(src, ratio=0.1):
    small = cv2.resize(src, None, fx=ratio, fy=ratio, interpolation=cv2.INTER_NEAREST)
    return cv2.resize(small, src.shape[:2][::-1], interpolation=cv2.INTER_NEAREST)

def mosaic_area(src, x, y, width, height, ratio=0.1):
    dst = src.copy()
    dst[y:y + height, x:x + width] = mosaic(dst[y:y + height, x:x + width], ratio)
    return dst

while True:
    # VideoCaptureから1フレーム読み込む
    ret, frame = cap.read()

    # そのままの大きさだと処理速度がきついのでリサイズ
    frame = cv2.resize(frame, (int(frame.shape[1]*0.5), int(frame.shape[0]*0.5)))

    # 処理速度を高めるために画像をグレースケールに変換したものを用意
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    
    
    # 顔検出
    facerect = cascade.detectMultiScale(
       gray,
       scaleFactor=1.11,
       minNeighbors=3,
       minSize=(100, 100)
    )

    if len(facerect) != 0:
        for x, y, w, h in facerect:
            # 顔の部分(この顔の部分に対して目の検出をかける)
            face_gray = gray[y: y + h, x: x + w]
  
            # くり抜いた顔の部分を表示(処理には必要ない。ただ見たいだけ。)
            show_face_gray = cv2.resize(face_gray, (int(gray.shape[1]), int(gray.shape[0])))
            cv2.imshow('face', show_face_gray)
  
            # 顔の部分から目の検出
            eyes = eye_cascade.detectMultiScale(
                face_gray,
                scaleFactor=1.11, # ここの値はPCのスペックに依存するので適宜修正してください
                minNeighbors=3,
                minSize=(15, 15)
            )
  
            if len(eyes) == 0:
                # 目が閉じられたとみなす
                cv2.putText(
                    frame,
                    'close your eyes',
                    (x, y - 10), # 位置を少し調整
                    cv2.FONT_HERSHEY_PLAIN,
                    2,
                    (0, 255,0),
                    2,
                    cv2.LINE_AA
                )
            else:
                for (ex, ey, ew, eh) in eyes:
                    # 目の部分にモザイク処理
                    frame = mosaic_area(
                        frame,
                        int((x + ex) - ew / 2),
                        int(y + ey),
                        int(ew * 2.5),
                        eh
                    )
  
            # 顔検出した部分に枠を描画
            cv2.rectangle(
                frame,
                (x, y),
                (x + w, y + h),
                (255, 255, 255),
                thickness=2
            )
  
    cv2.imshow('frame', frame)

    # キー入力を1ms待って、k が27(ESC)だったらBreakする
    k = cv2.waitKey(1)
    if k == 27:
        break

# キャプチャをリリースして、ウィンドウをすべて閉じる
cap.release()
cv2.destroyAllWindows()

感想

  • セキュリティさえ気お付ければ、遊べるIPカメラ
  • ネットワークカメラモジュールがドン・キホーテで直ぐに手に入る事を考えればお値打ち
  • OpenCVと組み合わせれば、テレビを見なくなったら消すなど出来そう

用語