前回はOpenCVであらかじめ用意された画像を表示しました。今回は実際にゲームの画面を取り込む方法を調べてみました。
# ImageGrab
で画面を取り込む
まずは前回インストールしたPillowにImageGrab
というモジュールが存在しています。画像の表示は割愛しますが、以下のスクリプトでデスクトップの画面全体をキャプチャすることが確認できます。
from PIL import ImageGrab
img = ImageGrab.grab()
img.show()
画面のキャプチャがウインドウで表示されるのでウインドウを閉じます。
このままでは使い勝手がよくないので、引数にbbox
を指定して、キャプチャする画面の領域を指定します。
このbbox
に関してですが、よくある(x, y, width, height)
のタプルかと思いきや(left, upper, right, lower)
でした。
この図を参考に説明すると、左上のx座標がleft、y座標がupperに対して、右下のx座標がright、y座標がlowerにあたります。つまり、右下の座標を求めるには(x, y, x+width, y+height)
で正しい座標が表示されるはずです。
Linuxにはxwininfo
というコマンドを使うと現在開いているウインドウの位置やサイズを調べることができるようです。
img = ImageGrab.grab(bbox=(152, 206, 1752, 1406))
これで指定した領域をもとに取り込みができるようになりました。
# 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側で色情報を正しくコンバートしてあげる必要があるようです。
imp = np.array(img)
img = cv2.cvtColor(imp, cv2.COLOR_BGR2RGB)
cv2.imshow("klondike", img)
これで実質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?