見出し画像

OpenCV 入門 (8) - Webカメラの映像表示しながらキー状態を取得

OpenCVでWebカメラの映像表示しながらキー状態を取得する方法が、予想外にややこしかったのでメモ。

前回

1. Webカメラの映像表示しながらキー状態を取得

waitKey()だとキーリピートで途切れ途切れになるため、キー状態の取得はpygletを利用しました。ポイントは、Numpy配列の画像をテクスチャに変換して画面に表示する部分になります。

import pyglet
import cv2
import numpy as np
from pyglet.gl import *
from pyglet.window import key

# 定数
CAMERA_ID = 0 # カメラID
IMAGE_SIZE = 256 # 画像サイズ

# カメラの生成
camera = cv2.VideoCapture(CAMERA_ID)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, IMAGE_SIZE)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, IMAGE_SIZE)

# ウィンドウの生成
win = pyglet.window.Window(width=IMAGE_SIZE, height=IMAGE_SIZE, vsync=False)
key_handler = pyglet.window.key.KeyStateHandler()
win.push_handlers(key_handler)
win_img = None

# キー状態の取得
def get_key_state():
    global key_handler
    key_state = set()
    win.dispatch_events()
    for key_code, pressed in key_handler.items():
        if pressed:
            key_state.add(key_code)
    return key_state

# 描画時の処理
@win.event
def on_draw():
    win.clear()
    if win_img != None:
        win_img.blit(0,0)

# イメージのクロップ
def clop_image(image):
    h, w, c = image.shape
    size = int(min(w, h))
    dx = int((w-size)/2)
    dy = int((h-size)/2)
    return image[dy : dy+size, dx : dx+size]

# 定期処理
def on_tick(dt):
    global win_img

    # イメージの更新
    retval, img = camera.read()
    img = clop_image(img)
    img = np.flipud(img) # Webカメラの向きの調整
    sy, sx, number_of_channels = img.shape
    number_of_bytes = sy * sx * number_of_channels
    img = img.ravel()
    image_texture = (GLubyte * number_of_bytes)(*img.astype('uint8'))
    win_img = pyglet.image.ImageData(sx, sy, 'BGR', image_texture,pitch=sx*number_of_channels)

    # キー状態の取得
    print('key_state:', get_key_state())

# アプリの開始
pyglet.app.platform_event_loop.start()
pyglet.clock.schedule_interval(on_tick, 0.1)
pyglet.app.run()

次回


この記事が気に入ったらサポートをしてみませんか?