前提・実現したいこと
PyQtでProcessingで書かれた迷路探索を自動で実行したい。
ここに質問の内容を詳しく書いてください。
Processingで作った迷路プログラムをchainerを使って学習するプログラムを作りたいと思っています。その際、GUI上の自動処理としてpyautoguiを用いています。
processing 3.4
python anaconda3-4.4.0
numpy 1.15.1
chainer 5.0.0(ニューラルネットワーク動かすためのもの)
pyautogui 0.9.38(キーボード操作、ディスプレイ内の画像検索するため)
発生している問題・エラーメッセージ
エラーメッセージ
取得に0.41797sかかりました 1回目のゲーム開始 Traceback (most recent call last): File "dqn_shimura.py", line 525, in <module> main() File "dqn_shimura.py", line 130, in main state = get_state(window_id, left, top, learning_width, learning_height, interval_w, interval_h) File "dqn_shimura.py", line 244, in get_state pixmap = test(win_id, left, top, width, height) File "dqn_shimura.py", line 299, in __init__ q=classmethod(QScreen.grabWindow()) TypeError: grabWindow(self, sip.voidptr, x: int = 0, y: int = 0, width: int = -1, height: int = -1): first argument of unbound method must have type 'QScreen'
該当のソースコード
#-*- coding: utf-8 -*- #ver0.41 2016/11/22 #python全体で使うような奴の追加 import argparse #起動時の引数設定 import os #ファイルの削除 import sys #シス import copy #データコピーテム関連(ここではプログラムの強制終了とか) import time #時間取得 import random #ランダム import configparser #iniファイルいじる import threading #マルチスレッド import csv #csvファイルの扱い(出力用) from collections import deque #デック(deque)を扱えるようにする from tqdm import tqdm #プログレスバー #ニューラルネットワークに関する追加 import numpy as np #数値計算補助(CPU) import cupy as cp #数値計算補助(GPU) import chainer #ディープネットワークのフレームワーク import chainer.functions as F import chainer.links as L from chainer import cuda,Variable,optimizers#optimizerpipsを消した(自分) from chainer import links as L #画面操作に関する追加 import pyautogui as ag #ディスプレイ内の画像検索、キーボード操作など from PIL import Image #RGB調べる #from PyQt4.QtGui import QPixmap,QApplication from PyQt5.QtWidgets import QApplication, QWidget, QLabel from PyQt5.QtGui import * from PyQt5.QtGui import QScreen from PyQt5.QtWidgets import * #引数設定 parser = argparse.ArgumentParser(description='Learning game') #行動選択の間隔(ms) parser.add_argument('--interval', default=1000, type=int, help='interval of capturing (ms)') #ゲームを回す回数 parser.add_argument('--play_number','-p' , default=1000, type=int, help='play number of count') #学習方法(初期設定DQN)(まだ使ってない) #Q・・・Q-learning #PS・・・Profit Sharing parser.add_argument('--learning_type','-l' , default='Q', type=str, help='learning type') args = parser.parse_args() #起動時の時間を保存 start_time = time.time() #サーチ間隔(ms) interval = args.interval / 1000.0 #gpuがあればcupyなければnumpyを使う(cpu未確認) xp = cuda.cupy if cuda.available else np #ランダムシードの決定 np.random.seed(0) #pyautoguiのコード実行後の待ち時間(s) ag.PAUSE = 0 #画面の位置設定 #キャプチャするウィンドウの取得 app = QApplication(sys.argv) window_id = app.desktop().winId() #ゲーム画面(学習対象)の位置(左上からの)とサイズ learning_left = 0 learning_top = 0 learning_width = 800 learning_height = 600 #学習画面の縮小度(xピクセルに一つの値を使用) interval_w = 2 interval_h = 2 #メイン def main(): #ゲーム画面認識してあったら画面にフォーカス移動,なければ終了 search = Thread_search('./image/start.png', 5) #スレッドスタート search.start() #ここでは他に動かすものがないので終わるまで待つ(この先も使うことはなかった) search.join() #値が返って来ていてディスプレイ内に認識したい画面が全部入っていたら if search.left != -1 and ag.onScreen(search.left + learning_left + learning_width, search.top + learning_top +learning_height): #画面内の適当な位置にカーソルを持って行きクリック ag.moveTo(search.left+48, search.top+16) ag.click() #画面外にカーソルを外しておく time.sleep(1) ag.press('t') time.sleep(1) #迷路の生成 time.sleep(1) ag.press('r') time.sleep(1) #迷路の写真取る ag.press('m') time.sleep(1) ag.press('g') time.sleep(1) ag.press('m') ag.moveTo(search.left-48, search.top-16) #ダメならエラーはいて終了 else : print('\033[31mError01:認識失敗 ディスプレイ内に画面がすべて入っていない場合があります\033[0m')#error01 sys.exit() #学習したい画面左上の座標を保存しておく(状態取得に使う) left = search.left + learning_left top = search.top + learning_top #エージェント作成 agent = Agent(learning_width, learning_height, interval_w, interval_h) #調整エージェント作成 tmp_agent = Agent(learning_width, learning_height, interval_w, interval_h) #インターバル調整 #ゲームを回す回数を決めておきその中かを確認 for i in range(1,args.play_number+1) : #100回に1度インターバル調整(うまくいってない?) #if i % 100 == 1: #インターバル調整 # interval = interval_adjust(tmp_agent,window_id) #最後に保存したスコアとゲームの状態と行動価値の最大値を初期化 game_state = 2 print(('%d回目のゲーム開始'%i)) #get_reward内でgame_state更新してるからこっちではそのまま調べる while game_state < 3 and agent.step < 3000: #今の時間をとっておく now_time = time.time() #現在の状態を取得 state = get_state(window_id, left, top, learning_width, learning_height, interval_w, interval_h) action_state = set_state(agent, state, learning_width, learning_height, interval_w, interval_h) #取得した状態に応じて行動を選択 action_choice, q = agent.get_action(action_state) fw = open('Q_1zikoku.csv','a') fw.write('%d回目,%f,%d\n'% (i, q, action_choice)) fw.close() #選択された行動を実際に実行する set_action(action_choice) #報酬取得 reward, game_state, ep_end, g = get_reward() time.sleep(0.2) #一時メモリに保存 agent.stock_tmp(state, action_choice, reward, ep_end) #経験メモリに入れるだけの情報が集まったら if len(agent.tmp_memory) > agent.tmp_size: #経験をストックする agent.stock_experience(g) #ステップを1増やす agent.step += 1 agent.reduce_epsilon() #最初の状態取得から次の取得の間の時間 interval_time = time.time()-now_time #情報表示 print(('%d回目\tstep%d\ttime:%01.4fs\taction:%d\tQ:%01.4f\tepsilon:%01.4f'% (i,agent.step, time.time()-now_time, action_choice, q, agent.epsilon))) agent.total_step += 1 print(('%d回目のゲーム終了'%i)) print(('ここまでのステップ数%d'%agent.total_step)) f = open('keika_1zikoku.csv','a') f.write('%d,%01.4f\n'% (agent.step, agent.epsilon)) f.close() #開始からの時間を表示 time_tmp = time.time() - start_time print(('実行時間 : %02d:%02d:%02.2f' % (time_tmp//3600, time_tmp%3600//60, time_tmp%60))) #学習をゲーム終了時にする agent.train(i,state) agent.step = 0 agent.goal += 1 time.sleep(0.5) ag.press('i') time.sleep(0.5) #-----------------↓関数とクラス↓-------------------- #特定画像がディスプレイ内に存在するか検索をするマルチスレッド用クラス #マルチスレッドにして使うときは来なかったから意味はない #pic・・・探したい画像パス #timeout・・・タイムアウトまでの時間(秒)0のときタイムアウトを行わない #スレッド実行後使う値・・・見つけた座標x,y。タイムアウトもしくは見つかるまで(-1,-1) class Thread_search(threading.Thread): def __init__(self, pic, timeout): threading.Thread.__init__(self) self.pic = pic self.timeout = timeout #変数の初期化(特に必要なのはleft,top) self.left, self.top, self.width, self.height = [-1, -1, -1, -1] #startで実行される部分 def run(self): #探し始めた時間を記録 search_start_time = time.time() while True : #画像と同じ部分を探す(1箇所のみ) pos_search = ag.locateOnScreen(self.pic) #取得できた時 if pos_search is not None: #取得した位置を変数に入れる self.left, self.top, self.width, self.height = pos_search print(('取得に%01.5fsかかりました'% (time.time()-search_start_time))) #座標をかえせる状態になったからbreak break #取得できなかった時 else : #タイムアウトするかどうかの確認 if (time.time()-search_start_time) > self.timeout and self.timeout != 0: print(('%dsで取得できませんでした'% self.timeout)) print('タイムアウト') break #タイムアウトの時間でないときwhileにもどる #行動選択の数値を3種の動作に分けてからiniに保存 def set_action(action): #choice(0~2)をもとに3つの行動に分ける #0が前進、1が左に向く、2が右に向く if action == 0: ag.keyDown('w') time.sleep(0.1) ag.keyUp('w') elif action == 1: ag.keyDown('a') time.sleep(0.1) ag.keyUp('a') elif action == 2: ag.keyDown('d') time.sleep(0.1) ag.keyUp('d') #状態state(画面のRGB情報)を入手 #win_id・・・みるウィンドウ #left・・・学習する画面の左上のx座標 #top・・・学習する画面の左上のx座標 #width・・・学習する画面の横幅 #height・・・学習する画面の縦幅 #interval_w・・・横方向の情報入手間隔 #interval_h・・・縦方向の情報入手間隔 def get_state(win_id, left, top, width, height, interval_w, interval_h): pixmap = test(win_id, left, top, width, height) print(pixmap) #pixmapにウィンドウの情報を渡す pixmap = QScreen.grabWindow(win_id, left, top, width, height) #QImageへの変換 image = pixmap.toImage() bits= image.bits() bits.setsize(image.byteCount()) #数ピクセルに一つの割合でImage型RGBモードで保存しなおす screen = Image.fromarray(np.array(bits).reshape((height, width, 4))[::interval_w,::interval_h,2::-1]) state = np.asarray(screen) ##いらない部分(画像保存できるか試してみる) #png2 = './piclog/' + str(agent.step) + '.png' #保存 #screen.save(png2) #書き込み可能に state.flags.writeable = True #元画像の緑だけを取り出す state = state[:,:,1] #戻り値にstate(現在の状態)を返す return state #行動選択時に渡す入力を作成する def set_state(agent, state, learning_width, learning_height, interval_w, interval_h): #返り値用のリスト作成 tmp = [] #まず持ってるだけ一時メモリの情報をもらう for i in range(min(agent.tmp_size-1, len(agent.tmp_memory))): tmp.append(agent.tmp_memory[i][0]) #今の状態を追加 tmp.append(state) #足りない分0行列を付け足す while len(tmp) < agent.tmp_size: tmp.insert(0, state)#np.zeros( [learning_width//interval_w, learning_height//interval_h] )) return tmp #報酬の決定 #-1から1にクリッピングする #報酬とゲームの状態と今のスコアを返す def get_reward(): goal = ag.locateOnScreen('./image/GOAL.png') #if goal == None and np.array_equal(stat,sd) == True : # return -1,2 if goal == None: return 0,2,0,goal else : return 1,3,1,goal #インターバルの時間を調整する(インターバル以外の動作を行い時間を測る) class test: def __init__(self, win_id, left, top, width, height): q=classmethod(QScreen.grabWindow(self,win_id, left, top, width, height)) print(q) 注意:文字数制限のため、省略。
試したこと
QpixmapがPyQt5に対応していない模様だったため、QScreenによる解決を図った。
補足情報(FW/ツールのバージョンなど)
サイト利用が初めてなので、至らない点が多くあると思いますが足りないファイルなどありましたらあげさせていただきます。よろしくお願いします。

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/10/30 09:21
2018/10/30 10:51 編集
退会済みユーザー
2018/10/31 07:09
2018/10/31 07:29 編集