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
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):
"""
code from https://stackoverflow.com/a/45770227/4512396
@ -40,7 +49,7 @@ def get_values_from_image(img):
try:
for qr in decode(img):
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")
return None

View File

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

View File

@ -1,4 +1,3 @@
import math
import logging
import math
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.player import Player
from fishy.engine.fullautofisher.mode.recorder import Recorder
from fishy.engine.fullautofisher.qr_detection import (get_qr_location,
get_values_from_image)
from fishy.engine.common.qr_detection import (get_qr_location,
get_values_from_image, image_pre_process)
from fishy.engine.semifisher import fishing_event, fishing_mode
from fishy.engine.semifisher.fishing_mode import FishingMode
from fishy.helper import helper, hotkey
@ -29,15 +28,6 @@ mse = mouse.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):
rotate_by = 30

View File

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

View File

@ -107,7 +107,10 @@ def fisher_callback(event: State):
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")
_sound_and_send_fishy_data()

View File

@ -17,21 +17,6 @@ class State(Enum):
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):
for subscriber in subscribers:
subscriber(event)
@ -42,17 +27,12 @@ class FishingMode:
PrevMode = State.IDLE
def loop(rgb):
def loop(state_num: int):
"""
Executed in the start of the main loop in fishy.py
Changes modes, calls mode events (callbacks) when mode is changed
:param rgb: rgb read by the bot
"""
FishingMode.CurrentMode = State.IDLE
for s in State:
if all(rgb == Colors[s]):
FishingMode.CurrentMode = s
FishingMode.CurrentMode = State(state_num)
if FishingMode.CurrentMode != FishingMode.PrevMode:
_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