| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- import cv2
- import time
- import datetime
- import numpy as np
- import io
- from PIL import Image
- from io import BytesIO
- from ppadb.client import Client as AdbClient
- from PIL import Image
- client = AdbClient(host="127.0.0.1", port=5037)
- device = client.device("192.168.178.32:5555")
- # template positions
- close_sub_fights = cv2.imread('templates/close_sub_fights.jpg')
- close_fight = cv2.imread('templates/close_fight.jpg')
- fight_button = cv2.imread('templates/i.jpg')
- end_of_log = cv2.imread('templates/end_of_log.jpg')
- # cursor positions
- fight_scroll_top = "2494 626"
- titan_fight = "1400 860"
- damage_taken = "450 850"
- close_details = "2175 450"
- close_titan_fight = "2650 570"
- def non_max_suppression(boxes, overlapThresh):
- if len(boxes) == 0:
- return []
- # Convert to float
- boxes = np.array(boxes, dtype="float")
- # Initialize the list of picked indexes
- pick = []
- # Grab the coordinates of the bounding boxes
- x1 = boxes[:,0]
- y1 = boxes[:,1]
- x2 = boxes[:,2]
- y2 = boxes[:,3]
- # Compute the area of the bounding boxes and sort by bottom-right y-coordinate
- area = (x2 - x1 + 1) * (y2 - y1 + 1)
- idxs = np.argsort(y2)
- # Keep looping while some indexes still remain in the indexes list
- while len(idxs) > 0:
- # Grab the last index in the indexes list and add the index value to the list of picked indexes
- last = len(idxs) - 1
- i = idxs[last]
- pick.append(i)
- # Find the largest (x, y) coordinates for the start of the bounding box and the smallest (x, y)
- # coordinates for the end of the bounding box
- xx1 = np.maximum(x1[i], x1[idxs[:last]])
- yy1 = np.maximum(y1[i], y1[idxs[:last]])
- xx2 = np.minimum(x2[i], x2[idxs[:last]])
- yy2 = np.minimum(y2[i], y2[idxs[:last]])
- # Compute the width and height of the bounding box
- w = np.maximum(0, xx2 - xx1 + 1)
- h = np.maximum(0, yy2 - yy1 + 1)
- # Compute the ratio of overlap
- overlap = (w * h) / area[idxs[:last]]
- # Delete all indexes from the index list that have overlap greater than the threshold
- idxs = np.delete(idxs, np.concatenate(([last], np.where(overlap > overlapThresh)[0])))
- # Return only the bounding boxes that were picked
- return boxes[pick].astype("int")
- def screen_has_changed(prev_screenshot, threshold=0.01):
- # Take a new screenshot
- current_screenshot = device.screencap()
- # Convert to NumPy arrays
- prev_img = np.frombuffer(prev_screenshot, dtype=np.uint8)
- current_img = np.frombuffer(current_screenshot, dtype=np.uint8)
- # Load images
- prev_img = cv2.imdecode(prev_img, cv2.IMREAD_COLOR)
- current_img = cv2.imdecode(current_img, cv2.IMREAD_COLOR)
- # Calculate absolute difference
- diff = cv2.absdiff(prev_img, current_img)
- non_zero_count = np.count_nonzero(diff)
- # print(f"diff: {non_zero_count} > {threshold * diff.size} = {non_zero_count > threshold * diff.size}")
- # Check if the difference is greater than the threshold
- return non_zero_count > threshold * diff.size
- def save_screenshot():
- # Take a screenshot
- result = device.screencap()
- timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
- image = Image.open(io.BytesIO(result))
- # TODO: write screenshots to network folder /mnt/t/nextcloud/InstantUpload/Herowars/
- jpeg_filename = f"fights/{timestamp}.jpg"
- image = image.convert('RGB') # Convert to RGB mode for JPEG
- with open(jpeg_filename, "wb") as fp:
- image.save(fp, format='JPEG', quality=85) # Adjust quality as needed
- time.sleep(0.5)
- def wait_for_screen_change():
- # Usage example
- prev_screenshot = device.screencap()
- while not screen_has_changed(prev_screenshot):
- time.sleep(0.1) # Polling interval
- def tap(location):
- device.shell(f"input tap {location}")
- time.sleep(1)
- def swipe(start, end):
- device.shell(f"input swipe {start} {end} 1000")
- time.sleep(0.5)
- def tap_button(template):
- button = find_templates(template)
- if len(button) == 0:
- return
- tap(f"{button[0][0]} {button[0][1]}")
- def is_end_of_log(template):
- templates = find_templates(template)
- result = len(templates) > 0
- if result:
- print(templates)
- print("reached end of guild war log!")
- return result
- def find_templates(template_image):
- screenshot = device.screencap()
- target_image = Image.open(BytesIO(screenshot))
- # Convert the image to a NumPy array and then to BGR format (which OpenCV uses)
- target_image = np.array(target_image)
- target_image = cv2.cvtColor(target_image, cv2.COLOR_RGB2BGR)
- w, h = template_image.shape[:-1]
- # Template matching
- result = cv2.matchTemplate(target_image, template_image, cv2.TM_CCOEFF_NORMED)
- # Define a threshold
- threshold = 0.9 # Adjust this threshold based on your requirements
- # Finding all locations where match exceeds threshold
- locations = np.where(result >= threshold)
- locations = list(zip(*locations[::-1]))
- # Create list of rectangles
- rectangles = [(*loc, loc[0] + w, loc[1] + h) for loc in locations]
- # Apply non-maximum suppression to remove overlaps
- rectangles = non_max_suppression(rectangles, 0.3)
- # Initialize an empty list to store coordinates
- coordinates = []
- for (startX, startY, endX, endY) in rectangles:
- # Calculate the center coordinates
- centerX = round(startX + (endX - startX) / 2)
- centerY = round(startY + (endY - startY) / 2)
- # Append the coordinate pair to the list
- coordinates.append((centerX, centerY))
- return coordinates
- def find_max_y_pair(coordinates):
- # find the coordinate pair with the maximum y value
- result = max(coordinates, key=lambda x: x[1])
- return f"{result[0]} {result[1]}"
- def take_fight_screenshots():
- save_screenshot()
- tap(damage_taken)
- save_screenshot()
- tap_button(close_fight)
- def process_war_log():
- buttons = find_templates(fight_button)
- # process all found buttons
- for pair in buttons:
- tap(f"{pair[0]} {pair[1]}")
- sub_buttons = find_templates(fight_button)
- if (len(sub_buttons) == 0):
- take_fight_screenshots()
- else:
- for pair2 in sub_buttons:
- tap(f"{pair2[0]} {pair2[1]}")
- take_fight_screenshots()
- tap_button(close_sub_fights)
- find_max_y_pair(buttons)
- swipe(find_max_y_pair(buttons), fight_scroll_top)
- # start
- while True:
- process_war_log();
- if is_end_of_log(end_of_log):
- break;
|