Compare commits

..

58 Commits

Author SHA1 Message Date
7eed550797 Merge remote-tracking branch 'origin/master' 2023-08-24 09:43:27 +02:00
cc9789c65c ring fix 2023-08-24 09:43:13 +02:00
d64b704274 update menti 2023-08-06 16:36:52 +02:00
ed23f196a6 update menti 2023-08-06 16:32:45 +02:00
b8abdb690b update menti 2023-08-06 16:30:20 +02:00
8d2aad34b2 update menti 2023-08-06 16:25:52 +02:00
e70c7d2be9 update menti 2023-08-06 16:23:55 +02:00
5005670bd3 update menti 2023-08-06 16:21:48 +02:00
b1fc655c0b update menti 2023-08-06 16:12:13 +02:00
9cc4018747 update flappy 2023-07-30 18:46:40 +02:00
849aaf8e27 update flappy 2023-07-30 18:42:53 +02:00
804f178fbf update flappy 2023-07-30 15:08:29 +02:00
c1eecfd567 update flappy 2023-07-30 15:05:47 +02:00
99a2976b61 update flappy 2023-07-30 15:01:20 +02:00
cadcfe8103 update litris with board detection 2023-07-30 14:28:15 +02:00
ab0def9115 update litris with board detection 2023-07-30 10:57:43 +02:00
b24a835f18 update litris with board detection 2023-07-30 10:08:33 +02:00
0a15b57fe5 Merge remote-tracking branch 'origin/master' 2023-07-30 10:00:17 +02:00
a7d2a73b00 update litris with board detection 2023-07-30 10:00:07 +02:00
Thaloria@web.de
3d209ca811 litris update 2023-07-30 00:49:42 +02:00
Thaloria@web.de
01768dc115 litris update 2023-07-30 00:29:36 +02:00
f32cbb8f2d update litris with board detection 2023-07-30 00:08:39 +02:00
7a539e301b update litris with board detection 2023-07-29 21:43:48 +02:00
00461177de update litris with board detection 2023-07-29 21:36:31 +02:00
7c6af4411b update litris with board detection 2023-07-29 21:32:53 +02:00
c3e677ca0a update litris with board detection 2023-07-29 21:30:00 +02:00
332190394d update litris with board detection 2023-07-29 21:20:50 +02:00
d3ace50341 update litris with board detection 2023-07-29 21:14:13 +02:00
8918683e5a update litris with board detection 2023-07-29 21:07:22 +02:00
b08356b036 update litris with board detection 2023-07-29 21:01:51 +02:00
ffca884a25 update litris with board detection 2023-07-29 20:54:00 +02:00
d3d2e1e65e update litris with board detection 2023-07-29 20:46:25 +02:00
6ec1b71d28 update litris with board detection 2023-07-29 20:20:18 +02:00
07d00404d8 update litris with board detection 2023-07-29 20:20:11 +02:00
c9081bd371 update litris with board detection 2023-07-29 20:12:51 +02:00
a9b76cde97 flappy init 2023-07-29 19:42:17 +02:00
2fa0255761 flappy init 2023-07-29 19:34:12 +02:00
c7dd04590a flappy init 2023-07-28 15:31:16 +02:00
189b81b3a0 flappy init 2023-07-28 15:28:25 +02:00
545127dcbc flappy init 2023-07-28 13:26:54 +02:00
bfd8690535 flappy init 2023-07-28 13:13:20 +02:00
c43399ac2a flappy init 2023-07-27 21:16:19 +02:00
33c7400fa4 flappy init 2023-07-27 20:55:54 +02:00
862fbf8bc6 flappy init 2023-07-27 17:58:57 +02:00
8ded30d75a menti words init 2023-07-27 13:02:42 +02:00
eff65b3ca4 menti words init 2023-07-26 22:28:30 +02:00
ef7669f015 menti words init 2023-07-26 22:00:57 +02:00
2d23f8e311 menti words init 2023-07-26 17:11:30 +02:00
38ac30cc64 menti words init 2023-07-26 17:04:53 +02:00
fc965a5133 menti words init 2023-07-26 17:02:57 +02:00
e11b2b8e94 menti words init 2023-07-26 16:58:43 +02:00
a82c069048 menti words init 2023-07-26 16:55:41 +02:00
5c24629b85 menti words init 2023-07-26 16:52:43 +02:00
f1bb158b21 menti words init 2023-07-26 16:49:09 +02:00
95f87d1c2e menti words init 2023-07-26 16:46:15 +02:00
cde729f820 menti words init 2023-07-26 16:43:36 +02:00
9841d6fae4 menti words init 2023-07-26 16:41:08 +02:00
f4d7523c3d menti words init 2023-07-26 16:37:04 +02:00
70 changed files with 394 additions and 68 deletions

View File

@@ -12,6 +12,7 @@ from fruit import Fruit
from pickaxe import Pickaxe_Field from pickaxe import Pickaxe_Field
from litris import Litris from litris import Litris
from menti_words import MentiWords from menti_words import MentiWords
from flappy import Flappy
def run(): def run():
@@ -73,6 +74,10 @@ def run():
elif overlay.rb_int.get() == 11: elif overlay.rb_int.get() == 11:
menti = MentiWords(overlay) menti = MentiWords(overlay)
menti.execute_main_loop() menti.execute_main_loop()
elif overlay.rb_int.get() == 12:
flappy = Flappy(overlay)
flappy.execute_main_loop()
flappy.flappy_pos_disc.run_mode = 'stop'
if __name__ == "__main__": if __name__ == "__main__":
run() run()

View File

@@ -33,7 +33,7 @@ class PrimaryOverlay(threading.Thread):
self.Emitter_Box = ttk.Combobox self.Emitter_Box = ttk.Combobox
self.RadioButtons = dict self.RadioButtons = dict
self.RadioButtonNames = ["Equip", "Crops", "Farm", "Magic", "Craft", "Mine", "Fruit", "Sodo", "PAxe", "Ltris", "Menti"] self.RadioButtonNames = ["Equip", "Crops", "Farm", "Magic", "Craft", "Mine", "Fruit", "Sodo", "PAxe", "Ltris", "Menti", "Flapp"]
self.RadioButton1 = tk.Radiobutton self.RadioButton1 = tk.Radiobutton
self.RadioButton2 = tk.Radiobutton self.RadioButton2 = tk.Radiobutton
self.RadioButton3 = tk.Radiobutton self.RadioButton3 = tk.Radiobutton
@@ -45,12 +45,13 @@ class PrimaryOverlay(threading.Thread):
self.RadioButton9 = tk.Radiobutton self.RadioButton9 = tk.Radiobutton
self.RadioButton10 = tk.Radiobutton self.RadioButton10 = tk.Radiobutton
self.RadioButton11 = tk.Radiobutton self.RadioButton11 = tk.Radiobutton
self.RadioButton12 = tk.Radiobutton
self.StartButton = tk.Button self.StartButton = tk.Button
self.StopButton = tk.Button self.StopButton = tk.Button
self.PauseButton = tk.Button self.PauseButton = tk.Button
self.QuitButton = tk.Button self.QuitButton = tk.Button
self.TkPosition = '133x429+60+600' self.TkPosition = '133x454+60+600'
self.setDaemon(True) self.setDaemon(True)
self.StatusLabel = tk.Label self.StatusLabel = tk.Label
@@ -78,7 +79,7 @@ class PrimaryOverlay(threading.Thread):
self.rb_int = tk.IntVar(self.root, value=1) self.rb_int = tk.IntVar(self.root, value=1)
self.RadioButtons = dict() self.RadioButtons = dict()
# var = tk.IntVar(value=1) # var = tk.IntVar(value=1)
for i in range(1, 12): for i in range(1, 13):
self.RadioButtons[i] = tk.Radiobutton(self.rb_frame, text=self.RadioButtonNames[i - 1], self.RadioButtons[i] = tk.Radiobutton(self.rb_frame, text=self.RadioButtonNames[i - 1],
variable=self.rb_int, variable=self.rb_int,
value=i, command=self.radio_button_callback) value=i, command=self.radio_button_callback)
@@ -338,6 +339,17 @@ class PrimaryOverlay(threading.Thread):
self.SpawnLabel.configure(text="") self.SpawnLabel.configure(text="")
self.EnergyLabel.configure(text="") self.EnergyLabel.configure(text="")
self.hide_mining_overlay() self.hide_mining_overlay()
elif self.rb_int.get() == 12:
self.EnergyEntry.configure(state=tk.DISABLED)
self.energy_use.set('')
self.SpawnEntry.configure(state=tk.DISABLED)
self.spawn_use.set('')
self.Emitter_Box.configure(state=tk.DISABLED)
self.emitter_use.set('')
self.EmitterLabel.configure(text="")
self.SpawnLabel.configure(text="")
self.EnergyLabel.configure(text="")
self.hide_mining_overlay()
def get_run_mode(self): def get_run_mode(self):
return self.run_mode return self.run_mode

View File

@@ -10,7 +10,7 @@ from config_file import UserConfigs
# load the original input image and display it to our screen # load the original input image and display it to our screen
#filename = "equip/chests/chest_23_32" #filename = "equip/chests/chest_23_32"
path = "equip/wands/" path = "flappy/"
os.chdir(path) os.chdir(path)
for entry in os.listdir(): for entry in os.listdir():

View File

@@ -112,6 +112,9 @@ class Equipment(GameBase):
spawn_1 = self.find_emitter(emitter, screenshot, 1) spawn_1 = self.find_emitter(emitter, screenshot, 1)
if len(spawn_1) == 1: if len(spawn_1) == 1:
#output_by_area = self.vision_stun.draw_rectangles(screenshot, spawn_1)
#cv.imshow("spawn_1", output_by_area)
#cv.waitKey(150)
points = self.vision_stun.get_click_points(spawn_1) points = self.vision_stun.get_click_points(spawn_1)
for i in range(0, self.SPAWN_COUNT, 1): for i in range(0, self.SPAWN_COUNT, 1):
self.click_point(points[0][0], points[0][1]) self.click_point(points[0][0], points[0][1])
@@ -316,7 +319,7 @@ class Equipment(GameBase):
else: else:
needle = cv.imread("equip/emitters/ring_e2_32.jpg", cv.IMREAD_UNCHANGED) needle = cv.imread("equip/emitters/ring_e2_32.jpg", cv.IMREAD_UNCHANGED)
mask = cv.imread("equip/emitters/ring_e2_32-mask.png", cv.IMREAD_COLOR) mask = cv.imread("equip/emitters/ring_e2_32-mask.png", cv.IMREAD_COLOR)
return self.vision_stun.find(screen, needle, 0.95, 1, True, mask) return self.vision_stun.find(screen, needle, 0.95, 1, False, mask)
elif emitter_to_use == EMITTER_WAND: elif emitter_to_use == EMITTER_WAND:
if layer == 0: if layer == 0:
needle = cv.imread("equip/emitters/wand_e1_32.jpg", cv.IMREAD_UNCHANGED) needle = cv.imread("equip/emitters/wand_e1_32.jpg", cv.IMREAD_UNCHANGED)

View File

@@ -14,7 +14,6 @@ class Field():
else: else:
self.state = [[' ' for cols in range(Field.WIDTH)] self.state = [[' ' for cols in range(Field.WIDTH)]
for rows in range(Field.HEIGHT)] for rows in range(Field.HEIGHT)]
#self.rotate_90_degree_clckwise(self.state)
self.cleared_rows = 1 self.cleared_rows = 1
def __str__(self): def __str__(self):
@@ -24,7 +23,8 @@ class Field():
'{:2d} |'.format(i) + ' '.join(row) + '|' '{:2d} |'.format(i) + ' '.join(row) + '|'
for i, row in enumerate(self.state)]) + '\n' + BAR for i, row in enumerate(self.state)]) + '\n' + BAR
def matrixflip(self, m, d): @staticmethod
def matrixflip(m, d):
tempm = m.copy() tempm = m.copy()
if d == 'h': if d == 'h':
for i in range(0, len(tempm), 1): for i in range(0, len(tempm), 1):
@@ -33,14 +33,16 @@ class Field():
tempm.reverse() tempm.reverse()
return (tempm) return (tempm)
def rotate_90_degree_anticlckwise(self, matrix): @staticmethod
def rotate_90_degree_anticlckwise(matrix):
new_matrix = [] new_matrix = []
for i in range(len(matrix[0]), 0, -1): for i in range(len(matrix[0]), 0, -1):
new_matrix.append(list(map(lambda x: x[i - 1], matrix))) new_matrix.append(list(map(lambda x: x[i - 1], matrix)))
return new_matrix return new_matrix
def rotate_90_degree_clckwise(self, matrix): @staticmethod
def rotate_90_degree_clckwise(matrix):
new_matrix = [] new_matrix = []
for i in range(len(matrix[0])): for i in range(len(matrix[0])):
li = list(map(lambda x: x[i], matrix)) li = list(map(lambda x: x[i], matrix))
@@ -58,9 +60,8 @@ class Field():
self.state[row] = [' ' for cols in range(Field.WIDTH)] self.state[row] = [' ' for cols in range(Field.WIDTH)]
def rotate_state(self): def rotate_state(self):
self.state = self.rotate_90_degree_anticlckwise(self.state) self.state = Field.rotate_90_degree_anticlckwise(self.state)
#self.state = self.matrixflip(self.state, 'v')
#print(self.state)
def get_line_count(self): def get_line_count(self):
return self.cleared_rows return self.cleared_rows
@@ -151,9 +152,14 @@ class Field():
def check_crucial_pos_to_be_free(self):
if self.state[19][9] == ' ' and self.state[19][10] == ' ' and self.state[18][9] == ' ' and self.state[18][10] == ' ':
return True
return False
def predict_gaps_in_next_rotation(self): def predict_gaps_in_next_rotation(self):
tmp_state = copy(self.state) tmp_state = copy(self.state)
tmp_state = self.rotate_90_degree_anticlckwise(tmp_state) tmp_state = Field.rotate_90_degree_anticlckwise(tmp_state)
for row in range(int(self.HEIGHT/2)): for row in range(int(self.HEIGHT/2)):
tmp_state[row] = [' ' for cols in range(Field.WIDTH)] tmp_state[row] = [' ' for cols in range(Field.WIDTH)]
return sum( return sum(

49
flappy.py Normal file
View File

@@ -0,0 +1,49 @@
import cv2 as cv
import pydirectinput
from game_base_class import GameBase
from flappy_pos_discovery_thread import FlappyPosDiscovery
from keyboard_thread import KeyboardEvent
class Flappy(GameBase):
def __init__(self, overlay):
super().__init__(overlay)
self.litris_reset_board = cv.imread("control_elements/sodoku_reset_button.jpg", cv.IMREAD_COLOR)
self.flappy_pos_disc = FlappyPosDiscovery()
self.keyboard_listener = KeyboardEvent()
def assess_playfield_and_make_move(self):
#last_letter_received = time()
while True:
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
wait_timer = 380 + self.keyboard_listener.offset_value
self.click()
cv.waitKey(wait_timer)
'''
if self.flappy_pos_disc.next_gate_height[0] is not 0:
offset = (self.flappy_pos_disc.next_gate_height[0] + 120) - self.flappy_pos_disc.get_actual_pet_height()
if offset > 50:
self.click()
cv.waitKey(int(wait_timer -100))
print("pet_pos: ", self.flappy_pos_disc.get_actual_pet_height())
if self.flappy_pos_disc.next_gate_height[0] is not 0:
offset = (self.flappy_pos_disc.next_gate_height[0] + 120) - self.flappy_pos_disc.current_pet_height
if offset > 50:
offset = 50
elif offset < -50:
offset = -50
print(offset)
wait_timer = 380 + offset
print(wait_timer)
print("pet_pos: ", self.flappy_pos_disc.current_pet_height)
print("next gate: ", self.flappy_pos_disc.next_gate_height[0] + 120) '''
def click(self):
pydirectinput.mouseDown()
cv.waitKey(50)
pydirectinput.mouseUp()

BIN
flappy/flappy-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

BIN
flappy/flappy.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
flappy/flappy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
flappy/gate-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
flappy/gate.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
flappy/gate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 KiB

BIN
flappy/screen.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB

View File

@@ -0,0 +1,83 @@
import threading
import cv2 as cv
from window_capture import WindowCapture
from vision import Vision
from config_file import UserConfigs
class FlappyPosDiscovery(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.config = UserConfigs()
self.capture_window = WindowCapture(None, None, self.config)
self.vision_stun = Vision()
self.needle_f = self.scale_picture(cv.imread("flappy/flappy.jpg"), 50)
self.mask_f = self.scale_picture(cv.imread("flappy/flappy-mask.png"), 50)
self.needle_g = self.scale_picture(cv.imread("flappy/gate.jpg"), 50)
self.mask_g = self.scale_picture(cv.imread("flappy/gate-mask.png"), 50)
self.run_mode = 'run'
self.current_pet_height = []
self.next_gate_height = [0,0,0]
self.offset_down = 90
self.start()
def run(self):
while self.run_mode == 'run':
screenshot_g = self.scale_picture(self.capture_window.get_screenshot_by_area([700, 1200, 1860, 90]), 50)
screenshot_f = self.scale_picture(self.capture_window.get_screenshot_by_area([200, 1250, 610, 90]), 50)
#cv.imshow("screenshot_g", screenshot_f)
#cv.waitKey(150)
rectangles_g = self.vision_stun.find(screenshot_g, self.needle_g, 0.8, 1)
rectangles_f = self.vision_stun.find(screenshot_f, self.needle_f, 0.7, 1) #, True, self.mask_f)
if len(rectangles_g) is not 0:
height = rectangles_g[0][1] + rectangles_g[0][3] + (self.offset_down /2)
if self.next_gate_height[2] is not height:
self.next_gate_height.append(height)
if len(self.next_gate_height) > 3:
self.next_gate_height.pop(0)
#pro_screen = self.vision_stun.draw_rectangles(screenshot_g, rectangles_g)
#cv.imshow("screenshot_g", pro_screen)
#cv.waitKey(150)
else:
pass
if len(rectangles_f) is not 0:
self.current_pet_height.append(rectangles_f[0][1] + rectangles_f[0][3] + self.offset_down)
if len(self.current_pet_height) > 5:
self.current_pet_height.pop(0)
#print("pet_pos: ", self.current_pet_height)
#print("next gate: ", self.next_gate_height)
def scale_picture(self, img, scale_percent):
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
resized_img = cv.resize(img, (width, height), interpolation=4)
gray = cv.cvtColor(resized_img, cv.COLOR_BGR2GRAY)
thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
return thresh
def get_actual_pet_height(self):
return sum(self.current_pet_height) / len(self.current_pet_height)
def get_next_gate_height(self):
return self.next_gate_height

32
keyboard_thread.py Normal file
View File

@@ -0,0 +1,32 @@
import threading
import cv2 as cv
import keyboard
class KeyboardEvent(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.run_mode = 'run'
self.offset_value = 0
self.start()
def run(self):
while self.run_mode == 'run':
if keyboard.is_pressed('up'): # if key 'q' is pressed
self.offset_value = -75
elif keyboard.is_pressed('down'):
self.offset_value = 75
elif keyboard.is_pressed('left') or keyboard.is_pressed('right'):
self.offset_value = 0
cv.waitKey(10)
def callback(self):
pass
def destroy(self):
self.destroy()
def get_run_mode(self):
return self.run_mode

View File

@@ -1,3 +1,5 @@
from copy import copy
import cv2 as cv import cv2 as cv
import numpy as np import numpy as np
from time import time from time import time
@@ -15,43 +17,37 @@ class Litris(GameBase):
self.keyboard = Controller() self.keyboard = Controller()
self.data_coordinates = np.zeros((20, 20), dtype=object)
self.observation = np.zeros((20, 20), dtype=int)
self.colors = [1, 2, 3, 4, 5, 6, 7, 8, 9]
self.offset_left = 610 self.offset_left = 610
self.offset_down = 40 self.offset_down = 40
self.fill_data_coordinates()
self.field = Field() self.field = Field()
self.field_mem = Field()
self.litris_reset_board = cv.imread("control_elements/sodoku_reset_button.jpg", cv.IMREAD_COLOR) self.litris_reset_board = cv.imread("control_elements/sodoku_reset_button.jpg", cv.IMREAD_COLOR)
self.stone_id_thread = NewStoneID() self.stone_id_thread = NewStoneID()
self.move_mode = 1 self.move_mode = 1
self.moved_around_full = False
def fill_data_coordinates(self): self.field_state_storage = {
# 610 to 1950 = 1340 - 76 / 20 = 63 1: self.field,
# 40 to 1380 = 1340 - 76 / 20 = 63 2: self.field,
# spacing 19 * 4 3: self.field,
dim = 63 4: self.field
e_spacing = 4 }
i_spacing = 4
for e in range(0, 20, 1): def reset(self):
for i in range(0, 20, 1): self.field.reset_field()
self.data_coordinates[e][i] = [(i * dim) + (i * i_spacing), (e * dim) + (e * e_spacing), dim, dim] self.field.cleared_rows = 1
self.move_mode = 1
self.moved_around_full = False
def assess_playfield_and_make_move(self): def assess_playfield_and_make_move(self):
last_letter_received = time() last_letter_received = time()
while True: while True:
if self.stone_id_thread.get_pick_up_status() == False: if self.stone_id_thread.get_pick_up_status() == False:
if (time() - last_letter_received) >= 5: if (time() - last_letter_received) >= 5:
self.field.reset_field() self.reset()
self.field.cleared_rows = 1
last_letter_received = time() last_letter_received = time()
self.dig_point(1500, 980, 100) self.dig_point(1500, 980, 100)
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
@@ -59,7 +55,7 @@ class Litris(GameBase):
continue continue
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return return
cv.waitKey(50) cv.waitKey(25)
continue continue
@@ -89,21 +85,46 @@ class Litris(GameBase):
self.move_stone(column - offset_col, rotation) self.move_stone(column - offset_col, rotation)
self.drop_down() self.drop_down()
print(self.field) print(self.field)
if self.field.get_line_count() >= 6 and self.field.height() <= 2: if self.field.get_line_count() >= 6 and self.field.height() <= 2 and self.field.check_crucial_pos_to_be_free():
if self.field.predict_gaps_in_next_rotation() <= 5: if self.field.predict_gaps_in_next_rotation() <= 3:
self.field_state_storage[self.move_mode] = copy(self.field)
self.update_move_mode() self.update_move_mode()
#self.field.state = self.stone_id_thread.get_current_board_state()
self.field.rotate_state() self.field.rotate_state()
#self.update_move_mode() #self.update_move_mode()
self.field.reset_half_field() self.field.reset_half_field()
self.update_field_with_stored_edges()
#field_mem = copy(self.field) #field_mem = copy(self.field)
#self.field = copy(self.field_mem) #self.field = copy(self.field_mem)
#self.field_mem = copy(field_mem) #self.field_mem = copy(field_mem)
self.field.cleared_rows = 1 self.field.cleared_rows = 1
cv.waitKey(200) cv.waitKey(100)
self.stone_id_thread.set_pick_up_status(False) self.stone_id_thread.set_pick_up_status(False)
def update_field_with_stored_edges(self):
if self.move_mode == 1 and self.moved_around_full:
state_copy = Field.rotate_90_degree_clckwise(copy(self.field_state_storage[2].state))
for i in range(11,20,1):
for e in range(0,2,1):
self.field.state[i][e] = state_copy[i][e]
elif self.move_mode == 2 and self.moved_around_full:
state_copy = Field.rotate_90_degree_clckwise(copy(self.field_state_storage[3].state))
for i in range(11,20,1):
for e in range(0,2,1):
self.field.state[i][e] = state_copy[i][e]
elif self.move_mode == 3 and self.moved_around_full:
state_copy = Field.rotate_90_degree_clckwise(copy(self.field_state_storage[4].state))
for i in range(11, 20, 1):
for e in range(0, 2, 1):
self.field.state[i][e] = state_copy[i][e]
elif self.move_mode == 4:
state_copy = Field.rotate_90_degree_clckwise(copy(self.field_state_storage[1].state))
for i in range(11,20,1):
for e in range(0,2,1):
self.field.state[i][e] = state_copy[i][e]
self.moved_around_full = True
def drop_down(self): def drop_down(self):
if self.move_mode == 1: if self.move_mode == 1:
@@ -126,7 +147,7 @@ class Litris(GameBase):
self.keyboard.press(down) self.keyboard.press(down)
self.keyboard.release(down) self.keyboard.release(down)
print("drop down pressed:", down) print("drop down pressed:", down)
cv.waitKey(50) cv.waitKey(40)
def update_move_mode(self): def update_move_mode(self):
if self.move_mode <=3: if self.move_mode <=3:
@@ -159,13 +180,13 @@ class Litris(GameBase):
self.keyboard.press(down) self.keyboard.press(down)
self.keyboard.release(down) self.keyboard.release(down)
print("direction pressed: ", down) print("direction pressed: ", down)
cv.waitKey(120) cv.waitKey(60)
if rotation == 3: if rotation == 3:
self.keyboard.press('e') self.keyboard.press('e')
self.keyboard.release('e') self.keyboard.release('e')
print("rotation 1 pressed: e") print("rotation 1 pressed: e")
cv.waitKey(40) cv.waitKey(30)
elif rotation == 2: elif rotation == 2:
self.keyboard.press('e') self.keyboard.press('e')
self.keyboard.release('e') self.keyboard.release('e')
@@ -179,28 +200,28 @@ class Litris(GameBase):
self.keyboard.press('e') self.keyboard.press('e')
self.keyboard.release('e') self.keyboard.release('e')
print("rotation 3 pressed: e 1") print("rotation 3 pressed: e 1")
cv.waitKey(20) cv.waitKey(30)
self.keyboard.press('e') self.keyboard.press('e')
self.keyboard.release('e') self.keyboard.release('e')
print("rotation 3 pressed: e 2") print("rotation 3 pressed: e 2")
cv.waitKey(20) cv.waitKey(30)
self.keyboard.press('e') self.keyboard.press('e')
self.keyboard.release('e') self.keyboard.release('e')
print("rotation 3 pressed: e 3") print("rotation 3 pressed: e 3")
cv.waitKey(20) cv.waitKey(30)
if col_movement < 0: if col_movement < 0:
for i in range(0, col_movement, - 1): for i in range(0, col_movement, - 1):
self.keyboard.press(left) self.keyboard.press(left)
self.keyboard.release(left) self.keyboard.release(left)
print("move left 3 pressed:", left) print("move left 3 pressed:", left)
cv.waitKey(40) cv.waitKey(30)
else: else:
for i in range(0, col_movement, 1): for i in range(0, col_movement, 1):
self.keyboard.press(right) self.keyboard.press(right)
self.keyboard.release(right) self.keyboard.release(right)
print("move right 3 pressed:", right) print("move right 3 pressed:", right)
cv.waitKey(40) cv.waitKey(30)
def point_in_rect(self, point): def point_in_rect(self, point):
for e in range(0, 20, 1): for e in range(0, 20, 1):

View File

@@ -26,9 +26,10 @@ class NewStoneID(threading.Thread):
self.vision_stun = Vision() self.vision_stun = Vision()
self.stone_coordinates = np.zeros((4, 4), dtype=object) self.stone_coordinates = np.zeros((4, 4), dtype=object)
self.data_coordinates = np.zeros((20, 20), dtype=object)
self.fill_data_coordinates() self.fill_data_coordinates()
self.needles = {1: cv.imread("litris/blue_needle.jpg", cv.IMREAD_UNCHANGED)} self.needles = {'Q': cv.imread("litris/blue_needle.jpg", cv.IMREAD_UNCHANGED)}
self.run_mode = 'run' self.run_mode = 'run'
self.actual_letter = "" self.actual_letter = ""
@@ -75,7 +76,7 @@ class NewStoneID(threading.Thread):
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
screenshot = screenshot[580:845, 1148:1412] screenshot = screenshot[580:845, 1148:1412]
rectangles = self.vision_stun.find(screenshot, self.needles[1], 0.85, 16) rectangles = self.vision_stun.find(screenshot, self.needles['Q'], 0.85, 16)
if len(rectangles) == 0: if len(rectangles) == 0:
return None return None
@@ -133,6 +134,50 @@ class NewStoneID(threading.Thread):
return e, i return e, i
return None, None return None, None
def get_current_board_state(self):
# get an updated image of the game
screenshot = self.capture_window.get_screenshot()
#screenshot = cv.imread("litris/main_playfield.jpg")
screenshot = screenshot[40:1380, 610:1950] # 1000,1000
# cv.imshow("screenshot", screenshot)
# cv.waitKey(150)
# continue
#data_coords = np.zeros((20, 20), dtype=object)
data_coords = np.full((20, 20), ' ', dtype=object)
#field = Pickaxe_Field()
for needle_key in self.needles.keys():
#gray_needle = cv.cvtColor(self.needles[needle_key], cv.COLOR_BGR2GRAY)
#thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
rectangles = self.vision_stun.find(screenshot, self.needles[needle_key], 0.8, 200)
if len(rectangles) == 0:
continue
points = self.vision_stun.get_click_points(rectangles)
for point in points:
x, y = self.point_in_rect(point)
if x is not None and y is not None:
data_coords[x][y] = needle_key
#self.change_value(x, y, int(needle_key))
# print(field.data_value_grid)
# cv.circle(screenshot, points[0], 7, (0, 255, 0), -1)
#output_image = self.vision_stun.draw_rectangles(screenshot, rectangles)
#cv.imshow("output_image", output_image)
#cv.waitKey(150)
return data_coords.tolist()
def point_in_rect(self, point):
for e in range(0, 20, 1):
for i in range(0, 20, 1):
x1, y1, w, h = self.data_coordinates[e][i]
x2, y2 = x1 + w, y1 + h
x, y = point
if x1 < x and x < x2:
if y1 < y and y < y2:
return e, i
return None, None
def fill_data_coordinates(self): def fill_data_coordinates(self):
# 610 to 1950 = 1340 - 76 / 20 = 63 # 610 to 1950 = 1340 - 76 / 20 = 63
# 40 to 1380 = 1340 - 76 / 20 = 63 # 40 to 1380 = 1340 - 76 / 20 = 63
@@ -143,3 +188,6 @@ class NewStoneID(threading.Thread):
for e in range(0, 4, 1): for e in range(0, 4, 1):
for i in range(0, 4, 1): for i in range(0, 4, 1):
self.stone_coordinates[e][i] = [(i * dim) + (i * i_spacing), (e * dim) + (e * e_spacing), dim, dim] self.stone_coordinates[e][i] = [(i * dim) + (i * i_spacing), (e * dim) + (e * e_spacing), dim, dim]
for e in range(0, 20, 1):
for i in range(0, 20, 1):
self.data_coordinates[e][i] = [(i * dim) + (i * i_spacing), (e * dim) + (e * e_spacing), dim, dim]

View File

@@ -1,7 +1,10 @@
import cv2 as cv import cv2 as cv
import numpy as np import numpy as np
import pydirectinput import pydirectinput
from nltk.corpus import words
from pytesseract import pytesseract
import utils
from utils import mse from utils import mse
from game_base_class import GameBase from game_base_class import GameBase
import random import random
@@ -18,6 +21,8 @@ class MentiWords(GameBase):
def __init__(self, overlay): def __init__(self, overlay):
super().__init__(overlay) super().__init__(overlay)
pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
self.observation = np.zeros((9, 9), dtype=int) self.observation = np.zeros((9, 9), dtype=int)
self.colors = [1, 2, 3, 4, 5, 6, 7, 8, 9] self.colors = [1, 2, 3, 4, 5, 6, 7, 8, 9]
@@ -27,13 +32,55 @@ class MentiWords(GameBase):
self.menti_play_button = cv.imread("control_elements/play.jpg", cv.IMREAD_COLOR) self.menti_play_button = cv.imread("control_elements/play.jpg", cv.IMREAD_COLOR)
self.needles = {'E': cv.imread("menti_words/e.jpg", cv.IMREAD_COLOR), self.needles = {
'A': cv.imread("menti_words/a.jpg", cv.IMREAD_COLOR),
'B': cv.imread("menti_words/b.jpg", cv.IMREAD_COLOR),
'C': cv.imread("menti_words/c.jpg", cv.IMREAD_COLOR),
'D': cv.imread("menti_words/d.jpg", cv.IMREAD_COLOR),
'E': cv.imread("menti_words/e.jpg", cv.IMREAD_COLOR),
'F': cv.imread("menti_words/f.jpg", cv.IMREAD_COLOR),
'H': cv.imread("menti_words/h.jpg", cv.IMREAD_COLOR), 'H': cv.imread("menti_words/h.jpg", cv.IMREAD_COLOR),
'I': cv.imread("menti_words/i.jpg", cv.IMREAD_COLOR),
'L': cv.imread("menti_words/l.jpg", cv.IMREAD_COLOR),
'M': cv.imread("menti_words/m.jpg", cv.IMREAD_COLOR),
'N': cv.imread("menti_words/n.jpg", cv.IMREAD_COLOR),
'O': cv.imread("menti_words/o.jpg", cv.IMREAD_COLOR), 'O': cv.imread("menti_words/o.jpg", cv.IMREAD_COLOR),
'R': cv.imread("menti_words/r.jpg", cv.IMREAD_COLOR),
'T': cv.imread("menti_words/t.jpg", cv.IMREAD_COLOR),
'P': cv.imread("menti_words/p.jpg", cv.IMREAD_COLOR), 'P': cv.imread("menti_words/p.jpg", cv.IMREAD_COLOR),
'I': cv.imread("menti_words/i.jpg", cv.IMREAD_COLOR)
'R': cv.imread("menti_words/r.jpg", cv.IMREAD_COLOR),
'S': cv.imread("menti_words/s.jpg", cv.IMREAD_COLOR),
'T': cv.imread("menti_words/t.jpg", cv.IMREAD_COLOR),
'U': cv.imread("menti_words/u.jpg", cv.IMREAD_COLOR),
'W': cv.imread("menti_words/w.jpg", cv.IMREAD_COLOR)
}
self.masks = {
'A': cv.imread("menti_words/a-mask.png", cv.IMREAD_COLOR),
'B': cv.imread("menti_words/b-mask.png", cv.IMREAD_COLOR),
'C': cv.imread("menti_words/c-mask.png", cv.IMREAD_COLOR),
'D': cv.imread("menti_words/d-mask.png", cv.IMREAD_COLOR),
'E': cv.imread("menti_words/e-mask.png", cv.IMREAD_COLOR),
'F': cv.imread("menti_words/f-mask.png", cv.IMREAD_COLOR),
'H': cv.imread("menti_words/h-mask.png", cv.IMREAD_COLOR),
'I': cv.imread("menti_words/i-mask.png", cv.IMREAD_COLOR),
'L': cv.imread("menti_words/l-mask.png", cv.IMREAD_COLOR),
'M': cv.imread("menti_words/m-mask.png", cv.IMREAD_COLOR),
'N': cv.imread("menti_words/n-mask.png", cv.IMREAD_COLOR),
'O': cv.imread("menti_words/o-mask.png", cv.IMREAD_COLOR),
'P': cv.imread("menti_words/p-mask.png", cv.IMREAD_COLOR),
'R': cv.imread("menti_words/r-mask.png", cv.IMREAD_COLOR),
'S': cv.imread("menti_words/s-mask.png", cv.IMREAD_COLOR),
'T': cv.imread("menti_words/t-mask.png", cv.IMREAD_COLOR),
'U': cv.imread("menti_words/u-mask.png", cv.IMREAD_COLOR),
'W': cv.imread("menti_words/w-mask.png", cv.IMREAD_COLOR)
} }
self.current_letters = [] self.current_letters = []
@@ -41,6 +88,7 @@ class MentiWords(GameBase):
with open("menti_dic") as file: with open("menti_dic") as file:
self.word_list = [line.rstrip() for line in file] self.word_list = [line.rstrip() for line in file]
#self.word_list2 = words.words()
def reset_lists(self): def reset_lists(self):
self.current_letters = [] self.current_letters = []
@@ -79,7 +127,7 @@ class MentiWords(GameBase):
#screenshot = cv.imread("menti_words/screenshot.jpg") #screenshot = cv.imread("menti_words/screenshot.jpg")
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
screenshot = screenshot[870:1240, 1080:1480] screenshot = utils.scale_screenshot(screenshot[870:1270, 1080:1480], 200, False)
#cv.imshow("screenshot", screenshot) #cv.imshow("screenshot", screenshot)
#cv.waitKey(150) #cv.waitKey(150)
@@ -87,19 +135,35 @@ class MentiWords(GameBase):
for needle_key in self.needles.keys(): for needle_key in self.needles.keys():
# gray_needle = cv.cvtColor(self.needles[needle_key], cv.COLOR_BGR2GRAY) # gray_needle = cv.cvtColor(self.needles[needle_key], cv.COLOR_BGR2GRAY)
# thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1] # thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
rectangles = self.vision_stun.find(screenshot, self.needles[needle_key], 0.85, 56)
thresh_needle = utils.scale_screenshot(self.needles[needle_key], 200, False)
rectangles = self.vision_stun.find(screenshot, thresh_needle , 0.85, 2)
#rectangles = self.vision_stun.find(screenshot, self.needles[needle_key], 0.95, 1 ,True, self.masks[needle_key])
if len(rectangles) == 0: if len(rectangles) == 0:
continue continue
points = self.vision_stun.get_click_points(rectangles) points = self.vision_stun.get_click_points(rectangles)
for point in points:
self.current_letters.append(needle_key) self.current_letters.append(needle_key)
self.letter_coords[needle_key] = points[0] self.letter_coords[needle_key] = (int(point[0]/2), int(point[1]/2))
'''
cropped1 = self.vision_stun.draw_display_picture(screenshot, rectangles, 10)
#cropped1 = utils.scale_screenshot(cropped1)
cv.imshow("cropped1", cropped1)
cv.waitKey(150)
text_1 = pytesseract.image_to_string(cropped1, lang='eng', config='--psm 6').strip()
if str.isalpha(text_1):
#cv.imshow("cropped1", cropped1)
#cv.waitKey(150)
points = self.vision_stun.get_click_points(rectangles)
self.current_letters.append(text_1)
self.letter_coords[text_1] = points[0]'''
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused': if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return return
def possible_words(self, lwords, charSet): def possible_words(self, lwords, charSet):
lst = [] lst = []
for word in lwords: for word in lwords:
if len(word) <= 2: if len(word) <= 1:
continue continue
flag = 1 flag = 1
chars = self.charCount(word) chars = self.charCount(word)

BIN
menti_words/a-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

BIN
menti_words/a.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
menti_words/a.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
menti_words/b-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

BIN
menti_words/b.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
menti_words/b.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
menti_words/c-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
menti_words/c.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
menti_words/c.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
menti_words/d-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

BIN
menti_words/d.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
menti_words/d.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
menti_words/e-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

BIN
menti_words/e.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
menti_words/f-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

BIN
menti_words/f.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
menti_words/f.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
menti_words/h-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

BIN
menti_words/h.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
menti_words/i-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 966 B

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
menti_words/i.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 782 B

BIN
menti_words/l-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

BIN
menti_words/l.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
menti_words/l.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
menti_words/m-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B

BIN
menti_words/m.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
menti_words/m.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
menti_words/n-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

BIN
menti_words/n.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
menti_words/n.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
menti_words/o-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
menti_words/o.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
menti_words/p-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
menti_words/p.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
menti_words/r-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

BIN
menti_words/r.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
menti_words/s-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

BIN
menti_words/s.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
menti_words/s.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
menti_words/t-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

BIN
menti_words/t.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
menti_words/u-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

BIN
menti_words/u.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
menti_words/u.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
menti_words/w-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

BIN
menti_words/w.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
menti_words/w.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -61,18 +61,20 @@ def check_for_bl_line(line_item, black_list):
return False return False
def scale_screenshot(screenshot): def scale_screenshot(screenshot, percent = 200, thresh_mode = True):
scale_percent = 200 # percent of original size scale_percent = percent # percent of original size
width = int(screenshot.shape[1] * scale_percent / 100) width = int(screenshot.shape[1] * scale_percent / 100)
height = int(screenshot.shape[0] * scale_percent / 100) height = int(screenshot.shape[0] * scale_percent / 100)
dim = (width, height) dim = (width, height)
resized_img = cv.resize(screenshot, dim, interpolation=4) resized_img = cv.resize(screenshot, dim, interpolation=4)
if thresh_mode:
gray = cv.cvtColor(resized_img, cv.COLOR_BGR2GRAY) gray = cv.cvtColor(resized_img, cv.COLOR_BGR2GRAY)
thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1] thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
return thresh
# cv.imshow("Tresh", thresh) # cv.imshow("Tresh", thresh)
# cv.waitKey(1000) # cv.waitKey(1000)
return thresh return resized_img
def save_line_item_npy_jpg(short_pic_list): def save_line_item_npy_jpg(short_pic_list):

View File

@@ -158,10 +158,11 @@ class Vision:
if mask is not None: if mask is not None:
result = cv.matchTemplate(haystack_img, needle_img, cv.TM_CCORR_NORMED, None, mask) result = cv.matchTemplate(haystack_img, needle_img, cv.TM_CCORR_NORMED, None, mask)
_minVal, _maxVal, minLoc, maxLoc = cv.minMaxLoc(result, None)
else: else:
result = cv.matchTemplate(haystack_img, needle_img, self.method) result = cv.matchTemplate(haystack_img, needle_img, self.method)
_minVal, _maxVal, minLoc, maxLoc = cv.minMaxLoc(result, None)
if normalize: if normalize:
cv.normalize(result, result, 0, 1, cv.NORM_MINMAX, -1) cv.normalize(result, result, 0, 1, cv.NORM_MINMAX, -1)
# Get the all the positions from the match result that exceed our threshold # Get the all the positions from the match result that exceed our threshold
@@ -246,11 +247,11 @@ class Vision:
return haystack_img return haystack_img
def draw_display_picture(self, haystack_img, rectangles): def draw_display_picture(self, haystack_img, rectangles, border = 0):
pic = None pic = None
for (x, y, w, h) in rectangles: for (x, y, w, h) in rectangles:
pic = haystack_img[y:y + h, x:x + w] pic = haystack_img[y-border:y + h +border, x-border:x + w + border]
# scale_percent = 500 # percent of original size # scale_percent = 500 # percent of original size
# width = int(pic.shape[1] * scale_percent / 100) # width = int(pic.shape[1] * scale_percent / 100)