abstracted control and log, removed bool from show method, windows scale bug fixed

This commit is contained in:
DESKTOP-JVKHS7I\Adam 2019-02-15 19:14:49 +05:30
parent ca78219163
commit a9e02686a4
5 changed files with 286 additions and 51 deletions

63
controls.py Normal file
View File

@ -0,0 +1,63 @@
from init import *
class Control:
#todo change to 0
current = 1 if arguments["--debug"] else 0
class Keywords(Enum):
SwitchMode = "switch mode"
StartPause = "start/pause"
Debug = "debug"
Stop = "stop"
ConfigPixLoc = "config pixel location"
ClearPrintOnce = "clear print once"
controls = [
{
"name": "SYSTEM",
"controls": [
[Keywords.SwitchMode, Key.f8],
[Keywords.StartPause, Key.f9],
[Keywords.ConfigPixLoc, Key.f10],
[Keywords.Stop, Key.f11]
]
},
{
"name": "DEBUG",
"controls": [
[Keywords.SwitchMode, Key.f8],
[Keywords.ClearPrintOnce, Key.f9],
[Keywords.Debug, Key.f10],
]
}
]
@staticmethod
def getControlHelp():
s = "\n\nCurrent Mode: " + Control.get()["name"]+"\n"
for c in Control.controls[Control.current]["controls"]:
s += c[0].value + ": " + c[1].name + "\n"
return s
@staticmethod
def get():
return Control.controls[Control.current]
@staticmethod
def find(key):
for c in Control.get()["controls"]:
if key == c[1]:
return c
return None
@staticmethod
def nextState():
Control.current += 1
if Control.current >= len(Control.controls):
Control.current = 0

103
fishy.py
View File

@ -8,22 +8,74 @@ def on_release(key):
:return: void
"""
if G.controls["pause"][0] == key:
c = Control.find(key)
if c is None:
return
if c[0] == Control.Keywords.StartPause:
G.pause = not G.pause
if G.pause:
print("PAUSED")
else:
print("STARTED")
elif G.controls["debug"][0] == key:
elif c[0] == Control.Keywords.Debug:
G.debug = not G.debug
elif G.controls["stop"][0] == key:
elif c[0] == Control.Keywords.Stop:
G.stop = True
elif G.controls["configPL"][0] == key:
elif c[0] == Control.Keywords.ConfigPixLoc:
G.configPL = not G.configPL
elif c[0] == Control.Keywords.SwitchMode:
Control.nextState()
Log.ctrl()
elif c[0] == Control.Keywords.ClearPrintOnce:
Log.clearPrintIds()
def ipDebug(img):
# Setup SimpleBlobDetector parameters.
hsvImg = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
lower = (99, 254, 100)
upper = (100, 255, 101)
mask = cv2.inRange(hsvImg, lower, upper)
#mask = cv2.bitwise_not(mask)
# 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.
keypoints = detector.detect(mask)
# Draw detected blobs as red circles.
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures the size of the circle corresponds to the size of blob
draw_keypoints(img, keypoints)
return img
def hsv2rgb(img):
return cv2.cvtColor(img, cv2.COLOR_HSV2RGB)
def startFishing():
"""
@ -45,30 +97,57 @@ def startFishing():
FishingMode("look", 2, LookEvent())
FishingMode("idle", 3, IdleEvent(use_net))
fishPixWindow = Window("fishPixWindow", PixelLoc.val, 1, cv2.COLOR_BGR2HSV)
fishPixDebugWindow = Window("fishPixDebugWindow", PixelLoc.val, 200, cv2.COLOR_BGR2RGB)
fishPixWindow = Window("fishPixWindow", PixelLoc.val, cv2.COLOR_BGR2HSV)
try:
hwnd = win32gui.FindWindow(None, "Elder Scrolls Online")
rect = win32gui.GetWindowRect(hwnd)
clientRect = win32gui.GetClientRect(hwnd)
windowOffset = math.floor(((rect[2] - rect[0]) - clientRect[2]) / 2)
titleOffset = ((rect[3] - rect[1]) - clientRect[3]) - windowOffset
windowLoc = (rect[0] + windowOffset, rect[1] + titleOffset, rect[2] - windowOffset, rect[3] - windowOffset)
gameScreen = Window("game", windowLoc, cv2.COLOR_BGR2RGB)
except pywintypes.error:
print("Game window not found")
return
Log.ctrl()
# todo
time.time()
with Listener(on_release=on_release):
while not G.stop:
time.sleep(sleepFor)
current_time = time.time()
Window.Loop()
Log.Loop()
PixelLoc.Loop()
pixelVal = (PixelLoc.val[0], PixelLoc.val[1], PixelLoc.val[0] + 1, PixelLoc.val[1] + 1)
fishPixWindow.crop = pixelVal
fishPixDebugWindow.crop = pixelVal
hueValue = fishPixWindow.getCapture()[0][0][0]
FishingMode.Loop(hueValue, G.pause)
fishPixDebugWindow.show(G.debug or G.configPL)
if G.debug or G.configPL:
Log.ou(str(FishingMode.CurrentMode.label) + ":" + str(hueValue))
PixelLoc.Loop()
if G.configPL:
fishPixWindow.show(resize=200, func=hsv2rgb)
Log.ou(str(FishingMode.CurrentMode.label) + ":" + str(fishPixWindow.getCapture()[0][0]))
if G.debug:
rect = win32gui.GetWindowRect(hwnd)
gameScreen.crop = (rect[0] + windowOffset, rect[1] + titleOffset, rect[2] - windowOffset,
rect[3] - windowOffset)
gameScreen.show(func=ipDebug)
Log.LoopEnd()
Window.LoopEnd()
frameTime = time.time() - current_time
if frameTime < sleepFor:
time.sleep(sleepFor - frameTime)
if __name__ == "__main__":
startFishing()

93
init.py
View File

@ -3,14 +3,15 @@
Usage:
fishy.py -h | --help
fishy.py -v | --version
fishy.py [--ip=<ipv4>] [--hook-threshold=<int>] [--check-frequency=<hz>] [--no-resize]
fishy.py [--debug] [--ip=<ipv4>] [--hook-threshold=<int>] [--check-frequency=<hz>] [--no-resize]
Options:
-h, --help Show this screen.
-v, --version Show version.
--ip=<ipv4> Local Ip Address of the android phone.
--hook-threshold=<int> Threshold amount for classifier after which label changes [default: 3].
--check-frequency=<hz> Sleep after loop in s [default: 10].
--hook-threshold=<int> Threshold amount for classifier after which label changes [default: 1].
--check-frequency=<hz> Sleep after loop in s [default: 1].
--debug Start program in debug controls.
"""
VERSION = "0.1.0"
@ -37,51 +38,81 @@ try:
from win32api import GetSystemMetrics
import pickle
import win32gui
import pywintypes
from abc import ABC, abstractmethod
from enum import Enum
import sys
import numpy as np
import math
except Exception:
raise
'''
import stack
fishy
pixel_loc
fishing_event
fishing_mode
window
log
controls
init
'''
class G:
fishCaught = 0
stickInitTime = 0
controls = {"stop": [Key.f11, "f11"], "debug": [Key.f10, "f10"], "pause": [Key.f9, "f9"],
"configPL": [Key.f8, "f8"]}
stop = False
pause = True
debug = False
configPL = False
class Log:
ouUsed = False
prevOuUsed = False
ctrl_help = G.controls["configPL"][1] + ": config pixel value\n" + G.controls["pause"][1] + ": start or pause\n" + \
G.controls["debug"][1] + ": start debug\n" + G.controls["stop"][1] + ": quit\n"
@staticmethod
def Loop():
Log.ouUsed = False
@staticmethod
def LoopEnd():
if Log.prevOuUsed and not Log.ouUsed:
print(Log.ctrl_help)
Log.prevOuUsed = Log.ouUsed
@staticmethod
def ctrl():
print(Log.ctrl_help)
@staticmethod
def ou(s):
Log.ouUsed = True
print(s)
def round_float(v, ndigits=2, rt_str=False):
d = Decimal(v)
v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
if rt_str:
return v_str
return Decimal(v_str)
def draw_keypoints(vis, keypoints, color=(0, 0, 255)):
for kp in keypoints:
x, y = kp.pt
cv2.circle(vis, (int(x), int(y)), 5, color, -1)
def image_resize(image, width=None, height=None, inter = cv2.INTER_AREA):
# initialize the dimensions of the image to be resized and
# grab the image size
dim = None
(h, w) = image.shape[:2]
# if both the width and height are None, then return the
# original image
if width is None and height is None:
return image
# check to see if the width is None
if width is None:
# calculate the ratio of the height and construct the
# dimensions
r = height / float(h)
dim = (int(w * r), height)
# otherwise, the height is None
else:
# calculate the ratio of the width and construct the
# dimensions
r = width / float(w)
dim = (width, int(h * r))
# resize the image
resized = cv2.resize(image, dim, interpolation = inter)
# return the resized image
return resized
# np.set_printoptions(threshold=sys.maxsize)

37
log.py Normal file
View File

@ -0,0 +1,37 @@
from controls import *
class Log:
ouUsed = False
prevOuUsed = False
printIds = []
@staticmethod
def Loop():
Log.ouUsed = False
@staticmethod
def LoopEnd():
if Log.prevOuUsed and not Log.ouUsed:
Log.ctrl()
Log.prevOuUsed = Log.ouUsed
@staticmethod
def ctrl():
print(Control.getControlHelp())
@staticmethod
def ou(s):
Log.ouUsed = True
print(s)
@staticmethod
def po(id, s):
if id not in Log.printIds:
print(s)
Log.printIds.append(id)
@staticmethod
def clearPrintIds():
Log.printIds = []

View File

@ -1,32 +1,57 @@
from init import *
from log import *
class Window:
Screen = None
wins = []
def __init__(self, name, crop, scale, color):
def __init__(self, name, crop, color, scale=None):
self.color = color
self.crop = crop
self.scale = scale
self.name = name
self.showed = False
Window.wins.append(self)
@staticmethod
def Loop():
bbox = (0, 0, GetSystemMetrics(0), GetSystemMetrics(1))
Window.Screen = np.array(ImageGrab.grab(bbox=bbox))
@staticmethod
def LoopEnd():
cv2.waitKey(25)
def show(self, show):
if show:
cv2.imshow(self.name, self.getCapture())
else:
cv2.destroyWindow(self.name)
for w in Window.wins:
if not w.showed:
cv2.destroyWindow(w.name)
w.showed = False
def getCapture(self):
temp_img = cv2.cvtColor(Window.Screen, self.color)
temp_img = temp_img[self.crop[1]:self.crop[3], self.crop[0]:self.crop[2]]
temp_img = imutils.resize(temp_img, width=self.scale)
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 processedImage(self, func=None):
if func is None:
return self.getCapture()
else:
return func(self.getCapture())
def show(self, resize=None, func=None):
img = self.processedImage(func)
if resize is not None:
img = imutils.resize(img, width=resize)
cv2.imshow(self.name, img)
self.showed = True