integrated fishyqr v0.0.2 for semi fisher

- remove color detection code
- move qr detection from full auto into common
- refactor both engines to use qr from common
This commit is contained in:
Adam Saudagar 2021-11-21 12:42:14 +05:30
parent 5d18b8538e
commit 8ae46dd5a5
7 changed files with 49 additions and 116 deletions

View File

@ -9,6 +9,15 @@ from pyzbar.pyzbar import decode
from fishy.helper.helper import get_documents from fishy.helper.helper import get_documents
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)
dim = (width, height)
img = cv2.resize(img, dim, interpolation=cv2.INTER_AREA)
return img
def get_qr_location(og_img): def get_qr_location(og_img):
""" """
code from https://stackoverflow.com/a/45770227/4512396 code from https://stackoverflow.com/a/45770227/4512396
@ -40,7 +49,7 @@ def get_values_from_image(img):
try: try:
for qr in decode(img): for qr in decode(img):
vals = qr.data.decode('utf-8').split(",") vals = qr.data.decode('utf-8').split(",")
return float(vals[0]), float(vals[1]), float(vals[2]) return tuple(float(v) for v in vals)
logging.error("FishyQR not found") logging.error("FishyQR not found")
return None return None

View File

@ -1,5 +1,6 @@
import logging import logging
import math import math
import traceback
from enum import Enum from enum import Enum
from threading import Thread from threading import Thread
@ -75,10 +76,15 @@ def loop_end():
cv2.waitKey(25) cv2.waitKey(25)
# noinspection PyBroadException
def run(): def run():
# todo use config # todo use config
while WindowServer.status == Status.RUNNING: while WindowServer.status == Status.RUNNING:
try:
loop() loop()
except Exception:
traceback.print_exc()
WindowServer.status = Status.CRASHED
loop_end() loop_end()

View File

@ -1,4 +1,3 @@
import math
import logging import logging
import math import math
import time import time
@ -16,8 +15,8 @@ from fishy.engine.fullautofisher.mode.calibrator import Calibrator
from fishy.engine.fullautofisher.mode.imode import FullAutoMode from fishy.engine.fullautofisher.mode.imode import FullAutoMode
from fishy.engine.fullautofisher.mode.player import Player from fishy.engine.fullautofisher.mode.player import Player
from fishy.engine.fullautofisher.mode.recorder import Recorder from fishy.engine.fullautofisher.mode.recorder import Recorder
from fishy.engine.fullautofisher.qr_detection import (get_qr_location, from fishy.engine.common.qr_detection import (get_qr_location,
get_values_from_image) get_values_from_image, image_pre_process)
from fishy.engine.semifisher import fishing_event, fishing_mode from fishy.engine.semifisher import fishing_event, fishing_mode
from fishy.engine.semifisher.fishing_mode import FishingMode from fishy.engine.semifisher.fishing_mode import FishingMode
from fishy.helper import helper, hotkey from fishy.helper import helper, hotkey
@ -29,15 +28,6 @@ mse = mouse.Controller()
kb = keyboard.Controller() kb = keyboard.Controller()
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)
dim = (width, height)
img = cv2.resize(img, dim, interpolation=cv2.INTER_AREA)
return img
class FullAuto(IEngine): class FullAuto(IEngine):
rotate_by = 30 rotate_by = 30

View File

@ -4,14 +4,16 @@ import typing
from threading import Thread from threading import Thread
from typing import Callable, Optional from typing import Callable, Optional
import cv2
from fishy.helper.helper import log_raise
from playsound import playsound from playsound import playsound
from fishy.engine.common.IEngine import IEngine 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.common.window import WindowClient
from fishy.engine.semifisher import fishing_event, fishing_mode from fishy.engine.semifisher import fishing_event, fishing_mode
from fishy.engine.semifisher.fishing_event import FishEvent from fishy.engine.semifisher.fishing_event import FishEvent
from fishy.engine.semifisher.fishing_mode import Colors, FishingMode
from fishy.engine.semifisher.pixel_loc import PixelLoc
from fishy.helper import helper from fishy.helper import helper
from fishy.helper.luaparser import sv_color_extract from fishy.helper.luaparser import sv_color_extract
@ -22,7 +24,7 @@ if typing.TYPE_CHECKING:
class SemiFisherEngine(IEngine): class SemiFisherEngine(IEngine):
def __init__(self, gui_ref: Optional['Callable[[], GUI]']): def __init__(self, gui_ref: Optional['Callable[[], GUI]']):
super().__init__(gui_ref) super().__init__(gui_ref)
self.fishPixWindow = None self.window = None
def run(self): def run(self):
""" """
@ -30,34 +32,43 @@ class SemiFisherEngine(IEngine):
code explained in comments in detail code explained in comments in detail
""" """
fishing_event.init() fishing_event.init()
self.fishPixWindow = WindowClient() self.window = WindowClient(color=cv2.COLOR_RGB2GRAY, show_name="semifisher debug")
# check for game window and stuff # check for game window and stuff
self.gui.bot_started(True) self.gui.bot_started(True)
sv_color_extract(Colors)
if self.get_gui: if self.get_gui:
logging.info("Starting the bot engine, look at the fishing hole to start fishing") logging.info("Starting the bot engine, look at the fishing hole to start fishing")
Thread(target=self._wait_and_check).start() Thread(target=self._wait_and_check).start()
while self.start and WindowClient.running(): self.window.crop = get_qr_location(self.window.get_capture())
capture = self.fishPixWindow.get_capture() if self.window.crop is None:
log_raise("FishyQR not found")
while self.start and WindowClient.running():
capture = self.window.processed_image(func=image_pre_process)
if capture is None:
# if window server crashed # if window server crashed
if capture is None:
self.gui.bot_started(False) self.gui.bot_started(False)
self.toggle_start() self.toggle_start()
continue continue
self.fishPixWindow.crop = PixelLoc.val # crop qr and get the values from it
fishing_mode.loop(capture[0][0]) values = get_values_from_image(capture)
if values is None:
self.gui.bot_started(False)
self.toggle_start()
continue
fishing_mode.loop(values[3])
time.sleep(0.1) time.sleep(0.1)
self.window.show(False)
logging.info("Fishing engine stopped") logging.info("Fishing engine stopped")
self.gui.bot_started(False) self.gui.bot_started(False)
fishing_event.unsubscribe() fishing_event.unsubscribe()
self.fishPixWindow.destory() self.window.destory()
def _wait_and_check(self): def _wait_and_check(self):
time.sleep(10) time.sleep(10)
@ -71,7 +82,7 @@ class SemiFisherEngine(IEngine):
t = 0 t = 0
while t < 10.0: while t < 10.0:
t += freq t += freq
logging.debug(str(FishingMode.CurrentMode) + ":" + str(self.fishPixWindow.get_capture()[0][0])) logging.debug(str(FishingMode.CurrentMode) + ":" + str(self.window.get_capture()[0][0]))
time.sleep(freq) time.sleep(freq)
logging.debug("Will display pixel values for 10 seconds") logging.debug("Will display pixel values for 10 seconds")

View File

@ -107,7 +107,10 @@ def fisher_callback(event: State):
def on_idle(): def on_idle():
if FishEvent.previousState in (State.FISHING, State.REELIN): if FishEvent.previousState == State.REELIN:
logging.info("HOLE DEPLETED")
_sound_and_send_fishy_data()
elif FishEvent.previousState == State.FISHING:
logging.info("FISHING INTERRUPTED") logging.info("FISHING INTERRUPTED")
_sound_and_send_fishy_data() _sound_and_send_fishy_data()

View File

@ -17,21 +17,6 @@ class State(Enum):
DEAD = 15 DEAD = 15
Colors = {
State.IDLE : [255, 255, 255],
State.LOOKAWAY : [ 76, 0, 76],
State.LOOKING : [101, 69, 0],
State.DEPLETED : [ 0, 76, 76],
State.NOBAIT : [255, 204, 0],
State.FISHING : [ 75, 156, 213],
State.REELIN : [ 0, 204, 0],
State.LOOT : [ 0, 0, 204],
State.INVFULL : [ 0, 0, 51],
State.FIGHT : [204, 0, 0],
State.DEAD : [ 51, 51, 51]
}
def _notify(event): def _notify(event):
for subscriber in subscribers: for subscriber in subscribers:
subscriber(event) subscriber(event)
@ -42,17 +27,12 @@ class FishingMode:
PrevMode = State.IDLE PrevMode = State.IDLE
def loop(rgb): def loop(state_num: int):
""" """
Executed in the start of the main loop in fishy.py Executed in the start of the main loop in fishy.py
Changes modes, calls mode events (callbacks) when mode is changed Changes modes, calls mode events (callbacks) when mode is changed
:param rgb: rgb read by the bot
""" """
FishingMode.CurrentMode = State.IDLE FishingMode.CurrentMode = State(state_num)
for s in State:
if all(rgb == Colors[s]):
FishingMode.CurrentMode = s
if FishingMode.CurrentMode != FishingMode.PrevMode: if FishingMode.CurrentMode != FishingMode.PrevMode:
_notify(FishingMode.CurrentMode) _notify(FishingMode.CurrentMode)

View File

@ -1,66 +0,0 @@
import cv2
def get_keypoint_from_image(img):
"""
convert image int hsv
creates a mask for brown color
uses blob detection to find a blob in the mask
filter the blobs to find the correct one
:param img: rgb image
:return: location of the pixel which is used to detect different fishing states
"""
# Setup SimpleBlobDetector parameters.
hsv_img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
lower = (99, 254, 100)
upper = (100, 255, 101)
mask = cv2.inRange(hsv_img, lower, upper)
# Setup SimpleBlobDetector parameters.
params = cv2.SimpleBlobDetector_Params()
# Change thresholds
params.minThreshold = 10
params.maxThreshold = 255
params.filterByColor = True
params.blobColor = 255
params.filterByCircularity = False
params.filterByConvexity = False
params.filterByInertia = False
params.filterByArea = True
params.minArea = 10.0
detector = cv2.SimpleBlobDetector_create(params)
# Detect blobs.
key_points = detector.detect(mask)
if len(key_points) <= 0:
return None
return int(key_points[0].pt[0]), int(key_points[0].pt[1])
class PixelLoc:
"""
finds the pixel loc and store it
"""
val = None
@staticmethod
def config():
"""
Uses the game window to get an image of the game screen
then uses `GetKeypointFromImage()` to find the Chalutier pixel location
:return: false if pixel loc not found
"""
PixelLoc.val = (0, 0, 1, 1)
return True