OpenCV3で画面をキャプチャしてみる

前回はOpenCVであらかじめ用意された画像を表示しました。今回は実際にゲームの画面を取り込む方法を調べてみました。

# ImageGrabで画面を取り込む

まずは前回インストールしたPillowにImageGrabというモジュールが存在しています。画像の表示は割愛しますが、以下のスクリプトでデスクトップの画面全体をキャプチャすることが確認できます。

from PIL import ImageGrab

img = ImageGrab.grab()
img.show()

画面のキャプチャがウインドウで表示されるのでウインドウを閉じます。

このままでは使い勝手がよくないので、引数にbboxを指定して、キャプチャする画面の領域を指定します。

このbboxに関してですが、よくある(x, y, width, height)のタプルかと思いきや(left, upper, right, lower)でした。

bboxの説明

この図を参考に説明すると、左上のx座標がleft、y座標がupperに対して、右下のx座標がright、y座標がlowerにあたります。つまり、右下の座標を求めるには(x, y, x+width, y+height)で正しい座標が表示されるはずです。

Linuxにはxwininfoというコマンドを使うと現在開いているウインドウの位置やサイズを調べることができるようです。

img = ImageGrab.grab(bbox=(152, 206, 1752, 1406))
Pillowで出力した画像

これで指定した領域をもとに取り込みができるようになりました。

# OpenCVで画像を表示する

ImageGrabで_grab_した画像はPillowの形式なのでOpenCVが読み込み可能な形式に変換してあげる必要があります。そこで使用するのが前回インストールしたnumpyです。

numpy.arrayでOpenCVが扱える配列に変換したあと、前回使用したcv2.imreadを使って画像を表示します。

import cv2
import numpy as np
from PIL import ImageGrab

img = ImageGrab.grab(bbox=(152, 206, 1752, 1406))
imp = np.array(img)

cv2.imshow("klondike", imp)

cv2.waitKey(0)
cv2.destroyAllWindows()
opencvでキャプチャを表示

結果を見てみるとカードの色が正しく表示されていません。なので、OpenCV側で色情報を正しくコンバートしてあげる必要があるようです。

imp = np.array(img)
img = cv2.cvtColor(imp, cv2.COLOR_BGR2RGB)

cv2.imshow("klondike", img)
opencvで色変換後にキャプチャを表示

これで実質PCで遊べるゲームの画面をOpenCVに取り込むことができるようになりました。ただし前回のように一枚の画像を取り込んでいるのと変わりありませんが、while文を使えばすぐに応用できるはずです。現時点でHDMIキャプチャを所有していないので、しばらくはPCゲームを題材に書いていこうと思っています。

# 参考にしたページ

Understand Python Pillow bbox for Beginners – Python Pillow Tutorial

How do I find the window dimensions and position accurately including decorations?