mirror of
https://github.com/fishyboteso/fishyboteso.git
synced 2024-08-30 18:32:13 +00:00
re structured window into server client model so that multiple engine can use them simultaneously
This commit is contained in:
parent
825ce11ced
commit
315adf9799
@ -8,7 +8,7 @@ import win32gui
|
|||||||
|
|
||||||
import fishy
|
import fishy
|
||||||
from fishy import web, helper, gui
|
from fishy import web, helper, gui
|
||||||
from fishy.engine.event_handler import EngineEventHandler
|
from fishy.engine.common.event_handler import EngineEventHandler
|
||||||
from fishy.gui import GUI, splash
|
from fishy.gui import GUI, splash
|
||||||
from fishy.helper import Config, hotkey
|
from fishy.helper import Config, hotkey
|
||||||
|
|
||||||
|
0
fishy/engine/common/__init__.py
Normal file
0
fishy/engine/common/__init__.py
Normal file
105
fishy/engine/common/window.py
Normal file
105
fishy/engine/common/window.py
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import logging
|
||||||
|
from enum import Enum
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
import imutils
|
||||||
|
|
||||||
|
from fishy.engine.common import window_server
|
||||||
|
from fishy.engine.common.window_server import WindowServer, Status
|
||||||
|
from fishy.helper import helper
|
||||||
|
|
||||||
|
|
||||||
|
class WindowClient:
|
||||||
|
clients: List['WindowClient'] = []
|
||||||
|
|
||||||
|
def __init__(self, crop=None, color=None, scale=None, show_name=None):
|
||||||
|
"""
|
||||||
|
create a window instance with these pre process
|
||||||
|
:param crop: [x1,y1,x2,y2] array defining the boundaries to crop
|
||||||
|
:param color: color to use example cv2.COLOR_RGB2HSV
|
||||||
|
:param scale: scaling the window
|
||||||
|
"""
|
||||||
|
self.color = color
|
||||||
|
self.crop = crop
|
||||||
|
self.scale = scale
|
||||||
|
self.show_name = show_name
|
||||||
|
self.showing = False
|
||||||
|
|
||||||
|
if len(WindowClient.clients) == 0:
|
||||||
|
window_server.start()
|
||||||
|
WindowClient.clients.append(self)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
WindowClient.clients.remove(self)
|
||||||
|
if len(WindowClient.clients) == 0:
|
||||||
|
window_server.stop()
|
||||||
|
|
||||||
|
def get_capture(self):
|
||||||
|
"""
|
||||||
|
copies the recorded screen and then pre processes its
|
||||||
|
:return: game window image
|
||||||
|
"""
|
||||||
|
if WindowServer.status == Status.CRASHED:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not window_server.screen_ready():
|
||||||
|
logging.info("waiting fors screen...")
|
||||||
|
helper.wait_until(window_server.screen_ready)
|
||||||
|
logging.info("screen ready, continuing...")
|
||||||
|
|
||||||
|
temp_img = WindowServer.Screen
|
||||||
|
|
||||||
|
if temp_img is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if self.color is not None:
|
||||||
|
temp_img = cv2.cvtColor(temp_img, self.color)
|
||||||
|
|
||||||
|
if self.crop is not None:
|
||||||
|
temp_img = temp_img[self.crop[1]:self.crop[3], self.crop[0]:self.crop[2]]
|
||||||
|
|
||||||
|
if self.scale is not None:
|
||||||
|
temp_img = cv2.resize(temp_img, (self.scale[0], self.scale[1]), interpolation=cv2.INTER_AREA)
|
||||||
|
|
||||||
|
return temp_img
|
||||||
|
|
||||||
|
def processed_image(self, func=None):
|
||||||
|
"""
|
||||||
|
processes the image using the function provided
|
||||||
|
:param func: function to process image
|
||||||
|
:return: processed image
|
||||||
|
"""
|
||||||
|
if WindowServer.status == Status.CRASHED:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if func is None:
|
||||||
|
return self.get_capture()
|
||||||
|
else:
|
||||||
|
return func(self.get_capture())
|
||||||
|
|
||||||
|
def show(self, resize=None, func=None, ready_img=None):
|
||||||
|
"""
|
||||||
|
Displays the processed image for debugging purposes
|
||||||
|
:param ready_img: send ready image, just show the `ready_img` directly
|
||||||
|
:param name: unique name for the image, used to create a new window
|
||||||
|
:param resize: scale the image to make small images more visible
|
||||||
|
:param func: function to process the image
|
||||||
|
"""
|
||||||
|
if WindowServer.status == Status.CRASHED:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not self.show_name:
|
||||||
|
logging.warning("You need to assign a name first")
|
||||||
|
return
|
||||||
|
|
||||||
|
if ready_img is None:
|
||||||
|
img = self.processed_image(func)
|
||||||
|
|
||||||
|
if resize is not None:
|
||||||
|
img = imutils.resize(img, width=resize)
|
||||||
|
else:
|
||||||
|
img = ready_img
|
||||||
|
cv2.imshow(self.show_name, img)
|
||||||
|
|
||||||
|
self.showing = True
|
106
fishy/engine/common/window_server.py
Normal file
106
fishy/engine/common/window_server.py
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import logging
|
||||||
|
from enum import Enum
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
import math
|
||||||
|
|
||||||
|
import pywintypes
|
||||||
|
import win32gui
|
||||||
|
from win32api import GetSystemMetrics
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from PIL import ImageGrab
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Status(Enum):
|
||||||
|
CRASHED = -1,
|
||||||
|
STOPPED = 0,
|
||||||
|
RUNNING = 1
|
||||||
|
|
||||||
|
|
||||||
|
class WindowServer:
|
||||||
|
"""
|
||||||
|
Records the game window, and allows to create instance to process it
|
||||||
|
"""
|
||||||
|
Screen = None
|
||||||
|
windowOffset = None
|
||||||
|
titleOffset = None
|
||||||
|
hwnd = None
|
||||||
|
status = Status.STOPPED
|
||||||
|
|
||||||
|
|
||||||
|
def init(borderless: bool):
|
||||||
|
"""
|
||||||
|
Executed once before the main loop,
|
||||||
|
Finds the game window, and calculates the offset to remove the title bar
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
WindowServer.hwnd = win32gui.FindWindow(None, "Elder Scrolls Online")
|
||||||
|
rect = win32gui.GetWindowRect(WindowServer.hwnd)
|
||||||
|
client_rect = win32gui.GetClientRect(WindowServer.hwnd)
|
||||||
|
WindowServer.windowOffset = math.floor(((rect[2] - rect[0]) - client_rect[2]) / 2)
|
||||||
|
WindowServer.titleOffset = ((rect[3] - rect[1]) - client_rect[3]) - WindowServer.windowOffset
|
||||||
|
if borderless:
|
||||||
|
WindowServer.titleOffset = 0
|
||||||
|
WindowServer.status = Status.RUNNING
|
||||||
|
except pywintypes.error:
|
||||||
|
logging.error("Game window not found")
|
||||||
|
WindowServer.status = Status.CRASHED
|
||||||
|
|
||||||
|
|
||||||
|
def loop():
|
||||||
|
"""
|
||||||
|
Executed in the start of the main loop
|
||||||
|
finds the game window location and captures it
|
||||||
|
"""
|
||||||
|
bbox = (0, 0, GetSystemMetrics(0), GetSystemMetrics(1))
|
||||||
|
|
||||||
|
temp_screen = np.array(ImageGrab.grab(bbox=bbox))
|
||||||
|
|
||||||
|
temp_screen = cv2.cvtColor(temp_screen, cv2.COLOR_BGR2RGB)
|
||||||
|
|
||||||
|
rect = win32gui.GetWindowRect(WindowServer.hwnd)
|
||||||
|
crop = (
|
||||||
|
rect[0] + WindowServer.windowOffset, rect[1] + WindowServer.titleOffset, rect[2] - WindowServer.windowOffset,
|
||||||
|
rect[3] - WindowServer.windowOffset)
|
||||||
|
|
||||||
|
WindowServer.Screen = temp_screen[crop[1]:crop[3], crop[0]:crop[2]]
|
||||||
|
|
||||||
|
if WindowServer.Screen.size == 0:
|
||||||
|
logging.error("Don't minimize or drag game window outside the screen")
|
||||||
|
WindowServer.status = Status.CRASHED
|
||||||
|
|
||||||
|
|
||||||
|
def loop_end():
|
||||||
|
cv2.waitKey(25)
|
||||||
|
|
||||||
|
from fishy.engine.common.window import WindowClient
|
||||||
|
for c in WindowClient.clients:
|
||||||
|
if not c.showing:
|
||||||
|
cv2.destroyWindow(c.show_name)
|
||||||
|
|
||||||
|
|
||||||
|
def run():
|
||||||
|
# todo use config
|
||||||
|
while WindowServer.status == Status.RUNNING:
|
||||||
|
loop()
|
||||||
|
loop_end()
|
||||||
|
|
||||||
|
|
||||||
|
def start():
|
||||||
|
if WindowServer.status == Status.RUNNING:
|
||||||
|
return
|
||||||
|
|
||||||
|
init(False)
|
||||||
|
if WindowServer.status == Status.RUNNING:
|
||||||
|
Thread(target=run).start()
|
||||||
|
|
||||||
|
|
||||||
|
def screen_ready():
|
||||||
|
return WindowServer.Screen is not None or WindowServer.status == Status.CRASHED
|
||||||
|
|
||||||
|
|
||||||
|
def stop():
|
||||||
|
WindowServer.status = Status.STOPPED
|
@ -1,5 +1,4 @@
|
|||||||
import math
|
import math
|
||||||
from threading import Thread
|
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import logging
|
import logging
|
||||||
@ -10,31 +9,27 @@ import pywintypes
|
|||||||
import pytesseract
|
import pytesseract
|
||||||
|
|
||||||
from fishy.engine import SemiFisherEngine
|
from fishy.engine import SemiFisherEngine
|
||||||
|
from fishy.engine.common.window import WindowClient
|
||||||
from fishy.engine.semifisher import fishing_event
|
from fishy.engine.semifisher import fishing_event
|
||||||
|
|
||||||
from fishy.engine.IEngine import IEngine
|
from fishy.engine.common.IEngine import IEngine
|
||||||
from fishy.engine.window import Window
|
|
||||||
from pynput import keyboard, mouse
|
from pynput import keyboard, mouse
|
||||||
|
|
||||||
from fishy.helper import Config, hotkey
|
from fishy.helper import Config, hotkey
|
||||||
from fishy.helper.helper import wait_until
|
|
||||||
from fishy.helper.hotkey import Key
|
from fishy.helper.hotkey import Key
|
||||||
|
|
||||||
mse = mouse.Controller()
|
mse = mouse.Controller()
|
||||||
kb = keyboard.Controller()
|
kb = keyboard.Controller()
|
||||||
|
offset = 10
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def sign(x):
|
def sign(x):
|
||||||
return -1 if x < 0 else 1
|
return -1 if x < 0 else 1
|
||||||
|
|
||||||
offset = 10
|
|
||||||
def get_crop_coods(window):
|
def get_crop_coods(window):
|
||||||
Window.loop()
|
|
||||||
img = window.get_capture()
|
img = window.get_capture()
|
||||||
img = cv2.inRange(img, 0, 1)
|
img = cv2.inRange(img, 0, 1)
|
||||||
Window.loop_end()
|
|
||||||
|
|
||||||
cnt, h = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
|
cnt, h = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
|
||||||
|
|
||||||
@ -99,14 +94,7 @@ class FullAuto(IEngine):
|
|||||||
logging.info("Loading please wait...")
|
logging.info("Loading please wait...")
|
||||||
self.initalize_keys()
|
self.initalize_keys()
|
||||||
|
|
||||||
try:
|
self.window = WindowClient(color=cv2.COLOR_RGB2GRAY, show_name="Full auto debug")
|
||||||
Window.init(False)
|
|
||||||
except pywintypes.error:
|
|
||||||
logging.info("Game window not found")
|
|
||||||
self.toggle_start()
|
|
||||||
return
|
|
||||||
|
|
||||||
self.window = Window(color=cv2.COLOR_RGB2GRAY)
|
|
||||||
self.window.crop = get_crop_coods(self.window)
|
self.window.crop = get_crop_coods(self.window)
|
||||||
self._tesseract_dir = self.config.get("tesseract_dir", None)
|
self._tesseract_dir = self.config.get("tesseract_dir", None)
|
||||||
|
|
||||||
@ -119,12 +107,11 @@ class FullAuto(IEngine):
|
|||||||
self.gui.bot_started(True)
|
self.gui.bot_started(True)
|
||||||
|
|
||||||
while self.start:
|
while self.start:
|
||||||
Window.loop()
|
self.window.show(func=image_pre_process)
|
||||||
|
cv2.waitKey(25)
|
||||||
self.window.show("test", func=image_pre_process)
|
|
||||||
Window.loop_end()
|
|
||||||
self.gui.bot_started(False)
|
self.gui.bot_started(False)
|
||||||
unassign_keys()
|
unassign_keys()
|
||||||
|
logging.info("Quit")
|
||||||
|
|
||||||
def get_coods(self):
|
def get_coods(self):
|
||||||
return get_values_from_image(self.window.processed_image(func=image_pre_process), self._tesseract_dir)
|
return get_values_from_image(self.window.processed_image(func=image_pre_process), self._tesseract_dir)
|
||||||
@ -187,7 +174,7 @@ class FullAuto(IEngine):
|
|||||||
fishing_event.subscribers.append(found_hole)
|
fishing_event.subscribers.append(found_hole)
|
||||||
|
|
||||||
t = 0
|
t = 0
|
||||||
while not self._hole_found_flag and t <= self.factors[2]/2:
|
while not self._hole_found_flag and t <= self.factors[2] / 2:
|
||||||
mse.move(0, FullAuto.rotate_by)
|
mse.move(0, FullAuto.rotate_by)
|
||||||
time.sleep(0.05)
|
time.sleep(0.05)
|
||||||
t += 0.05
|
t += 0.05
|
||||||
@ -230,5 +217,5 @@ if __name__ == '__main__':
|
|||||||
bot = FullAuto(c, None)
|
bot = FullAuto(c, None)
|
||||||
fisher = SemiFisherEngine(c, None)
|
fisher = SemiFisherEngine(c, None)
|
||||||
hotkey.initalize()
|
hotkey.initalize()
|
||||||
# fisher.toggle_start()
|
fisher.toggle_start()
|
||||||
bot.toggle_start()
|
bot.toggle_start()
|
||||||
|
@ -8,12 +8,12 @@ import logging
|
|||||||
|
|
||||||
import pywintypes
|
import pywintypes
|
||||||
|
|
||||||
from fishy.engine.IEngine import IEngine
|
from fishy.engine.common.IEngine import IEngine
|
||||||
from fishy.engine.semifisher import fishing_event
|
from fishy.engine.semifisher import fishing_event
|
||||||
from .fishing_event import HookEvent, StickEvent, LookEvent, IdleEvent
|
from .fishing_event import HookEvent, StickEvent, LookEvent, IdleEvent
|
||||||
from .fishing_mode import FishingMode
|
from .fishing_mode import FishingMode
|
||||||
from .pixel_loc import PixelLoc
|
from .pixel_loc import PixelLoc
|
||||||
from fishy.engine.window import Window
|
from ..common.window import WindowClient
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
from fishy.gui import GUI
|
from fishy.gui import GUI
|
||||||
@ -31,16 +31,6 @@ class SemiFisherEngine(IEngine):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
action_key = self.config.get("action_key", "e")
|
action_key = self.config.get("action_key", "e")
|
||||||
borderless = self.config.get("borderless", False)
|
|
||||||
|
|
||||||
# initialize widow
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
try:
|
|
||||||
Window.init(borderless)
|
|
||||||
except pywintypes.error:
|
|
||||||
logging.info("Game window not found")
|
|
||||||
self.start = False
|
|
||||||
return
|
|
||||||
|
|
||||||
# initializes fishing modes and their callbacks
|
# initializes fishing modes and their callbacks
|
||||||
FishingMode("hook", 0, HookEvent(action_key, False))
|
FishingMode("hook", 0, HookEvent(action_key, False))
|
||||||
@ -48,27 +38,24 @@ class SemiFisherEngine(IEngine):
|
|||||||
FishingMode("look", 2, LookEvent(action_key))
|
FishingMode("look", 2, LookEvent(action_key))
|
||||||
FishingMode("idle", 3, IdleEvent(self.config.get("uid"), self.config.get("sound_notification")))
|
FishingMode("idle", 3, IdleEvent(self.config.get("uid"), self.config.get("sound_notification")))
|
||||||
|
|
||||||
self.fishPixWindow = Window(color=cv2.COLOR_RGB2HSV)
|
self.fishPixWindow = WindowClient(color=cv2.COLOR_RGB2HSV)
|
||||||
|
|
||||||
# check for game window and stuff
|
# check for game window and stuff
|
||||||
self.gui.bot_started(True)
|
self.gui.bot_started(True)
|
||||||
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:
|
while self.start:
|
||||||
# Services to be ran in the start of the main loop
|
capture = self.fishPixWindow.get_capture()
|
||||||
success = Window.loop()
|
|
||||||
|
|
||||||
if not success:
|
if capture is None:
|
||||||
|
# if window server crashed
|
||||||
self.gui.bot_started(False)
|
self.gui.bot_started(False)
|
||||||
self.toggle_start()
|
self.toggle_start()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# get the PixelLoc and find the color values, to give it to `FishingMode.Loop`
|
|
||||||
self.fishPixWindow.crop = PixelLoc.val
|
self.fishPixWindow.crop = PixelLoc.val
|
||||||
hue_value = self.fishPixWindow.get_capture()[0][0][0]
|
hue_value = capture[0][0][0]
|
||||||
FishingMode.loop(hue_value)
|
FishingMode.loop(hue_value)
|
||||||
# Services to be ran in the end of the main loop
|
|
||||||
Window.loop_end()
|
|
||||||
logging.info("Fishing engine stopped")
|
logging.info("Fishing engine stopped")
|
||||||
self.gui.bot_started(False)
|
self.gui.bot_started(False)
|
||||||
|
|
||||||
|
@ -1,130 +0,0 @@
|
|||||||
import logging
|
|
||||||
|
|
||||||
import cv2
|
|
||||||
import math
|
|
||||||
import win32gui
|
|
||||||
from win32api import GetSystemMetrics
|
|
||||||
|
|
||||||
import imutils
|
|
||||||
import numpy as np
|
|
||||||
from PIL import ImageGrab
|
|
||||||
|
|
||||||
|
|
||||||
class Window:
|
|
||||||
"""
|
|
||||||
Records the game window, and allows to create instance to process it
|
|
||||||
"""
|
|
||||||
Screen = None
|
|
||||||
windowOffset = None
|
|
||||||
titleOffset = None
|
|
||||||
hwnd = None
|
|
||||||
showing = False
|
|
||||||
|
|
||||||
def __init__(self, crop=None, color=None, scale=None):
|
|
||||||
"""
|
|
||||||
create a window instance with these pre process
|
|
||||||
:param crop: [x1,y1,x2,y2] array defining the boundaries to crop
|
|
||||||
:param color: color to use example cv2.COLOR_RGB2HSV
|
|
||||||
:param scale: scaling the window
|
|
||||||
"""
|
|
||||||
self.color = color
|
|
||||||
self.crop = crop
|
|
||||||
self.scale = scale
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def init(borderless: bool):
|
|
||||||
"""
|
|
||||||
Executed once before the main loop,
|
|
||||||
Finds the game window, and calculates the offset to remove the title bar
|
|
||||||
"""
|
|
||||||
Window.hwnd = win32gui.FindWindow(None, "Elder Scrolls Online")
|
|
||||||
rect = win32gui.GetWindowRect(Window.hwnd)
|
|
||||||
client_rect = win32gui.GetClientRect(Window.hwnd)
|
|
||||||
Window.windowOffset = math.floor(((rect[2] - rect[0]) - client_rect[2]) / 2)
|
|
||||||
Window.titleOffset = ((rect[3] - rect[1]) - client_rect[3]) - Window.windowOffset
|
|
||||||
if borderless:
|
|
||||||
Window.titleOffset = 0
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def loop():
|
|
||||||
"""
|
|
||||||
Executed in the start of the main loop
|
|
||||||
finds the game window location and captures it
|
|
||||||
"""
|
|
||||||
Window.showing = False
|
|
||||||
|
|
||||||
bbox = (0, 0, GetSystemMetrics(0), GetSystemMetrics(1))
|
|
||||||
|
|
||||||
temp_screen = np.array(ImageGrab.grab(bbox=bbox))
|
|
||||||
|
|
||||||
temp_screen = cv2.cvtColor(temp_screen, cv2.COLOR_BGR2RGB)
|
|
||||||
|
|
||||||
rect = win32gui.GetWindowRect(Window.hwnd)
|
|
||||||
crop = (rect[0] + Window.windowOffset, rect[1] + Window.titleOffset, rect[2] - Window.windowOffset,
|
|
||||||
rect[3] - Window.windowOffset)
|
|
||||||
|
|
||||||
Window.Screen = temp_screen[crop[1]:crop[3], crop[0]:crop[2]]
|
|
||||||
|
|
||||||
if Window.Screen.size == 0:
|
|
||||||
logging.info("Don't minimize or drag game window outside the screen")
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def loop_end():
|
|
||||||
"""
|
|
||||||
Executed in the end of the game loop
|
|
||||||
"""
|
|
||||||
cv2.waitKey(25)
|
|
||||||
|
|
||||||
if not Window.showing:
|
|
||||||
cv2.destroyAllWindows()
|
|
||||||
|
|
||||||
def get_capture(self):
|
|
||||||
"""
|
|
||||||
copies the recorded screen and then pre processes its
|
|
||||||
:return: game window image
|
|
||||||
"""
|
|
||||||
temp_img = Window.Screen
|
|
||||||
|
|
||||||
if self.color is not None:
|
|
||||||
temp_img = cv2.cvtColor(temp_img, self.color)
|
|
||||||
|
|
||||||
if self.crop is not None:
|
|
||||||
temp_img = temp_img[self.crop[1]:self.crop[3], self.crop[0]:self.crop[2]]
|
|
||||||
|
|
||||||
if self.scale is not None:
|
|
||||||
temp_img = cv2.resize(temp_img, (self.scale[0], self.scale[1]), interpolation=cv2.INTER_AREA)
|
|
||||||
|
|
||||||
return temp_img
|
|
||||||
|
|
||||||
def processed_image(self, func=None):
|
|
||||||
"""
|
|
||||||
processes the image using the function provided
|
|
||||||
:param func: function to process image
|
|
||||||
:return: processed image
|
|
||||||
"""
|
|
||||||
if func is None:
|
|
||||||
return self.get_capture()
|
|
||||||
else:
|
|
||||||
return func(self.get_capture())
|
|
||||||
|
|
||||||
def show(self, name, resize=None, func=None, ready_img=None):
|
|
||||||
"""
|
|
||||||
Displays the processed image for debugging purposes
|
|
||||||
:param ready_img: send ready image, just show the `ready_img` directly
|
|
||||||
:param name: unique name for the image, used to create a new window
|
|
||||||
:param resize: scale the image to make small images more visible
|
|
||||||
:param func: function to process the image
|
|
||||||
"""
|
|
||||||
if ready_img is None:
|
|
||||||
img = self.processed_image(func)
|
|
||||||
|
|
||||||
if resize is not None:
|
|
||||||
img = imutils.resize(img, width=resize)
|
|
||||||
else:
|
|
||||||
img = ready_img
|
|
||||||
cv2.imshow(name, img)
|
|
||||||
|
|
||||||
Window.showing = True
|
|
@ -5,7 +5,7 @@ import threading
|
|||||||
|
|
||||||
from ttkthemes import ThemedTk
|
from ttkthemes import ThemedTk
|
||||||
|
|
||||||
from fishy.engine.event_handler import EngineEventHandler
|
from fishy.engine.common.event_handler import EngineEventHandler
|
||||||
from fishy.gui import config_top
|
from fishy.gui import config_top
|
||||||
from fishy.gui.funcs import GUIFuncs
|
from fishy.gui.funcs import GUIFuncs
|
||||||
from . import main_gui
|
from . import main_gui
|
||||||
|
Loading…
Reference in New Issue
Block a user