1. Rowing0914

    Posted

    Rowing0914
Changes in title
+pythonでデスクトップツール開発のため、クリックを判定するライブラリを見つけた
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,150 @@
+すいません、自分用の記事として描かせていただきます。
+
+めちゃめちゃ探すのに苦労しました。。。
+1日ぐらいかかったかも。。
+
+やりたかったことは簡単です。
+デスクトップ上で動くゲームや外部カメラを通じて流れてくる動画など、特定のWindowを経由して映像が流れることがあるとします。
+それをずーっとトラッキングしたかったのです。
+PILなどを使ってそれをベクトル変換できるのでそれを持って機械学習をしたかったのです。
+ただ今回の肝はウィンドウサイズをユーザーが決められるようにしたいということです。
+ですので、簡単に言えば、ネイティブスクリーンキャプチャツールwindowsで言えば、snipping toolのように。
+macで言えば、`shift + cmd + 4`で出てくるアレみたいなやつです。
+それで枠をくくった上で、その指定した範囲をpythonで見続けてもらうっていう感じです。
+あれこれ書いても仕方がないので、結論から。
+
+## pynput
+https://pypi.org/project/pynput/
+
+```python
+from pynput import mouse
+
+def on_move(x, y):
+ print('Pointer moved to {0}'.format((int(x), int(y))))
+
+def on_click(x, y, button, pressed):
+ print('{0} at {1}'.format('Pressed' if pressed else 'Released',(int(x), int(y))))
+ if not pressed:
+ # Stop listener
+ return False
+
+def on_scroll(x, y, dx, dy):
+ print('Scrolled {0} at {1}'.format(
+ 'down' if dy < 0 else 'up',
+ (x, y)))
+
+# Collect events until released
+with mouse.Listener(
+ on_move=on_move,
+ on_click=on_click,
+ on_scroll=on_scroll) as listener:
+ listener.join()
+```
+これでマウスのトラッキングとクリックした時のJSできなイベントを起動させることができました。
+
+## めっちゃ時間を食った時に考えていた案
+
+1. _get_windows():こっちを使うと、Quartzのライブラリを使ってMacOSの程レイヤーな部分から現状動いているアプリケーション等の情報を持って来れます。
+そして、そこからトラックしたアプリケーションのウィンドウのサイズとポジションを取得して、マニュアルでそいつを捕捉してやろうとしてました。できまs。。。。したが、なぜかPILにその`(x,y,w,h)`情報を渡す部分でうまくいかず、常に的外れな場所のキャプチャを続けるという始末。
+2. get_windows():死闘のあげく発見した、AppleScriptというWindowsのWSH的なやつ。。それで、下の方にはったget_info_game.scptを書いて、それをsubprocessで読んできて、1版と同様にマニュアルで敵を捕捉。しかし、やっぱりPILがうまくいかない。
+
+```python
+"""
+get_windows() is obtained from the link below
+https://superuser.com/questions/902869/how-to-identify-which-process-is-running-which-window-in-mac-os-x
+"""
+import Quartz
+import gym
+import numpy as np
+from PIL import ImageGrab, Image
+import subprocess
+
+def show_windows():
+ wl = Quartz.CGWindowListCopyWindowInfo( Quartz.kCGWindowListOptionAll, Quartz.kCGNullWindowID)
+ wl = sorted(wl, key=lambda k: k.valueForKey_('kCGWindowOwnerPID'))
+
+ print 'PID'.rjust(7) + ' ' + 'WinID'.rjust(5) + ' ' + 'x,y,w,h'.ljust(21) + ' ' + '\t[Title] SubTitle'
+ print '-'.rjust(7,'-') + ' ' + '-'.rjust(5,'-') + ' ' + '-'.ljust(21,'-') + ' ' + '\t-------------------------------------------'
+
+ for v in wl:
+ print ( \
+ str(v.valueForKey_('kCGWindowOwnerPID') or '?').rjust(7) + \
+ ' ' + str(v.valueForKey_('kCGWindowNumber') or '?').rjust(5) + \
+ ' {' + ('' if v.valueForKey_('kCGWindowBounds') is None else \
+ ( \
+ str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('X'))) + ',' + \
+ str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('Y'))) + ',' + \
+ str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('Width'))) + ',' + \
+ str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('Height'))) \
+ ) \
+ ).ljust(21) + \
+ '}' + \
+ '\t[' + ((v.valueForKey_('kCGWindowOwnerName') or '') + ']') + \
+ ('' if v.valueForKey_('kCGWindowName') is None else (' ' + v.valueForKey_('kCGWindowName') or '')) \
+ ).encode('utf8')
+
+ return "done"
+
+def _get_windows():
+ wl = Quartz.CGWindowListCopyWindowInfo( Quartz.kCGWindowListOptionAll, Quartz.kCGNullWindowID)
+ wl = sorted(wl, key=lambda k: k.valueForKey_('kCGWindowOwnerPID'))
+
+ dimensions = {}
+ cnt = 0
+
+ # create dict to store the position for the window
+ for v in wl:
+ if (v.valueForKey_('kCGWindowOwnerName') == 'Sublime Text'):
+ x = int(v.valueForKey_('kCGWindowBounds').valueForKey_('X'))
+ y = int(v.valueForKey_('kCGWindowBounds').valueForKey_('Y'))
+ w = int(v.valueForKey_('kCGWindowBounds').valueForKey_('Width'))
+ h = int(v.valueForKey_('kCGWindowBounds').valueForKey_('Height'))
+ dimensions["{}".format(cnt)] = (x,y,w,h)
+ cnt += 1
+
+ print(dimensions)
+ return dimensions
+
+def get_windows():
+ result = subprocess.check_output(["osascript", "get_info_game.scpt"]).strip().split(',')
+ result = map(int, result)
+ x,y,w,h = result
+ result = (x+50,y+50,w+x+600,h+y+450)
+ return result
+
+def _screenshot(dimensions):
+ dimension = dimensions["0"]
+ print(dimension)
+
+ # save image
+ ImageGrab.grab(dimension).save("png_{}.png".format(0))
+
+ image = ImageGrab.grab(dimension)
+ image.load()
+ data = np.asarray(image, dtype="int32")
+ print(data)
+
+def screenshot(dimension):
+ # save image
+ ImageGrab.grab(dimension).save("png_{}.png".format(0))
+
+ image = ImageGrab.grab(dimension)
+ image.load()
+ data = np.asarray(image, dtype="int32")
+ print(data)
+
+if __name__ == '__main__':
+ # show_windows()
+ dimension = get_windows()
+ print(dimension)
+ screenshot(dimension)
+```
+
+```applescript:get_info_game.scpt
+tell application "System Events" to tell application process "AppName入れてね"
+ tell window 1
+ activate
+ get {position, size}
+ end tell
+end tell
+```