Merge pull request #125 from fishyboteso/improvement/resilient-qr

This commit is contained in:
Adam Saudagar 2022-06-30 22:28:42 +05:30 committed by GitHub
commit dfc3c14c2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 46 deletions

View File

@ -3,11 +3,38 @@ import re
import cv2
import numpy as np
from fishy.engine.common.window import WindowClient
detector = cv2.QRCodeDetector()
def image_pre_process(img):
# noinspection PyBroadException
def get_values(window: WindowClient):
values = None
for _ in range(5):
img = window.processed_image(func=_image_pre_process)
if img is None:
logging.debug("Couldn't capture window.")
continue
if not window.crop:
window.crop = _get_qr_location(img)
if not window.crop:
logging.debug("FishyQR not found.")
continue
img = window.processed_image(func=_image_pre_process)
values = _get_values_from_image(img)
if not values:
window.crop = None
logging.debug("Values not able to read.")
continue
break
return values
def _image_pre_process(img):
scale_percent = 100 # percent of original size
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
@ -16,7 +43,7 @@ def image_pre_process(img):
return img
def get_qr_location(image):
def _get_qr_location(image):
"""
code from https://stackoverflow.com/a/45770227/4512396
"""
@ -29,16 +56,15 @@ def get_qr_location(image):
return [int(x) for x in [p[0][0], p[0][1], p[1][0], p[2][1]]]
# noinspection PyBroadException
def get_values_from_image(img):
def _get_values_from_image(img):
h, w = img.shape
points = np.array([[(0, 0), (w, 0), (w, h), (0, h)]])
code = detector.decode(img, points)[0]
return parse_qr_code(code)
return _parse_qr_code(code)
# this needs to be updated each time qr code format is changed
def parse_qr_code(code):
def _parse_qr_code(code):
if not code:
return None
match = re.match(r'^(-?\d+\.\d+),(-?\d+\.\d+),(-?\d+),(\d+)$', code)

View File

@ -3,6 +3,7 @@ import math
import time
from threading import Thread
from fishy.engine.common import qr_detection
from pynput import keyboard, mouse
from fishy.engine import SemiFisherEngine
@ -12,8 +13,6 @@ from fishy.engine.fullautofisher.mode.calibrator import Calibrator
from fishy.engine.fullautofisher.mode.imode import FullAutoMode
from fishy.engine.fullautofisher.mode.player import Player
from fishy.engine.fullautofisher.mode.recorder import Recorder
from fishy.engine.common.qr_detection import (get_qr_location,
get_values_from_image, image_pre_process)
from fishy.engine.semifisher import fishing_mode
from fishy.engine.semifisher.fishing_mode import FishingMode
from fishy.helper.config import config
@ -60,7 +59,13 @@ class FullAuto(IEngine):
logging.info("starting in 2 secs...")
time.sleep(2)
if not self._pre_run_checks():
if not (type(self.mode) is Calibrator) and not self.calibrator.all_calibrated():
logging.error("you need to calibrate first")
return
if not qr_detection.get_values(self.window):
logging.error("FishyQR not found, if its not hidden, try to drag it around, "
"or increase/decrease its size and try again\nStopping engine...")
return
if config.get("tabout_stop", 1):
@ -73,26 +78,10 @@ class FullAuto(IEngine):
logging.error("exception occurred while running full auto mode")
print_exc()
def _pre_run_checks(self):
if self.window.get_capture() is None:
logging.error("Game window not found")
return False
self.window.crop = get_qr_location(self.window.get_capture())
if self.window.crop is None:
logging.error("FishyQR not found, try to drag it around and try again")
return False
if not (type(self.mode) is Calibrator) and not self.calibrator.all_calibrated():
logging.error("you need to calibrate first")
return False
return True
def start_show(self):
def func():
while self.start and WindowClient.running():
self.window.show(self.show_crop, func=image_pre_process)
self.window.show(self.show_crop)
Thread(target=func).start()
def stop_on_inactive(self):
@ -111,8 +100,7 @@ class FullAuto(IEngine):
todo find a better way of handling None: switch from start bool to state which knows
todo its waiting for qr which doesn't block the engine when commanded to close
"""
img = self.window.processed_image(func=image_pre_process)
values = get_values_from_image(img)
values = qr_detection.get_values(self.window)
return values[:3] if values else None
def move_to(self, target) -> bool:

View File

@ -4,10 +4,11 @@ import typing
from threading import Thread
from typing import Callable, Optional
from fishy.engine.common import qr_detection
from fishy.engine.semifisher.fishing_mode import FishingMode
from fishy.engine.common.IEngine import IEngine
from fishy.engine.common.qr_detection import get_qr_location, get_values_from_image, image_pre_process
from fishy.engine.common.window import WindowClient
from fishy.engine.semifisher import fishing_event, fishing_mode
from fishy.engine.semifisher.fishing_event import FishEvent
@ -35,15 +36,6 @@ class SemiFisherEngine(IEngine):
Thread(target=self._wait_and_check).start()
time.sleep(0.2)
capture = self.window.get_capture()
if capture is None:
logging.error("couldn't get game capture")
return
self.window.crop = get_qr_location(capture)
if not self.window.crop:
logging.error("FishyQR not found, try to drag it around and try again")
return
fishing_event.init()
# noinspection PyBroadException
@ -59,15 +51,9 @@ class SemiFisherEngine(IEngine):
def _engine_loop(self):
skip_count = 0
while self.state == 1 and WindowClient.running():
capture = self.window.processed_image(func=image_pre_process)
# if window server crashed
if capture is None:
logging.error("Couldn't capture window stopping engine")
return
# crop qr and get the values from it
self.values = get_values_from_image(capture)
self.values = qr_detection.get_values(self.window)
# if fishyqr fails to get read multiple times, stop the bot
if not self.values:
if skip_count >= 5: