mirror of
https://github.com/jjaldridge2009/Project_Xs.git
synced 2024-10-03 22:07:09 +02:00
This commit is contained in:
commit
1ca51efed0
BIN
barry/eye.png
Normal file
BIN
barry/eye.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
cresselia/eye.png
Normal file
BIN
cresselia/eye.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 368 B |
BIN
images/fullmoon/eye.png
Normal file
BIN
images/fullmoon/eye.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
images/lake/eye.png
Normal file
BIN
images/lake/eye.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
3
memo.md
3
memo.md
@ -2,6 +2,7 @@ memo.md
|
|||||||
|
|
||||||
type : roi_x, roi_y, roi_w, roi_h
|
type : roi_x, roi_y, roi_w, roi_h
|
||||||
munchlax : 730, 670 ,50, 60
|
munchlax : 730, 670 ,50, 60
|
||||||
|
cresselia/eye :805, 480, 20, 30
|
||||||
trainer/home/eye_blur : 905, 750, 55, 55
|
trainer/home/eye_blur : 905, 750, 55, 55
|
||||||
trainer/home/eye_normal : 905, 480, 55, 200
|
trainer/home/eye_normal : 905, 480, 55, 200
|
||||||
trainer/ruin/eye : 920, 490, 35, 50
|
trainer/ruin/eye : 920, 490, 35, 50
|
||||||
@ -10,4 +11,6 @@ trainer/underground/eye : 925, 520, 35, 35
|
|||||||
trainer/trophygarden/eye : 930, 505, 30, 30
|
trainer/trophygarden/eye : 930, 505, 30, 30
|
||||||
trainer/mtcoronet/eye : 930, 510, 30, 40
|
trainer/mtcoronet/eye : 930, 510, 30, 40
|
||||||
trainer/spearpillar/eye : 935,505,25,30
|
trainer/spearpillar/eye : 935,505,25,30
|
||||||
|
trainer/lake/eye : 930, 490, 30, 35
|
||||||
|
trainer/fullmoon/eye : 925, 500, 35, 35
|
||||||
barry/eye : 1065, 490, 30, 35
|
barry/eye : 1065, 490, 30, 35
|
187
src/cresselia.py
Normal file
187
src/cresselia.py
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
"""
|
||||||
|
this program is experimental.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import rngtool
|
||||||
|
import calc
|
||||||
|
import cv2
|
||||||
|
import time
|
||||||
|
from xorshift import Xorshift
|
||||||
|
import heapq
|
||||||
|
|
||||||
|
imgpath = "./trainer/fullmoon/eye.png"
|
||||||
|
|
||||||
|
def firstspecify():
|
||||||
|
imgpath = "./trainer/secretbase/eye.png"
|
||||||
|
player_eye = cv2.imread(imgpath, cv2.IMREAD_GRAYSCALE)
|
||||||
|
if player_eye is None:
|
||||||
|
print("path is wrong")
|
||||||
|
return
|
||||||
|
blinks, intervals, offset_time = rngtool.tracking_blink(player_eye, 870, 680, 85, 90)
|
||||||
|
prng = rngtool.recov(blinks, intervals, )
|
||||||
|
|
||||||
|
waituntil = time.perf_counter()
|
||||||
|
diff = round(waituntil-offset_time)
|
||||||
|
prng.getNextRandSequence(diff)
|
||||||
|
|
||||||
|
state = prng.getState()
|
||||||
|
print("state(64bit 64bit)")
|
||||||
|
print(hex(state[0]<<32|state[1]), hex(state[2]<<32|state[3]))
|
||||||
|
print("state(32bit 32bit 32bit 32bit)")
|
||||||
|
print(*[hex(s) for s in state])
|
||||||
|
|
||||||
|
def reidentify():
|
||||||
|
print("input xorshift state(state[0] state[1] state[2] state[3])")
|
||||||
|
state = [int(x,0) for x in input().split()]
|
||||||
|
plimgpath = "./trainer/fullmoon/eye.png"
|
||||||
|
plimg = cv2.imread(plimgpath, cv2.IMREAD_GRAYSCALE)
|
||||||
|
plroi = (925, 500, 35, 35)
|
||||||
|
|
||||||
|
pkimgpath = "./cresselia/eye.png"
|
||||||
|
pkimg = cv2.imread(pkimgpath, cv2.IMREAD_GRAYSCALE)
|
||||||
|
pkroi = (805, 475, 20, 30)
|
||||||
|
blinks, observed_intervals, offset_time = rngtool.simultaneous_tracking(plimg, plroi, pkimg, pkroi, pkth = 0.999185, size = 8)
|
||||||
|
|
||||||
|
reidentified_rng = rngtool.reidentifyByIntervals(Xorshift(*state), observed_intervals, th=2, search_max=10**5)
|
||||||
|
if reidentified_rng is None:
|
||||||
|
print("couldn't reidentify state.")
|
||||||
|
return
|
||||||
|
|
||||||
|
waituntil = time.perf_counter()
|
||||||
|
diff = int(-(-(waituntil-offset_time)//1))
|
||||||
|
print(diff, waituntil-offset_time)
|
||||||
|
reidentified_rng.advances(max(diff,0))
|
||||||
|
|
||||||
|
state = reidentified_rng.getState()
|
||||||
|
print("state(64bit 64bit)")
|
||||||
|
print(hex(state[0]<<32|state[1]), hex(state[2]<<32|state[3]))
|
||||||
|
print("state(32bit 32bit 32bit 32bit)")
|
||||||
|
print(*[hex(s) for s in state])
|
||||||
|
|
||||||
|
#timecounter reset
|
||||||
|
advances = 0
|
||||||
|
waituntil = time.perf_counter()
|
||||||
|
time.sleep(diff - (waituntil - offset_time))
|
||||||
|
|
||||||
|
while True:
|
||||||
|
advances += 1
|
||||||
|
r = reidentified_rng.next()
|
||||||
|
|
||||||
|
waituntil += 1.017
|
||||||
|
|
||||||
|
next_time = waituntil - time.perf_counter() or 0
|
||||||
|
time.sleep(next_time)
|
||||||
|
print(f"advances:{advances}, blink:{hex(r&0xF)}")
|
||||||
|
|
||||||
|
def reidentifyInSecretBase():
|
||||||
|
"""reidentify xorshift internal state in the cresselia's room
|
||||||
|
note: this function is a bit unreliable since it is difficult to track the blinks of cresselia.
|
||||||
|
|
||||||
|
"""
|
||||||
|
print("input xorshift state(state[0] state[1] state[2] state[3])")
|
||||||
|
state = [int(x,0) for x in input().split()]
|
||||||
|
imgpath = "./trainer/secretbase/eye.png"
|
||||||
|
player_eye = cv2.imread(imgpath, cv2.IMREAD_GRAYSCALE)
|
||||||
|
if player_eye is None:
|
||||||
|
print("path is wrong")
|
||||||
|
return
|
||||||
|
blinks, observed_intervals, offset_time = rngtool.tracking_blink(player_eye, 870, 680, 85, 90, size=7)
|
||||||
|
reidentified_rng = rngtool.reidentifyByIntervals(Xorshift(*state), observed_intervals, npc=0)
|
||||||
|
if reidentified_rng is None:
|
||||||
|
print("couldn't reidentify state.")
|
||||||
|
return
|
||||||
|
|
||||||
|
waituntil = time.perf_counter()
|
||||||
|
diff = int(-(-(waituntil-offset_time)//1))
|
||||||
|
print(diff, waituntil-offset_time)
|
||||||
|
reidentified_rng.advances(max(diff,0))
|
||||||
|
|
||||||
|
state = reidentified_rng.getState()
|
||||||
|
print("state(64bit 64bit)")
|
||||||
|
print(hex(state[0]<<32|state[1]), hex(state[2]<<32|state[3]))
|
||||||
|
print("state(32bit 32bit 32bit 32bit)")
|
||||||
|
print(*[hex(s) for s in state])
|
||||||
|
|
||||||
|
#timecounter reset
|
||||||
|
advances = 0
|
||||||
|
waituntil = time.perf_counter()
|
||||||
|
time.sleep(diff - (waituntil - offset_time))
|
||||||
|
|
||||||
|
while True:
|
||||||
|
advances += 1
|
||||||
|
r = reidentified_rng.next()
|
||||||
|
waituntil += 1.017
|
||||||
|
|
||||||
|
next_time = waituntil - time.perf_counter() or 0
|
||||||
|
time.sleep(next_time)
|
||||||
|
print(f"advances:{advances}, blink:{hex(r&0xF)}")
|
||||||
|
|
||||||
|
def cresselia_timeline():
|
||||||
|
print("input xorshift state(state[0] state[1] state[2] state[3])")
|
||||||
|
state = [int(x,0) for x in input().split()]
|
||||||
|
plimgpath = "./trainer/fullmoon/eye.png"
|
||||||
|
plimg = cv2.imread(plimgpath, cv2.IMREAD_GRAYSCALE)
|
||||||
|
plroi = (925, 500, 35, 35)
|
||||||
|
|
||||||
|
pkimgpath = "./cresselia/eye.png"
|
||||||
|
pkimg = cv2.imread(pkimgpath, cv2.IMREAD_GRAYSCALE)
|
||||||
|
pkroi = (805, 475, 20, 30)
|
||||||
|
blinks, observed_intervals, offset_time = rngtool.simultaneous_tracking(plimg, plroi, pkimg, pkroi, pkth = 0.999185, size = 4)
|
||||||
|
|
||||||
|
reidentified_rng = rngtool.reidentifyByIntervals(Xorshift(*state), observed_intervals, th=1, search_max=1*10**3, search_min=0)
|
||||||
|
if reidentified_rng is None:
|
||||||
|
print("couldn't reidentify state.")
|
||||||
|
return
|
||||||
|
|
||||||
|
waituntil = time.perf_counter()
|
||||||
|
diff = int(-(-(waituntil-offset_time)//1))
|
||||||
|
print(diff, waituntil-offset_time)
|
||||||
|
reidentified_rng.advances(max(diff,0))
|
||||||
|
|
||||||
|
state = reidentified_rng.getState()
|
||||||
|
print("state(64bit 64bit)")
|
||||||
|
print(hex(state[0]<<32|state[1]), hex(state[2]<<32|state[3]))
|
||||||
|
print("state(32bit 32bit 32bit 32bit)")
|
||||||
|
print(*[hex(s) for s in state])
|
||||||
|
|
||||||
|
advances = 1
|
||||||
|
waituntil = time.perf_counter()
|
||||||
|
time.sleep(diff - (waituntil - offset_time))
|
||||||
|
#timeline prepare
|
||||||
|
queue = []
|
||||||
|
blink_int = reidentified_rng.range(3.0, 12.0) + 0.285
|
||||||
|
#blink_int = reidentified_rng.rangefloat(3,12) + 0.285
|
||||||
|
heapq.heappush(queue, (waituntil+blink_int,1))
|
||||||
|
|
||||||
|
#_ = reidentified_rng.next()
|
||||||
|
heapq.heappush(queue, (waituntil+1.017,0))
|
||||||
|
|
||||||
|
while queue:
|
||||||
|
advances += 1
|
||||||
|
w, q = heapq.heappop(queue)
|
||||||
|
next_time = w - time.perf_counter() or 0
|
||||||
|
if next_time>0:
|
||||||
|
time.sleep(next_time)
|
||||||
|
|
||||||
|
if q==0:
|
||||||
|
r = reidentified_rng.next()
|
||||||
|
print(f"advances:{advances}, blink:{hex(r&0xF)}")
|
||||||
|
heapq.heappush(queue, (w+1.017, 0))
|
||||||
|
else:
|
||||||
|
blink_int = reidentified_rng.range(3.0, 12.0) + 0.285
|
||||||
|
#blink_int = reidentified_rng.rangefloat(3,12) + 0.285
|
||||||
|
|
||||||
|
heapq.heappush(queue, (w+blink_int, 1))
|
||||||
|
print(f"advances:{advances}, interval:{blink_int}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
#note:
|
||||||
|
#1. specify internal state with firstspecify() (secretbase is better place)
|
||||||
|
#2. search target on pokefinder
|
||||||
|
#3. advance rng (fullmoon island exterior is fast, about +250/s)
|
||||||
|
#4. enter the cresselia's room 2000 advances before the target, and reidentify state with cresselia_timeline()
|
||||||
|
#5.
|
||||||
|
|
||||||
|
#firstspecify()
|
||||||
|
#reidentifyInSecretBase()
|
||||||
|
cresselia_timeline()
|
107
src/rngtool.py
107
src/rngtool.py
@ -8,6 +8,7 @@ import sys
|
|||||||
import cv2
|
import cv2
|
||||||
from xorshift import Xorshift
|
from xorshift import Xorshift
|
||||||
import calc
|
import calc
|
||||||
|
from collections import Counter
|
||||||
|
|
||||||
IDLE = 0xFF
|
IDLE = 0xFF
|
||||||
SINGLE = 0xF0
|
SINGLE = 0xF0
|
||||||
@ -21,7 +22,7 @@ def tracking_blink(img, roi_x, roi_y, roi_w, roi_h, th = 0.9, size = 40, Monitor
|
|||||||
"""measuring the type and interval of player's blinks
|
"""measuring the type and interval of player's blinks
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
blinks:List[int],intervals:list[int],offset_time:float: [description]
|
blinks:List[int], intervals:list[int], offset_time:float
|
||||||
"""
|
"""
|
||||||
|
|
||||||
eye = img
|
eye = img
|
||||||
@ -55,7 +56,7 @@ def tracking_blink(img, roi_x, roi_y, roi_w, roi_h, th = 0.9, size = 40, Monitor
|
|||||||
|
|
||||||
offset_time = 0
|
offset_time = 0
|
||||||
|
|
||||||
# 瞬きの観測
|
# observe blinks
|
||||||
while len(blinks)<size or state!=IDLE:
|
while len(blinks)<size or state!=IDLE:
|
||||||
if tk_window != None:
|
if tk_window != None:
|
||||||
if not tk_window.monitoring and not tk_window.reidentifying:
|
if not tk_window.monitoring and not tk_window.reidentifying:
|
||||||
@ -78,7 +79,7 @@ def tracking_blink(img, roi_x, roi_y, roi_w, roi_h, th = 0.9, size = 40, Monitor
|
|||||||
cv2.rectangle(frame,(roi_x,roi_y), (roi_x+roi_w,roi_y+roi_h), 255, 2)
|
cv2.rectangle(frame,(roi_x,roi_y), (roi_x+roi_w,roi_y+roi_h), 255, 2)
|
||||||
if state==IDLE:
|
if state==IDLE:
|
||||||
blinks.append(0)
|
blinks.append(0)
|
||||||
interval = (time_counter - prev_time)/1.018
|
interval = (time_counter - prev_time)/1.017
|
||||||
interval_round = round(interval)
|
interval_round = round(interval)
|
||||||
intervals.append(interval_round)
|
intervals.append(interval_round)
|
||||||
print(f"Adv Since Last: {round((time_counter - prev_time)/1.018)} {(time_counter - prev_time)/1.018}")
|
print(f"Adv Since Last: {round((time_counter - prev_time)/1.018)} {(time_counter - prev_time)/1.018}")
|
||||||
@ -211,7 +212,7 @@ def tracking_poke_blink(img, roi_x, roi_y, roi_w, roi_h, size = 64, th = 0.85, M
|
|||||||
w, h = eye.shape[::-1]
|
w, h = eye.shape[::-1]
|
||||||
|
|
||||||
|
|
||||||
# 瞬きの観測
|
# observe blinks
|
||||||
while len(intervals)<size:
|
while len(intervals)<size:
|
||||||
if tk_window != None:
|
if tk_window != None:
|
||||||
if not tk_window.tidsiding:
|
if not tk_window.tidsiding:
|
||||||
@ -275,6 +276,100 @@ def tracking_poke_blink(img, roi_x, roi_y, roi_w, roi_h, size = 64, th = 0.85, M
|
|||||||
video.release()
|
video.release()
|
||||||
return intervals
|
return intervals
|
||||||
|
|
||||||
|
def simultaneous_tracking(plimg, plroi:Tuple[int,int,int,int], pkimg, pkroi:Tuple[int,int,int,int], plth=0.88, pkth=0.999185, size=8)->Tuple[List[int],List[int],float]:
|
||||||
|
"""measuring type/intervals of player's blinks and the interval of pokemon's blinks
|
||||||
|
note: this methods is very unstable. it not recommended to use.
|
||||||
|
Returns:
|
||||||
|
intervals:list[int],offset_time:float: [description]
|
||||||
|
"""
|
||||||
|
video = cv2.VideoCapture(0,cv2.CAP_DSHOW)
|
||||||
|
video.set(cv2.CAP_PROP_FRAME_WIDTH,1920)
|
||||||
|
video.set(cv2.CAP_PROP_FRAME_HEIGHT,1080)
|
||||||
|
video.set(cv2.CAP_PROP_BUFFERSIZE,1)
|
||||||
|
|
||||||
|
pl_state = IDLE
|
||||||
|
pk_state = IDLE
|
||||||
|
blinks = []
|
||||||
|
intervals = []
|
||||||
|
pl_prev = time.perf_counter()
|
||||||
|
pk_prev = time.perf_counter()
|
||||||
|
|
||||||
|
prev_roi = None
|
||||||
|
debug_txt = ""
|
||||||
|
|
||||||
|
offset_time = 0
|
||||||
|
|
||||||
|
blinkcounter = 0
|
||||||
|
|
||||||
|
# observe blinks
|
||||||
|
while len(blinks)<size or pl_state!=IDLE:
|
||||||
|
_, frame = video.read()
|
||||||
|
time_counter = time.perf_counter()
|
||||||
|
|
||||||
|
#player eye
|
||||||
|
roi_x,roi_y,roi_w,roi_h = plroi
|
||||||
|
roi = cv2.cvtColor(frame[roi_y:roi_y+roi_h,roi_x:roi_x+roi_w],cv2.COLOR_RGB2GRAY)
|
||||||
|
if (roi==prev_roi).all():
|
||||||
|
continue
|
||||||
|
|
||||||
|
prev_roi = roi
|
||||||
|
res = cv2.matchTemplate(roi,plimg,cv2.TM_CCOEFF_NORMED)
|
||||||
|
_, match, _, _ = cv2.minMaxLoc(res)
|
||||||
|
|
||||||
|
#cv2.imshow("pl",roi)
|
||||||
|
|
||||||
|
if 0.01<match<plth:
|
||||||
|
if pl_state==IDLE:
|
||||||
|
blinks.append(0)
|
||||||
|
interval = (time_counter - pl_prev)/1.017
|
||||||
|
interval_round = round(interval)
|
||||||
|
interval_corrected = interval_round + blinkcounter
|
||||||
|
blinkcounter = 0#reset blinkcounter
|
||||||
|
intervals.append(interval_corrected)
|
||||||
|
|
||||||
|
if len(intervals)==size:
|
||||||
|
offset_time = time_counter
|
||||||
|
|
||||||
|
#check interval
|
||||||
|
check = " " if abs(interval-interval_round)<0.2 else "*"
|
||||||
|
debug_txt = f"{interval}"+check
|
||||||
|
pl_state = SINGLE
|
||||||
|
pl_prev = time_counter
|
||||||
|
elif pl_state==SINGLE:
|
||||||
|
#double
|
||||||
|
if time_counter - pl_prev>0.3:
|
||||||
|
blinks[-1] = 1
|
||||||
|
debug_txt = debug_txt+"d"
|
||||||
|
pl_state = DOUBLE
|
||||||
|
elif pl_state==DOUBLE:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if pl_state!=IDLE and time_counter - pl_prev>0.7:
|
||||||
|
pl_state = IDLE
|
||||||
|
print(debug_txt, len(blinks))
|
||||||
|
|
||||||
|
if pk_state==IDLE:
|
||||||
|
#poke eye
|
||||||
|
roi_x,roi_y,roi_w,roi_h = pkroi
|
||||||
|
roi = cv2.cvtColor(frame[roi_y:roi_y+roi_h,roi_x:roi_x+roi_w],cv2.COLOR_RGB2GRAY)
|
||||||
|
|
||||||
|
res = cv2.matchTemplate(roi,pkimg,cv2.TM_CCORR_NORMED)#CCORR might be better?
|
||||||
|
_, match, _, _ = cv2.minMaxLoc(res)
|
||||||
|
cv2.imshow("pk",roi)
|
||||||
|
cv2.waitKey(1)
|
||||||
|
if 0.4<match<pkth:
|
||||||
|
#print("poke blinked!")
|
||||||
|
blinkcounter += 1
|
||||||
|
pk_prev = time_counter
|
||||||
|
pk_state = SINGLE
|
||||||
|
|
||||||
|
if pk_state!=IDLE and time_counter - pk_prev>0.7:
|
||||||
|
pk_state = IDLE
|
||||||
|
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
print(intervals)
|
||||||
|
return (blinks, intervals, offset_time)
|
||||||
|
|
||||||
def recov(blinks:List[int],rawintervals:List[int])->Xorshift:
|
def recov(blinks:List[int],rawintervals:List[int])->Xorshift:
|
||||||
"""
|
"""
|
||||||
Recover the xorshift from the type and interval of blinks.
|
Recover the xorshift from the type and interval of blinks.
|
||||||
@ -443,8 +538,8 @@ def recovByMunchlax(rawintervals:List[float])->Xorshift:
|
|||||||
Xorshift: [description]
|
Xorshift: [description]
|
||||||
"""
|
"""
|
||||||
advances = len(rawintervals)
|
advances = len(rawintervals)
|
||||||
intervals = [interval+0.048 for interval in rawintervals]#観測結果のずれを補正
|
intervals = [interval+0.048 for interval in rawintervals]#Corrects for delays in observation results
|
||||||
intervals = intervals[1:]#最初の観測結果はノイズなのでそれ以降を使う
|
intervals = intervals[1:]#The first observation is noise, so we use the one after that.
|
||||||
states = calc.reverseStatesByMunchlax(intervals)
|
states = calc.reverseStatesByMunchlax(intervals)
|
||||||
|
|
||||||
prng = Xorshift(*states)
|
prng = Xorshift(*states)
|
||||||
|
@ -112,7 +112,7 @@ def reidentifyInSecretBase():
|
|||||||
if player_eye is None:
|
if player_eye is None:
|
||||||
print("path is wrong")
|
print("path is wrong")
|
||||||
return
|
return
|
||||||
blinks, observed_intervals, offset_time = rngtool.tracking_blink(player_eye, 870, 680, 85, 90, size=6)
|
blinks, observed_intervals, offset_time = rngtool.tracking_blink(player_eye, 870, 680, 85, 90, size=7)
|
||||||
reidentified_rng = rngtool.reidentifyByIntervals(Xorshift(*state), observed_intervals, npc=0)
|
reidentified_rng = rngtool.reidentifyByIntervals(Xorshift(*state), observed_intervals, npc=0)
|
||||||
if reidentified_rng is None:
|
if reidentified_rng is None:
|
||||||
print("couldn't reidentify state.")
|
print("couldn't reidentify state.")
|
||||||
|
Loading…
Reference in New Issue
Block a user