mirror of
https://github.com/jjaldridge2009/Project_Xs.git
synced 2024-11-19 17:02:33 +01:00
simultaneous tracking (player and pokemon) support added
This commit is contained in:
parent
efe3375618
commit
e741278d1a
136
src/rngtool.py
136
src/rngtool.py
@ -7,6 +7,7 @@ import time
|
||||
import cv2
|
||||
from xorshift import Xorshift
|
||||
import calc
|
||||
from collections import Counter
|
||||
|
||||
IDLE = 0xFF
|
||||
SINGLE = 0xF0
|
||||
@ -20,7 +21,7 @@ def tracking_blink(img, roi_x, roi_y, roi_w, roi_h, th = 0.9, size = 40)->Tuple[
|
||||
"""measuring the type and interval of player's blinks
|
||||
|
||||
Returns:
|
||||
blinks:List[int],intervals:list[int],offset_time:float: [description]
|
||||
blinks:List[int], intervals:list[int], offset_time:float
|
||||
"""
|
||||
|
||||
eye = img
|
||||
@ -40,7 +41,7 @@ def tracking_blink(img, roi_x, roi_y, roi_w, roi_h, th = 0.9, size = 40)->Tuple[
|
||||
|
||||
offset_time = 0
|
||||
|
||||
# 瞬きの観測
|
||||
# observe blinks
|
||||
while len(blinks)<size or state!=IDLE:
|
||||
_, frame = video.read()
|
||||
time_counter = time.perf_counter()
|
||||
@ -58,7 +59,7 @@ def tracking_blink(img, roi_x, roi_y, roi_w, roi_h, th = 0.9, size = 40)->Tuple[
|
||||
if 0.01<match<th:
|
||||
if state==IDLE:
|
||||
blinks.append(0)
|
||||
interval = (time_counter - prev_time)/1.018
|
||||
interval = (time_counter - prev_time)/1.017
|
||||
interval_round = round(interval)
|
||||
intervals.append(interval_round)
|
||||
|
||||
@ -85,8 +86,8 @@ def tracking_blink(img, roi_x, roi_y, roi_w, roi_h, th = 0.9, size = 40)->Tuple[
|
||||
cv2.destroyAllWindows()
|
||||
return (blinks, intervals, offset_time)
|
||||
|
||||
def tracking_poke_blink(img, roi_x, roi_y, roi_w, roi_h, size = 60)->Tuple[List[int],List[int],float]:
|
||||
"""measuring the type and interval of pokemon's blinks
|
||||
def tracking_poke_blink(img, roi_x, roi_y, roi_w, roi_h, th = 0.85, size = 60)->Tuple[List[int],List[int],float]:
|
||||
"""measuring the interval of pokemon's blinks
|
||||
|
||||
Returns:
|
||||
intervals:list[int],offset_time:float: [description]
|
||||
@ -106,7 +107,7 @@ def tracking_poke_blink(img, roi_x, roi_y, roi_w, roi_h, size = 60)->Tuple[List[
|
||||
prev_time = time.perf_counter()
|
||||
|
||||
|
||||
# 瞬きの観測
|
||||
# observe blinks
|
||||
while len(intervals)<size:
|
||||
_, frame = video.read()
|
||||
time_counter = time.perf_counter()
|
||||
@ -115,12 +116,12 @@ def tracking_poke_blink(img, roi_x, roi_y, roi_w, roi_h, size = 60)->Tuple[List[
|
||||
if (roi==prev_roi).all():
|
||||
continue
|
||||
prev_roi = roi
|
||||
cv2.imshow("",roi)
|
||||
cv2.imshow("",cv2.resize(roi, (roi_w*2, roi_h*2)))
|
||||
cv2.waitKey(1)
|
||||
res = cv2.matchTemplate(roi,eye,cv2.TM_CCOEFF_NORMED)
|
||||
_, match, _, _ = cv2.minMaxLoc(res)
|
||||
|
||||
if 0.4<match<0.85:
|
||||
if 0.4<match<th:
|
||||
if state==IDLE:
|
||||
interval = (time_counter - prev_time)
|
||||
print(interval)
|
||||
@ -135,6 +136,100 @@ def tracking_poke_blink(img, roi_x, roi_y, roi_w, roi_h, size = 60)->Tuple[List[
|
||||
video.release()
|
||||
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:
|
||||
"""
|
||||
Recover the xorshift from the type and interval of blinks.
|
||||
@ -165,7 +260,7 @@ def recov(blinks:List[int],rawintervals:List[int])->Xorshift:
|
||||
return result
|
||||
|
||||
def reidentifyByBlinks(rng:Xorshift, observed_blinks:List[int], npc = 0, search_max=10**6, search_min=0)->Xorshift:
|
||||
"""reidentify Xorshift state by type of observed blinks.
|
||||
"""reidentify Xorshift state by the type of observed blinks.
|
||||
|
||||
Args:
|
||||
rng (Xorshift): identified rng
|
||||
@ -223,13 +318,13 @@ def reidentifyByBlinks(rng:Xorshift, observed_blinks:List[int], npc = 0, search_
|
||||
|
||||
return None
|
||||
|
||||
def reidentifyByIntervals(rng:Xorshift, rawintervals:List[int], npc = 0, search_max=10**6, search_min=0)->Xorshift:
|
||||
def reidentifyByIntervals(rng:Xorshift, rawintervals:List[int], npc = 0, th = 0, search_max=10**6, search_min=0)->Xorshift:
|
||||
"""reidentify Xorshift state by intervals of observed blinks.
|
||||
This method is faster than "reidentifyByBlinks" in most cases since it can be reidentified by less blinking.
|
||||
|
||||
Args:
|
||||
rng (Xorshift): [description]
|
||||
rawintervals (List[int]): list of intervals of blinks. 6 or more is recommended.
|
||||
rawintervals (List[int]): list of intervals of blinks. 7 or more are recommended.
|
||||
npc (int, optional): [description]. Defaults to 0.
|
||||
search_max ([type], optional): [description]. Defaults to 10**6.
|
||||
search_min (int, optional): [description]. Defaults to 0.
|
||||
@ -248,9 +343,6 @@ def reidentifyByIntervals(rng:Xorshift, rawintervals:List[int], npc = 0, search_
|
||||
blinkrands = [(i, int((r&0b1110)==0)) for i,r in list(enumerate(identify_rng.getNextRandSequence(search_max)))[d::1+npc]]
|
||||
|
||||
#prepare
|
||||
|
||||
|
||||
|
||||
expected_blinks_lst = []
|
||||
expected_blinks = 0
|
||||
lastblink_idx = -1
|
||||
@ -280,15 +372,21 @@ def reidentifyByIntervals(rng:Xorshift, rawintervals:List[int], npc = 0, search_
|
||||
|
||||
#search
|
||||
result = Xorshift(*rng.getState())
|
||||
distlst = []
|
||||
for idx, blinks in expected_blinks_lst:
|
||||
if search_blinks==blinks and search_min <= idx:
|
||||
print(f"found at advances:{idx}, d={d}")
|
||||
#check by hamming distance
|
||||
distance = bin(search_blinks^blinks).count("1")
|
||||
distlst.append(distance)
|
||||
isSame = distance<=th
|
||||
if isSame and search_min <= idx:
|
||||
print(f"found at advances:{idx}, d={d}, hamming={distance}")
|
||||
result.getNextRandSequence(idx)
|
||||
return result
|
||||
c = Counter(distlst)
|
||||
print(sorted(c.items()))
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def recovByMunchlax(rawintervals:List[float])->Xorshift:
|
||||
"""Recover the xorshift from the interval of Munchlax blinks.
|
||||
|
||||
@ -299,8 +397,8 @@ def recovByMunchlax(rawintervals:List[float])->Xorshift:
|
||||
Xorshift: [description]
|
||||
"""
|
||||
advances = len(rawintervals)
|
||||
intervals = [interval+0.048 for interval in rawintervals]#観測結果のずれを補正
|
||||
intervals = intervals[1:]#最初の観測結果はノイズなのでそれ以降を使う
|
||||
intervals = [interval+0.048 for interval in rawintervals]#Corrects for delays in observation results
|
||||
intervals = intervals[1:]#The first observation is noise, so we use the one after that.
|
||||
states = calc.reverseStatesByMunchlax(intervals)
|
||||
|
||||
prng = Xorshift(*states)
|
||||
|
Loading…
Reference in New Issue
Block a user