# -*- coding: utf-8 -*- import cv2 import numpy as np import logging from PIL import Image # import pytesseract from pytesseract import image_to_string from resolutionCalculator import * import os import os.path import sys sys.path.insert(0, '../') from screenWrapper import ScreenWrapper import collections import re import time import math import sys reload(sys) sys.setdefaultencoding('utf8') Coordinate = collections.namedtuple("Coordinate", ['x', 'y']) Bounds = collections.namedtuple("Bounds", ['top', 'bottom', 'left', 'right']) log = logging.getLogger(__name__) class PogoWindows: def __init__(self, screenWrapper, width, height, tempDirPath): self.screenWrapper = screenWrapper if not os.path.exists(tempDirPath): os.makedirs(tempDirPath) log.info('PogoWindows: Temp directory created') self.tempDirPath = tempDirPath self.width = width self.height = height def __mostPresentColour(self, filename, maxColours): img = Image.open(filename) colors = img.getcolors(maxColours) # put a higher value if there are many colors in your image max_occurence, most_present = 0, 0 try: for c in colors: if c[0] > max_occurence: (max_occurence, most_present) = c return most_present except TypeError: return None def __checkPostLoginOkButton(self, filename, hash, type, ratio): if not os.path.isfile(filename): return False log.debug('checkPostLoginOkButton: Checking for post-login ok button of type %s...' % type) pos = None if type == 'post_login_ok_driving': pos = self.resolutionCalculator.getPostLoginOkDrivingClick() else: pos = self.resolutionCalculator.getPostLoginOkPrivatePropertyClick() if not self.__lookForButton(filename, 2.20, pos.y): log.debug('checkPostLoginOkButton: Could not find OK button') return False else: log.debug('checkPostLoginOkButton: Found post login OK button - closing ...') self.screenWrapper.click(pos.x, pos.y) return True def isGpsSignalLost(self, filename, hash): if not os.path.isfile(filename): log.error("isGpsSignalLost: %s does not exist" % str(filename)) return None log.debug("isGpsSignalLost: checking for red bar") try: col = cv2.imread(filename) except: log.error("Screenshot corrupted :(") return True if col is None: log.error("Screenshot corrupted :(") return True width, height,_ = col.shape gpsError = col[0:height/7,0:width] tempPathColoured = self.tempDirPath + "/" + str(hash) + "_gpsError.png" cv2.imwrite(tempPathColoured, gpsError) col = Image.open(tempPathColoured) width, height = col.size # check for the colour of the GPS error if self.__mostPresentColour(tempPathColoured, width * height) == (240, 75, 95): return True else: return False def checkPostLoginOkButton(self, filename, hash): log.debug('checkPostLoginOkButton: Starting check') return (self.__checkPostLoginOkButton(filename, hash, 'post_login_ok_driving', 26) or self.__checkPostLoginOkButton(filename, hash, 'post_login_ok_private_property', 17)) def __readCircleCount(self,filename,hash,ratio, xcord = False, crop = False, click = False, canny=False): log.debug("__readCircleCount: Reading circles") try: screenshotRead = cv2.imread(filename) except: log.error("Screenshot corrupted :(") return -1 if screenshotRead is None: log.error("Screenshot corrupted :(") return -1 height, width, _ = screenshotRead.shape if crop: screenshotRead = screenshotRead[int(height)-int(height/4.5):int(height),int(width)/2-int(width)/8:int(width)/2+int(width)/8] log.debug("__readCircleCount: Determined screenshot scale: " + str(height) + " x " + str(width)) gray = cv2.cvtColor(screenshotRead, cv2.COLOR_BGR2GRAY) # detect circles in the image radMin = int((width / float(ratio) - 3) / 2) radMax = int((width / float(ratio) + 3) / 2) if canny: gray = cv2.GaussianBlur(gray, (3, 3), 0) gray = cv2.Canny(gray, 100, 50, apertureSize=3) log.debug("__readCircleCount: Detect radius of circle: Min " + str(radMin) + " Max " + str(radMax)) circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, width / 8, param1=100, param2=15, minRadius=radMin, maxRadius=radMax) circle = 0 # ensure at least some circles were found if circles is not None: # convert the (x, y) coordinates and radius of the circles to integers circles = np.round(circles[0, :]).astype("int") # loop over the (x, y) coordinates and radius of the circles for (x, y, r) in circles: if not xcord: circle += 1 if click: log.debug('__readCircleCount: found Circle - click it') self.screenWrapper.click(width/2, ((int(height)-int(height/4.5)))+y) time.sleep(2) else: if x >= (width / 2) - 100 and x <= (width / 2) + 100 and y >= (height - (height / 3)): circle += 1 if click: log.debug('__readCircleCount: found Circle - click on: it' ) self.screenWrapper.click(width/2, ((int(height)-int(height/4.5)))+y) time.sleep(2) log.debug("__readCircleCount: Determined screenshot to have " + str(circle) + " Circle.") return circle else: log.debug("__readCircleCount: Determined screenshot to have 0 Circle") return -1 def __readCircleCords(self,filename,hash,ratio, crop = False, canny=False): log.debug("__readCircleCords: Reading circlescords") try: screenshotRead = cv2.imread(filename) except: log.error("Screenshot corrupted :(") return False if screenshotRead is None: log.error("Screenshot corrupted :(") return False height, width, _ = screenshotRead.shape if crop: screenshotRead = screenshotRead[int(height)-int(height/5):int(height),int(width)/2-int(width)/8:int(width)/2+int(width)/8] log.debug("__readCircleCords: Determined screenshot scale: " + str(height) + " x " + str(width)) gray = cv2.cvtColor(screenshotRead, cv2.COLOR_BGR2GRAY) # detect circles in the image radMin = int((width / float(ratio) - 3) / 2) radMax = int((width / float(ratio) + 3) / 2) if canny: gray = cv2.GaussianBlur(gray, (3, 3), 0) gray = cv2.Canny(gray, 100, 50, apertureSize=3) log.debug("__readCircleCords: Detect radius of circle: Min " + str(radMin) + " Max " + str(radMax)) circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, width / 8, param1=100, param2=15, minRadius=radMin, maxRadius=radMax) circle = 0 # ensure at least some circles were found if circles is not None: # convert the (x, y) coordinates and radius of the circles to integers circles = np.round(circles[0, :]).astype("int") # loop over the (x, y) coordinates and radius of the circles for (x, y, r) in circles: log.debug("__readCircleCords: Found Circle x: %s y: %s" % (str(width/2), str((int(height)-int(height/5))+y))) return True, width/2, (int(height)-int(height/5))+y, height, width else: log.debug("__readCircleCords: Found no Circle") return False, 0, 0, 0, 0 def readRaidCircles(self, filename, hash): log.debug("readCircles: Reading circles") if not self.readAmountOfRaidsCircle(filename, hash): # no raidcount (orange circle) present... return 0 circle = self.__readCircleCount(filename, hash, 4.7) if circle > 6: circle = 6 if circle > 0: log.debug("readCircles: Determined screenshot to have " + str(circle) + " Circle.") return circle log.debug("readCircles: Determined screenshot to not contain raidcircles, but a raidcount!") return -1 def lookForButton(self, filename, ratiomin, ratiomax): log.debug("lookForButton: Reading lines") disToMiddleMin = None try: screenshotRead = cv2.imread(filename) gray = cv2.cvtColor(screenshotRead, cv2.COLOR_BGR2GRAY) except: log.error("Screenshot corrupted :(") return False if screenshotRead is None: log.error("Screenshot corrupted :(") return False allowRatio = [1.60, 1.05, 2.20, 3.01, 2.32] height, width, _ = screenshotRead.shape _widthold = float(width) log.debug("lookForButton: Determined screenshot scale: " + str(height) + " x " + str(width)) # resize for better line quality #gray = cv2.resize(gray, (0,0), fx=width*0.001, fy=width*0.001) height, width = gray.shape faktor = width / _widthold gray = cv2.GaussianBlur(gray, (3, 3), 0) edges = cv2.Canny(gray, 50, 200, apertureSize=3) #checking for all possible button lines maxLineLength = (width / ratiomin) + (width*0.18) log.debug("lookForButton: MaxLineLength:" + str(maxLineLength)) minLineLength = (width / ratiomax) - (width*0.02) log.debug("lookForButton: MinLineLength:" + str(minLineLength)) kernel = np.ones((2,2),np.uint8) edges = cv2.morphologyEx(edges, cv2.MORPH_GRADIENT, kernel) maxLineGap = 50 lineCount = 0 lines = [] _x = 0 _y = height lines = cv2.HoughLinesP(edges, rho = 1, theta = math.pi / 180, threshold = 70, minLineLength = minLineLength, maxLineGap = 2) if lines is None: return False for line in lines: for x1, y1, x2, y2 in line: if y1 == y2 and (x2 - x1 <= maxLineLength) and (x2 - x1 >= minLineLength) and y1 > height / 2: lineCount += 1 __y = y2 __x1 = x1 __x2 = x2 if __y < _y: _y = __y _x1 = __x1 _x2 = __x2 log.debug("lookForButton: Found Buttonline Nr. " + str(lineCount) + " - Line lenght: " + str( x2 - x1) + "px Coords - X: " + str(x1) + " " + str(x2) + " Y: " + str(y1) + " " + str(y2)) if lineCount > 1 and lineCount <= 6: #recalculate click area for real resolution click_x = int(((width - _x2) + ((_x2 - _x1) /2)) / round(faktor,2)) click_y = int(_y / round(faktor,2) + height*0.03) log.debug('lookForButton: found Button - click on it' ) self.screenWrapper.click(click_x, click_y) time.sleep(4) return True elif lineCount > 6: log.debug('lookForButton: found to much Buttons :) - close it' ) self.screenWrapper.click(int(width - ( width / 7.2)), int(height - ( height / 12.19))) time.sleep(4) return True log.debug('lookForButton: did not found any Button') return False def __checkRaidLine(self, filename, hash, leftSide=False, clickinvers=False): log.debug("__checkRaidLine: Reading lines") if leftSide: log.debug("__checkRaidLine: Check nearby open ") try: screenshotRead = cv2.imread(filename) except: log.error("Screenshot corrupted :(") return False if screenshotRead is None: log.error("Screenshot corrupted :(") return False if self.__readCircleCount(os.path.join('', filename), hash, float(11), xcord=False, crop=True, click=False, canny=True) == -1: log.debug("__checkRaidLine: Not active") return False height, width, _ = screenshotRead.shape screenshotRead = screenshotRead[int(height / 2) - int(height / 3):int(height / 2) + int(height / 3), int(0):int(width)] gray = cv2.cvtColor(screenshotRead, cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(gray, (5, 5), 0) log.debug("__checkRaidLine: Determined screenshot scale: " + str(height) + " x " + str(width)) edges = cv2.Canny(gray, 50, 150, apertureSize=3) maxLineLength = width / 3.30 + width * 0.03 log.debug("__checkRaidLine: MaxLineLength:" + str(maxLineLength)) minLineLength = width / 6.35 - width * 0.03 log.debug("__checkRaidLine: MinLineLength:" + str(minLineLength)) maxLineGap = 50 lines = cv2.HoughLinesP(edges, rho = 1, theta = math.pi / 180, threshold = 70, minLineLength = minLineLength, maxLineGap = 2) if lines is None: return False for line in lines: for x1, y1, x2, y2 in line: if not leftSide: if y1 == y2 and (x2 - x1 <= maxLineLength) and ( x2 - x1 >= minLineLength) and x1 > width / 2 and x2 > width / 2 and y1 < (height / 2): log.debug("__checkRaidLine: Raid-tab is active - Line lenght: " + str( x2 - x1) + "px Coords - X: " + str(x1) + " " + str(x2) + " Y: " + str(y1) + " " + str(y2)) return True # else: log.debug("__checkRaidLine: Raid-tab is not active - Line lenght: " + str(x2-x1) + "px # Coords - X: " + str(x1) + " " + str(x2) + " Y: " + str(y1) + " " + str(y2)) return False else: if y1 == y2 and (x2 - x1 <= maxLineLength) and ( x2 - x1 >= minLineLength) and ((x1 < width / 2 and x2 < width / 2) or (x1 < width / 2 and x2 > width / 2)) and y1 < (height / 2): log.debug("__checkRaidLine: Nearby is active - but not Raid-Tab") if clickinvers: xRaidTab = int(width - (x2-x1)) yRaidTab = int((int(height / 2) - int(height / 3)+y1) * 0.9) log.debug('__checkRaidLine: open Raid-Tab' ) self.screenWrapper.click(xRaidTab, yRaidTab) time.sleep(3) return True # else: # log.debug("__checkRaidLine: Nearby not active - but maybe Raid-tab") # return False log.debug("__checkRaidLine: Not active") return False def readAmountOfRaidsCircle(self, filename, hash): if not os.path.isfile(filename): return None log.debug("readAmountOfRaidsCircle: Cropping circle") try: image = cv2.imread(filename) except: log.error("Screenshot corrupted :(") return False if image is None: log.error("Screenshot corrupted :(") return False height, width, _ = image.shape image = image[int(height / 2 - (height / 3)):int(height / 2 + (height / 3)), 0:int(width)] cv2.imwrite(os.path.join(self.tempDirPath, str(hash) + '_AmountOfRaids.jpg'), image) if self.__readCircleCount(os.path.join(self.tempDirPath, str(hash) + '_AmountOfRaids.jpg'), hash, 18) > 0: log.info("readAmountOfRaidsCircle: Raidcircle found, assuming raids nearby") os.remove(os.path.join(self.tempDirPath, str(hash) + '_AmountOfRaids.jpg')) return True else: log.info("readAmountOfRaidsCircle: No raidcircle found, assuming no raids nearby") os.remove(os.path.join(self.tempDirPath, str(hash) + '_AmountOfRaids.jpg')) return False # assumes we are on the general view of the game def checkRaidscreen(self, filename, hash): log.debug("checkRaidscreen: Checking if RAID is present (nearby tab)") if self.__checkRaidLine(filename, hash): log.debug('checkRaidscreen: RAID-tab found') return True if self.__checkRaidLine(filename, hash, True): log.debug('checkRaidscreen: RAID-tab not activated') return False log.debug('checkRaidscreen: nearby not found') # log.warning('checkRaidscreen: Could not locate RAID-tab') return False def checkNearby(self, filename, hash): try: screenshotRead = cv2.imread(filename) except: log.error("Screenshot corrupted :(") return False if screenshotRead is None: log.error("Screenshot corrupted :(") return False if self.__checkRaidLine(filename, hash): log.info('Nearby already open') return True if self.__checkRaidLine(filename, hash, leftSide=True, clickinvers=True): log.info('Raidscreen not running but nearby open') return False height, width, _ = screenshotRead.shape log.info('Raidscreen not running...') self.screenWrapper.click(int(width - ( width / 7.2)), int(height - ( height / 12.19))) time.sleep(4) return False def checkWeatherWarning(self, filename, hash): if not os.path.isfile(filename): return False log.debug('checkWeatherwarning: Checking for weatherwarning ...') if not self.__lookForButton(filename, 1.05): log.debug('checkWeatherwarning: No weatherwarning found') return False else: log.debug('checkWeatherwarning: Found weather warning - closing ...') posPassenger = self.resolutionCalculator.getWeatherWarningFirstClick() log.debug("checkWeatherwarning: Clicking %s" % str(posPassenger)) self.screenWrapper.click(posPassenger.x, posPassenger.y) time.sleep(1) log.debug('checkWeatherwarning: Also closing the weather info ...') posPassenger = self.resolutionCalculator.getWeatherWarningSecondClick() log.debug("checkWeatherwarning: Clicking %s" % str(posPassenger)) self.screenWrapper.click(posPassenger.x, posPassenger.y) return True def __checkClosePresent(self, filename, hash, radiusratio=12, Xcord=True): if not os.path.isfile(filename): log.warning("__checkClosePresent: %s does not exist" % str(filename)) return False try: image = cv2.imread(filename) height, width, _ = image.shape except: log.error("Screenshot corrupted :(") return False cv2.imwrite(os.path.join(self.tempDirPath, str(hash) + '_exitcircle.jpg'), image) if self.__readCircleCount(os.path.join(self.tempDirPath, str(hash) + '_exitcircle.jpg'), hash, float(radiusratio), xcord=False, crop=True, click=True, canny=True) > 0: return True #checks for X button on any screen... could kill raidscreen, handle properly def checkCloseExceptNearbyButton(self, filename, hash, closeraid = False): try: screenshotRead = cv2.imread(filename) except: log.error("Screenshot corrupted :(") return False if screenshotRead is None: log.error("Screenshot corrupted :(") return False if not closeraid: if (not os.path.isfile(filename) or self.__checkRaidLine(filename, hash) or self.__checkRaidLine(filename, hash, True)): #file not found or raid tab present log.debug("checkCloseExceptNearbyButton: Not checking for close button (X). Input wrong OR nearby window open") return False log.debug("checkCloseExceptNearbyButton: Checking for close button (X). Input wrong OR nearby window open") if (self.__checkClosePresent(filename, hash, 10, True)): log.debug("Found close button (X). Closing the window - Ratio: 10") return True if (self.__checkClosePresent(filename, hash, 12, True)): log.debug("Found close button (X). Closing the window - Ratio: 12") return True if (self.__checkClosePresent(filename, hash, 14, True)): log.debug("Found close button (X). Closing the window - Ratio: 14") return True if (self.__checkClosePresent(filename, hash, 13, True)): log.debug("Found close button (X). Closing the window - Ratio: 13") return True else: log.debug("Could not find close button (X).") return False