Python&OpenCVでPC画面に表示された領域を画像処理する

PythonとOpenCVを使って顔認識等の画像処理をする方法がネット上で数多く紹介されていますが、多くが画像ファイルや動画ファイル、Webカメラを入力としていて、PCの画面上に表示されているものを直接取り込む方法が見つからなかったので、この記事で紹介したいと思います。私はPythonもOpenCVもかじった程度の素人なのですが、今回たまたま上手くいったのでラッキーでした。

今回紹介するサンプルコードは下記サイトのものをベースにしています。
https://www.learnrobotics.org/blog/face-tracking-opencv/
こちらのサイトでは画像入力にはWebカメラを使用していますが、今回はこちらを改変していきます。
また、参照元ではarduino制御も行っていますがは今回は省略して顔を認識したら枠を顔にオーバーレイさせる処理のみを実装します。
早速ですがソースコードがこちらになります。

import numpy as np
import serial
import time
import sys
import cv2
import PIL.ImageGrab as ImageGrab
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
left = 1000
top = 220
width = 500
height = 500
width2 = int(width / 2)
height2 = int(height / 2)
while 1:
    box = (left,top,left+width,top+height) 
    screen = ImageGrab.grab(box)
    screen = cv2.cvtColor(np.array(screen), cv2.COLOR_RGB2BGR)
    cap = screen
    ret, img = 1, cap
    cv2.line(img,(width,height2),(0,height2),(0,255,0),1)
    cv2.line(img,(width2,0),(width2,height),(0,255,0),1)
    faces = face_cascade.detectMultiScale(img, 1.3)
    for (x,y,w,h) in faces:
        cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),5)
    
    cv2.imshow('img',img)
   
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break

こちらを画像取り込みのために追加しました。

import PIL.ImageGrab as ImageGrab

leftとtopで画面で指定する領域のx, y座標の始点を指定し、widthとheightで幅と高さを指定します。

そして、下記1行がミソだと思うのですが、私は素人なのでこうしたら動きましたとしか言えません(汗)

ret, img = 1, cap

実際にプログラムを動作させているときの様子をYoutubeにUpしましたのでよろしければご覧ください。