I'm learning image detection and python writing a bot for a 2d game. There are certain targets we want to attack and certain targets we want to avoid. One target is displayed on the screen at a time out of a pool of 100 and you click next or attack depending on what you want to do. In doing this you're able to cycle through targets until you find one you want to attack. My code currently checks to see if it finds one of 24 different targets we want to avoid, if it does it avoids that target. Otherwise, it attacks that target.
At the moment my code:
1. Loads 24 different images of things we want to avoid into a NumPy array and checks with `py.locateCenterOnScreen`
if we are on the correct screen to start the video loop
2. Uses cv2.imshow to display a real-time view of what is happening for use later with cv2.rectangles
3. Continuously loops through the NumPy array to determine if any of the loaded images have been found
4. If anything has been found it will either print "avoid" or "attack" to the terminal.
There's also additional logging that I've not added to the below code as it isn't relevant. It simply logs the attack/avoid to a .txt file with time stamps.
My issue:
At the moment my object detection loop for i in image_list:
never stops when it finds one of the 24 images, it loops over them again and again swapping away from the found image.
My question:
When one of the 24 images is detected, how do I stop my detection loop without stopping my cv2.imshow
loop. For example, if image 5 is found. I want to keep image 5 highlighted with cv2.rectangle
rather than only having it highlight for a fraction of a second when it comes up in the detection loop.
# Load Images
def loadImages(directory):
# Intialise empty array
image_list = []
# Add images to array
for i in directory:
img = cv.imread(i, cv.IMREAD_REDUCED_GRAYSCALE_2)
image_list.append((img, i))
return image_list
def objectDetection(image_list, threshold_value):
# Video Loop
while True:
# Listener to check if attack! button displaying
if py.locateCenterOnScreen('!attack.jpg', region = (1282, 931, 1585-1282, 1032-931), grayscale=True) != None:
# Set attack_loop to false as haven't found anything yet, only set to true when something has been attacked
attack_loop = False
while attack_loop is False:
# Grab PSS Window and find size
window = pygetwindow.getWindowsWithTitle('App')[0]
x1 = window.left
y1 = window.top
height = window.height
width = window.width
x2 = x1 + width
y2 = y1 + height
# Actual Video Loop, cropped down to the specific window,
# resized to 1/2 size, and converted to BGR for OpenCV
haystack_img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
(width, height) = (haystack_img.width // 2, haystack_img.height // 2)
haystack_img_resized = haystack_img.resize((width, height))
crop = haystack_img_resized.crop((360,22,600,65))
haystack_img_np = np.array(crop)
haystack = cv.cvtColor(haystack_img_np, cv.COLOR_BGR2GRAY)
cv.imshow("Screen", haystack)
# Object Detection
for i in image_list:
needle_img = i[0]
needle_name = i[1]
result = cv.matchTemplate(haystack, needle_img, cv.TM_CCORR_NORMED)
# Get the best match position
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
# Define top left and bottom right and threshold
(H, W) = i[0].shape[:2]
top_left = max_loc
bottom_right = (top_left[0] + W, top_left[1] + H)
threshold = threshold_value
# If something has been detected click keep looking code
if max_val >= threshold:
cv.rectangle(haystack, top_left, bottom_right, 255, 2)
print("avoid")
else:
print("attack")
if max_val >= threshold:print(max_val)
### Main Script ###
# load images to detect
ships_to_avoid = loadImages(defeat)
# Run actual image detection
objectDetection(ships_to_avoid, 0.92)