Skip to content
This repository has been archived by the owner on Sep 23, 2019. It is now read-only.

Commit

Permalink
Changelog
Browse files Browse the repository at this point in the history
->Created simpler, smaller, universal template(\media\Images\template.png)
->Added simple test script with sample frames
->Updated grabscreen.py:
-Removed prints
-added resize function, now all returned frames have 600px in height(for faster template matching)
->Updated SaveData.py:
-fishing_function remade for better performance
-added zoom detection, now user don't need to specify what zoom is using(def detect_zoom)
-better frame crop for better performace
->SaveDataold.py:
-old savedata script, for backup purposes
  • Loading branch information
jpvolt committed Jul 27, 2018
1 parent 7d1b743 commit 911dc5d
Show file tree
Hide file tree
Showing 12 changed files with 304 additions and 111 deletions.
209 changes: 107 additions & 102 deletions SVFBFuncs/SaveData.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,47 +8,20 @@
from PyQt5.QtCore import QObject, pyqtSignal
from SVFBFuncs.getkeys import key_check
from SVFBFuncs import grabscreen


def fishing_region(img, region_template_gray, w, h):
# Função usada para encontrar a área de pesca nos frames. Adaptado do tutorial no site oficial do Opencv
# img: imagem fonte
# region_template_gray: template em preto e branco
# w e h: width e height do template

res = cv2.matchTemplate(img, region_template_gray, cv2.TM_CCOEFF_NORMED)

threshold = 0.65

loc = np.where(res >= threshold)

for pt in zip(*loc[::-1]):
# Caso seja encontrado o template matching, será retornado apenas um valor, que é o primeiro ponto aonde houve
# o match. Seria melhor mudar isso para retornar o valor daonde teve o melhor match.
x1, y1 = pt[0], pt[1]
x2, y2 = pt[0] + w, pt[1] + h


# TODO: Fix this constants so the image can be resized to 0.3*size
coords_list = [y1 - 10, y2 + 10, x1 - 25, x2 + 25] # these number are added to give a little margin for the TM
green_bar_region = img[y1: y2, x1 + 55: x2 - 35]

# Antes de retornar o frame, faz um resize dele pra um tamanho menor, a fim de não ocupar muito espaço em disco
# Como uma convnet precisa que todas as imagens tenha o mesmo tamanho, talvez seja melhor estabelecer um tamanho
# fixo aqui, e não um razão de diminuição, como está sendo feito.
green_bar_region = cv2.resize(green_bar_region, None, fx=0.3, fy=0.3) # TODO: optimize this resizing

return {"Detected": True, "Region": green_bar_region, "Coords": coords_list}


# Só roda caso não seja achado a região
return {"Detected": False}


import win32api

template_file = 'media\\Images\\template.png'
template = cv2.imread(template_file)
gray_template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
r_factor = 1
resized_template = cv2.resize(gray_template, (0, 0), fx=r_factor, fy=r_factor)
w_crop = 150 # size of cut region
h_crop = 300 # size of cut region
class SaveData(QObject):
finished = pyqtSignal()
send_data = pyqtSignal()


def __init__(self, key, res, zoom, parent=None):
QObject.__init__(self, parent=parent)

Expand All @@ -61,8 +34,52 @@ def __init__(self, key, res, zoom, parent=None):

self.zoom = zoom
self.key = key

self.knowszoom = False
self.template = None
self.run = True
def detect_zoom(self,img):

test_size = 75

for i in range(11):
r_factor = test_size/125
#print("testing zoom:",test_size)
resized_template = cv2.resize(gray_template, (0, 0), fx=r_factor*self.frameresizeratio, fy=r_factor*self.frameresizeratio)
#w, h = resized_template.shape[::-1]
res = cv2.matchTemplate(img, resized_template, cv2.TM_CCOEFF_NORMED)
threshold = 0.6
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
self.knowszoom = True
self.template = resized_template
print("Detected zoom:",test_size)
return test_size
break
test_size += 5

def fishing_region(self, img):
# Função usada para encontrar a área de pesca nos frames.
# img: imagem fonte

gray_template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
if self.knowszoom:
res = cv2.matchTemplate(img, self.template, cv2.TM_CCOEFF_NORMED)
threshold = 0.5
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
x1 = pt[0] - w_crop
y1 = pt[1] - h_crop
x2 = pt[0] + w_crop
y2 = pt[1] + h_crop
return {"Detected": True, "frame": img, "coords": [y1,y2,x1,x2]}

else: #detecta zoom
#print("detecting zoom")
self.detect_zoom(img)

# Só roda caso não seja achado a região
return {"Detected": False}


def main(self):

Expand All @@ -72,99 +89,87 @@ def main(self):
logger.info("Training data file created")
training_data = np.empty(shape=[0, 2])

# Loading template according to zoom level:
logger.info("Loading template image")
fishing_region_file = 'media\\Images\\fr {}.png'.format(self.zoom)
region_template = cv2.imread(fishing_region_file)
# region_template = cv2.resize(region_template, None, fx=0.3, fy=0.3) # TODO: using smaller img for less space used
region_template = cv2.cvtColor(region_template, cv2.COLOR_BGR2GRAY)
wr, hr = region_template.shape[::-1] # 121, 474

# Variáveis de controle:
# was_fishing: sinaliza se o frame anterior foi ou não um frame da sessão de pescaria. Caso o mini-game seja
# detectado, isso é setado para True no final do loop. Assim, no frame seguinte, caso não tenha sido detectado a
# região e was_fishing for True, isso signifca que a pescaria acabou, e deve ser feito o processo de finalização
# da captura de dados.
# coords: coordenadas da região reduzida encontrada do mini-game.
# knowszoom : flag para detectar o zoom
was_fishing = False
coords = None

logger.info("Data started")

while self.run:

#res_x, res_y = self.res
screen = grabscreen.grab_screen(region=self.region) # Return gray screen
screen, self.frameresizeratio = grabscreen.grab_screen(region=self.region) # Return gray screen, frameresizeratio is used to recalculate template size
if screen is not None:
if coords is None:
region = self.fishing_region(screen)
else:
crop_frame = screen[:, coords[2]:coords[3]]
region = self.fishing_region(crop_frame)

# screen = cv2.resize(screen, None, fx=0.3, fy=0.3) # TODO: using smaller img for less space used

# Finds the thin area the fish stays at
if coords:
# If there was found coords, cut the screen size to look again for the template, so it uses less resources
region = fishing_region(screen[coords[0]:coords[1], coords[2]:coords[3]], region_template, wr, hr) #[y1, y2, x1 + 55, x2 - 35]
if region["Detected"]:
# Se a área for detectada, salvar na np.array o frame e a o key-press do jogador.

else:
region = fishing_region(screen, region_template, wr, hr)
frame = region["frame"]

key_pressed = key_check(self.key) # return 1 or 0

if region["Detected"]:
# Se a área for detectada, salvar na np.array o frame e a o key-press do jogador.
data = [frame, key_pressed] # or data = np.array([key_pressed, frame], dtype=object)

window = region["Region"]
training_data = np.vstack((training_data, data))
method = 'np.vstack'

key_pressed = key_check(self.key) # return 1 or 0

data = [window, key_pressed] # or data = np.array([key_pressed, window], dtype=object)

training_data = np.vstack((training_data, data))
method = 'np.vstack'
# For the first frame detected
if not was_fishing:
coords = region["coords"]
initial_time = datetime.datetime.now()

was_fishing = True
was_fishing = True

# For the first frame of the detected region, get its coordinates to reduce the area to look for it again
if not coords:
coords = region["Coords"]
logger.info("Coordinates found: %s" % coords)
initial_time = datetime.datetime.now()
# If area not detected this frame, but was on the last one, this means fishing is over.
if not region["Detected"] and was_fishing:
logger.info("Fishing finished")
final_time = datetime.datetime.now()
was_fishing = False

# If area not detected this frame, but was on the last one, this means fishing is over.
if not region["Detected"] and was_fishing:
logger.info("Fishing finished")
final_time = datetime.datetime.now()
was_fishing = False
new_frames = np.float64(len(training_data))

new_frames = np.float64(len(training_data))
print("Frames analysed: %s" % new_frames)

print("Frames analysed: %s" % new_frames)
if new_frames >= 75:
# Apenas salva caso houver mais de 75 frames
print("Saving...")
np.save(file_name, training_data)

if new_frames >= 75:
# Apenas salva caso houver mais de 75 frames
print("Saving...")
np.save(file_name, training_data)
# Sinaliza ao main_thread que deve enviar os dados coletados
self.send_data.emit()

# Sinaliza ao main_thread que deve enviar os dados coletados
self.send_data.emit()
else:
print("Not saving!")
logger.debug("Data too small")

else:
print("Not saving!")
logger.debug("Data too small")

# Necessary to reset the region coordinates after every fishing session.
training_data = np.empty(shape=[0, 2])
file_name = 'Data\\Training Data\\%s.npy' % uuid4()
coords = None

# Measurements (debug):
time_delta = (final_time - initial_time).total_seconds()
median_fps = new_frames/time_delta
print("Median FPS: {}".format(median_fps))
print("ΔTime: {}".format(time_delta))

with open("Data\\log.txt", 'a') as f:
f.write("Method: {}\nMedian FPS: {}\ndTime: {}s\nFrames: {}\n\n".format(
method,
round(median_fps, 2),
time_delta, new_frames))
# Necessary to reset the region coordinates after every fishing session.
training_data = np.empty(shape=[0, 2])
file_name = 'Data\\Training Data\\%s.npy' % uuid4()
coords = None

# Measurements (debug):
time_delta = (final_time - initial_time).total_seconds()
median_fps = new_frames/time_delta
print("Median FPS: {}".format(median_fps))
print("ΔTime: {}".format(time_delta))

with open("Data\\log.txt", 'a') as f:
f.write("Method: {}\nMedian FPS: {}\ndTime: {}s\nFrames: {}\n\n".format(
method,
round(median_fps, 2),
time_delta, new_frames))

# Caso o usuário clique em "Stop" na GUI
self.finished.emit()
Expand Down
Loading

0 comments on commit 911dc5d

Please sign in to comment.