|
|
|
@@ -1,3 +1,4 @@
|
|
|
|
|
|
|
|
import json
|
|
|
|
import time
|
|
|
|
import time
|
|
|
|
from pathlib import Path
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
|
|
@@ -8,6 +9,8 @@ from loguru import logger
|
|
|
|
from .waytools import capActiveWindow, focusWindow, moveMouse
|
|
|
|
from .waytools import capActiveWindow, focusWindow, moveMouse
|
|
|
|
from .waytools import sendKey as _sendKey
|
|
|
|
from .waytools import sendKey as _sendKey
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: Consider type hinting images from cv2.typing import MatLike
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DFWINDOW:
|
|
|
|
class DFWINDOW:
|
|
|
|
class TOOLS:
|
|
|
|
class TOOLS:
|
|
|
|
@@ -29,24 +32,24 @@ class DFWINDOW:
|
|
|
|
) -> tuple[int, int]:
|
|
|
|
) -> tuple[int, int]:
|
|
|
|
# Check the first (num_rows) rows at the top of the image,
|
|
|
|
# Check the first (num_rows) rows at the top of the image,
|
|
|
|
# ignoring (ignore_cols) number of pixels at each end of teh line.
|
|
|
|
# ignoring (ignore_cols) number of pixels at each end of teh line.
|
|
|
|
test_mean = np.mean(
|
|
|
|
test_max = np.max(
|
|
|
|
cv2.cvtColor(image_in[0:num_rows, ignore_cols:-ignore_cols], cv2.COLOR_BGR2GRAY),
|
|
|
|
cv2.cvtColor(image_in[0:num_rows, ignore_cols:-ignore_cols], cv2.COLOR_BGR2GRAY),
|
|
|
|
axis=1, # get the mean along the x-axis
|
|
|
|
axis=1, # get the mean along the x-axis
|
|
|
|
)
|
|
|
|
)
|
|
|
|
# TODO: handle when 0 results return
|
|
|
|
# TODO: handle when 0 results return
|
|
|
|
# Test the mean darkness, get the first row darker than 4
|
|
|
|
# Test the mean darkness, get the first row darker than 4
|
|
|
|
content_y = np.where(test_mean < mean_threshold)[0][0]
|
|
|
|
content_y = np.where(test_max < mean_threshold)[0][0]
|
|
|
|
|
|
|
|
|
|
|
|
_ignore_rows = max(ignore_rows, content_y + 1)
|
|
|
|
_ignore_rows = max(ignore_rows, content_y + 1)
|
|
|
|
test_mean = np.mean(
|
|
|
|
test_max = np.max(
|
|
|
|
cv2.cvtColor(image_in[_ignore_rows:-_ignore_rows, 0:num_cols], cv2.COLOR_BGR2GRAY),
|
|
|
|
cv2.cvtColor(image_in[_ignore_rows:-_ignore_rows, 0:num_cols], cv2.COLOR_BGR2GRAY),
|
|
|
|
axis=0, # get the mean along the y-axis
|
|
|
|
axis=0, # get the mean along the y-axis
|
|
|
|
)
|
|
|
|
)
|
|
|
|
content_x = np.where(test_mean < mean_threshold)[0][0]
|
|
|
|
content_x = np.where(test_max < mean_threshold)[0][0]
|
|
|
|
|
|
|
|
|
|
|
|
logger.debug(f"Content origin ({content_x}, {content_y})")
|
|
|
|
logger.debug(f"Content origin ({content_x}, {content_y})")
|
|
|
|
|
|
|
|
|
|
|
|
return (content_x, content_y)
|
|
|
|
return (int(content_x), int(content_y))
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
@staticmethod
|
|
|
|
def isRightBorder(img, num_columns=20, border_threshold: int = 10) -> bool:
|
|
|
|
def isRightBorder(img, num_columns=20, border_threshold: int = 10) -> bool:
|
|
|
|
@@ -58,6 +61,20 @@ class DFWINDOW:
|
|
|
|
# Are all pixels in the strip "black"
|
|
|
|
# Are all pixels in the strip "black"
|
|
|
|
return not np.any(thresh)
|
|
|
|
return not np.any(thresh)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
|
|
|
def getImageDiff(image1, image2, conversion=cv2.COLOR_BGR2GRAY) -> float:
|
|
|
|
|
|
|
|
# Diff size, very dif img
|
|
|
|
|
|
|
|
if image1.shape != image2.shape:
|
|
|
|
|
|
|
|
return float("inf")
|
|
|
|
|
|
|
|
grey1 = cv2.cvtColor(image1, conversion)
|
|
|
|
|
|
|
|
grey2 = cv2.cvtColor(image2, conversion)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Apparently this is the Mean Squared Error (MES). Thanks Gemini (LLM)
|
|
|
|
|
|
|
|
err = np.sum((grey1.astype("float") - grey2.astype("float")) ** 2)
|
|
|
|
|
|
|
|
err /= float(grey1.shape[0] * grey1.shape[0])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return float(err)
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
@staticmethod
|
|
|
|
def isLeftBorder(img, num_columns=20, border_threshold: int = 10) -> bool:
|
|
|
|
def isLeftBorder(img, num_columns=20, border_threshold: int = 10) -> bool:
|
|
|
|
# grab a greyscale strip to look at
|
|
|
|
# grab a greyscale strip to look at
|
|
|
|
@@ -89,20 +106,30 @@ class DFWINDOW:
|
|
|
|
return not np.any(thresh)
|
|
|
|
return not np.any(thresh)
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
@staticmethod
|
|
|
|
def firstNotBlackX(img):
|
|
|
|
def firstNotBlackX(img) -> int:
|
|
|
|
first_x = np.where(np.mean(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), axis=0) > 15)[0][0]
|
|
|
|
first_x = np.where(np.max(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), axis=0) > 5)[0][0]
|
|
|
|
return first_x
|
|
|
|
return int(first_x)
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
@staticmethod
|
|
|
|
def firstNotBlackY(img):
|
|
|
|
def lastNotBlackX(img) -> int:
|
|
|
|
first_y = np.where(np.mean(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), axis=1) > 15)[0][0]
|
|
|
|
first_x = np.where(np.max(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), axis=0) > 5)[0][-1]
|
|
|
|
return first_y
|
|
|
|
return int(first_x)
|
|
|
|
|
|
|
|
|
|
|
|
bottom_to_ignore = 120
|
|
|
|
@staticmethod
|
|
|
|
sleep_after_mouse = 0.2
|
|
|
|
def firstNotBlackY(img) -> int:
|
|
|
|
sleep_after_key = 0.08
|
|
|
|
first_y = np.where(np.max(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), axis=1) > 5)[0][0]
|
|
|
|
sleep_after_focus = 0.3
|
|
|
|
return int(first_y)
|
|
|
|
sleep_after_panning = 0.3
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
|
|
|
def lastNotBlackY(img) -> int:
|
|
|
|
|
|
|
|
first_y = np.where(np.max(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), axis=1) > 5)[0][-1]
|
|
|
|
|
|
|
|
return int(first_y)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bottom_to_ignore = 160
|
|
|
|
|
|
|
|
sleep_after_mouse = 0.2 # 2
|
|
|
|
|
|
|
|
sleep_after_key = 0.08 # 08
|
|
|
|
|
|
|
|
sleep_after_focus = 0.2 # 3
|
|
|
|
|
|
|
|
sleep_after_panning = 0.2 # 3
|
|
|
|
query_for_window = "dwarfort"
|
|
|
|
query_for_window = "dwarfort"
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self) -> None:
|
|
|
|
def __init__(self) -> None:
|
|
|
|
@@ -220,12 +247,26 @@ class DFWINDOW:
|
|
|
|
time.sleep(self.sleep_after_mouse)
|
|
|
|
time.sleep(self.sleep_after_mouse)
|
|
|
|
self.focusWindow()
|
|
|
|
self.focusWindow()
|
|
|
|
time.sleep(self.sleep_after_focus)
|
|
|
|
time.sleep(self.sleep_after_focus)
|
|
|
|
self.sendKeys("w", 30)
|
|
|
|
|
|
|
|
self.sendKeys("a", 30)
|
|
|
|
# Improved seeking upper left
|
|
|
|
|
|
|
|
self.sendKeys("w", 8)
|
|
|
|
|
|
|
|
img = self.capContent()
|
|
|
|
|
|
|
|
while not self.TOOLS.isTopBorder(img):
|
|
|
|
|
|
|
|
self.sendKeys("w", 4)
|
|
|
|
|
|
|
|
img = self.capContent()
|
|
|
|
|
|
|
|
self.sendKeys("w", 4)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.sendKeys("a", 8)
|
|
|
|
|
|
|
|
img = self.capContent()
|
|
|
|
|
|
|
|
while not self.TOOLS.isLeftBorder(img):
|
|
|
|
|
|
|
|
self.sendKeys("a", 4)
|
|
|
|
|
|
|
|
img = self.capContent()
|
|
|
|
|
|
|
|
self.sendKeys("a", 4)
|
|
|
|
|
|
|
|
|
|
|
|
img = self.capWindow()
|
|
|
|
img = self.capWindow()
|
|
|
|
self._content_left, self._content_top = self.TOOLS.find_content_origin(img)
|
|
|
|
self._content_left, self._content_top = self.TOOLS.find_content_origin(img)
|
|
|
|
self._content_right = img.shape[1] - self._content_left
|
|
|
|
self._content_right = int(img.shape[1] - self._content_left)
|
|
|
|
self._content_bottom = img.shape[0] - self.bottom_to_ignore
|
|
|
|
self._content_bottom = int(img.shape[0] - self.bottom_to_ignore)
|
|
|
|
img = img[self._content_top : self._content_bottom, self._content_left : self._content_right] # pyright: ignore[reportOptionalSubscript]
|
|
|
|
img = img[self._content_top : self._content_bottom, self._content_left : self._content_right] # pyright: ignore[reportOptionalSubscript]
|
|
|
|
logger.debug(f"Content width {self.contentWidth}. Content height {self.contentHeight}.")
|
|
|
|
logger.debug(f"Content width {self.contentWidth}. Content height {self.contentHeight}.")
|
|
|
|
|
|
|
|
|
|
|
|
@@ -239,8 +280,8 @@ class DFWINDOW:
|
|
|
|
img = self.capContent()
|
|
|
|
img = self.capContent()
|
|
|
|
mx2 = self.TOOLS.firstNotBlackX(img)
|
|
|
|
mx2 = self.TOOLS.firstNotBlackX(img)
|
|
|
|
my2 = self.TOOLS.firstNotBlackY(img)
|
|
|
|
my2 = self.TOOLS.firstNotBlackY(img)
|
|
|
|
self._step_size_x = mx2 - mx1
|
|
|
|
self._step_size_x = mx1 - mx2
|
|
|
|
self._step_size_y = my2 - my1
|
|
|
|
self._step_size_y = my1 - my2
|
|
|
|
logger.info(f"Step sizes calculated: x={self._step_size_x} and y={self._step_size_y}")
|
|
|
|
logger.info(f"Step sizes calculated: x={self._step_size_x} and y={self._step_size_y}")
|
|
|
|
self.sendKeys("w")
|
|
|
|
self.sendKeys("w")
|
|
|
|
self.sendKeys("a")
|
|
|
|
self.sendKeys("a")
|
|
|
|
@@ -303,13 +344,6 @@ class DFWINDOW:
|
|
|
|
self._gridx = steps_right
|
|
|
|
self._gridx = steps_right
|
|
|
|
self._gridy = steps_down
|
|
|
|
self._gridy = steps_down
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: Use seek tests to calculate mapsize in pixels
|
|
|
|
|
|
|
|
# at (0,0) save left_edge_offset and top_edge_offset
|
|
|
|
|
|
|
|
# at (max,max) save right_edge_offset and bottom_edge_offset
|
|
|
|
|
|
|
|
# width = (contentWidth - l_e_o) + (gridyx_max * _step_size_x) - abs(r_e_o)
|
|
|
|
|
|
|
|
# | <==|====|====|==> |
|
|
|
|
|
|
|
|
# (max*size) is too far, so we subract the ofset/border from the right map edge
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Test going to 0,0
|
|
|
|
# Test going to 0,0
|
|
|
|
self.setGridPos(0, 0)
|
|
|
|
self.setGridPos(0, 0)
|
|
|
|
time.sleep(self.sleep_after_panning)
|
|
|
|
time.sleep(self.sleep_after_panning)
|
|
|
|
@@ -318,6 +352,9 @@ class DFWINDOW:
|
|
|
|
logger.debug("Calibration error. Not at requested upper left of map")
|
|
|
|
logger.debug("Calibration error. Not at requested upper left of map")
|
|
|
|
raise Exception("Calibration error. Not at requested upper left of map")
|
|
|
|
raise Exception("Calibration error. Not at requested upper left of map")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cal_left_border = self.TOOLS.firstNotBlackX(img)
|
|
|
|
|
|
|
|
cal_top_border = self.TOOLS.firstNotBlackY(img)
|
|
|
|
|
|
|
|
|
|
|
|
# Test going to (max,max)
|
|
|
|
# Test going to (max,max)
|
|
|
|
self.setGridPos(self.maxGridX, self.maxGridY)
|
|
|
|
self.setGridPos(self.maxGridX, self.maxGridY)
|
|
|
|
time.sleep(self.sleep_after_panning)
|
|
|
|
time.sleep(self.sleep_after_panning)
|
|
|
|
@@ -326,31 +363,112 @@ class DFWINDOW:
|
|
|
|
logger.debug("Calibration error. Not at requested lower right of map")
|
|
|
|
logger.debug("Calibration error. Not at requested lower right of map")
|
|
|
|
raise Exception("Calibration error. Not at requested lower right of map")
|
|
|
|
raise Exception("Calibration error. Not at requested lower right of map")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cal_right_border = self.TOOLS.lastNotBlackX(img)
|
|
|
|
|
|
|
|
cal_bottom_border = self.TOOLS.lastNotBlackY(img)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: Use seek tests to calculate mapsize in pixels
|
|
|
|
|
|
|
|
# at (0,0) save left_edge_offset and top_edge_offset
|
|
|
|
|
|
|
|
# at (max,max) save right_edge_offset and bottom_edge_offset
|
|
|
|
|
|
|
|
# width = (contentWidth - l_e_o) + (gridyx_max * _step_size_x) - abs(r_e_o)
|
|
|
|
|
|
|
|
# | <==|====|====|==> |
|
|
|
|
|
|
|
|
# (max*size) is too far, so we subract the ofset/border from the right map edge
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self._map_width = (
|
|
|
|
|
|
|
|
(img.shape[1] - cal_left_border) # Grid x = 0
|
|
|
|
|
|
|
|
+ ((self._gridx_max - 1) * self._step_size_x) # All the middle
|
|
|
|
|
|
|
|
+ cal_right_border # grid x = max
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self._map_height = (
|
|
|
|
|
|
|
|
(img.shape[0] - cal_top_border) # Grid x = 0
|
|
|
|
|
|
|
|
+ ((self._gridy_max - 1) * self._step_size_y) # All the middle
|
|
|
|
|
|
|
|
+ cal_bottom_border # grid x = max
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.setGridPos(0, 0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logger.debug(f"Map dimensions calculated as {self._map_width} x {self._map_height}")
|
|
|
|
|
|
|
|
|
|
|
|
logger.info(
|
|
|
|
logger.info(
|
|
|
|
f"Grid calibration complete. Grid steps ({self._gridy_max + 1},{self._gridy_max + 1}), step sizes({self._step_size_x},{self._step_size_y})"
|
|
|
|
f"Grid calibration complete. Grid steps ({self._gridy_max + 1},{self._gridy_max + 1}), step sizes({self._step_size_x},{self._step_size_y})"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test1(self):
|
|
|
|
|
|
|
|
# rawimg = cv2.imread("./test_img.png")
|
|
|
|
|
|
|
|
# rawimg = cv2.imread("grid_base_3.png")
|
|
|
|
|
|
|
|
# img = rawimg[100 : -self.bottom_to_ignore - 70, 65:-65]
|
|
|
|
|
|
|
|
# tlb = self.TOOLS.firstNotBlackX(img)
|
|
|
|
|
|
|
|
# ttb = self.TOOLS.firstNotBlackY(img)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# tt_setup = (
|
|
|
|
|
|
|
|
# r"gc.enable() ; import cv2 ; import numpy as np ; timg = cv2.imread('./test_img.png', cv2.IMREAD_UNCHANGED)"
|
|
|
|
|
|
|
|
# )
|
|
|
|
|
|
|
|
# tt1 = timeit.Timer(
|
|
|
|
|
|
|
|
# "np.where(np.mean(cv2.cvtColor(timg, cv2.COLOR_BGR2GRAY), axis=0) > 15)[0][0]",
|
|
|
|
|
|
|
|
# setup=tt_setup,
|
|
|
|
|
|
|
|
# )
|
|
|
|
|
|
|
|
# tt2 = timeit.Timer(
|
|
|
|
|
|
|
|
# "np.where(np.max(cv2.cvtColor(timg, cv2.COLOR_BGR2GRAY), axis=0) > 25)[0][0]",
|
|
|
|
|
|
|
|
# setup=tt_setup,
|
|
|
|
|
|
|
|
# )
|
|
|
|
|
|
|
|
# tt3 = timeit.Timer(
|
|
|
|
|
|
|
|
# "np.where(np.max(cv2.cvtColor(timg, cv2.COLOR_BGRA2GRAY), axis=0) > 25)[0][0]",
|
|
|
|
|
|
|
|
# setup=tt_setup,
|
|
|
|
|
|
|
|
# )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# num_tests = 80
|
|
|
|
|
|
|
|
# r1 = tt1.timeit(number=num_tests)
|
|
|
|
|
|
|
|
# r2 = tt2.timeit(number=num_tests)
|
|
|
|
|
|
|
|
# r3 = tt3.timeit(number=num_tests)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logger.debug("Pause here for testing")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_saveGrids(self):
|
|
|
|
|
|
|
|
savedir = Path()
|
|
|
|
|
|
|
|
savefile_base = "cached_grid"
|
|
|
|
|
|
|
|
savefile_ext = "png"
|
|
|
|
|
|
|
|
for x in range(0, self._gridx_max + 1):
|
|
|
|
|
|
|
|
for y in range(0, self._gridy_max):
|
|
|
|
|
|
|
|
self.setGridPos(x, y)
|
|
|
|
|
|
|
|
time.sleep(self.sleep_after_panning)
|
|
|
|
|
|
|
|
img = self.capContent()
|
|
|
|
|
|
|
|
savefilename = savedir.joinpath(f"{savefile_base}_{x}_{y}.{savefile_ext}")
|
|
|
|
|
|
|
|
cv2.imwrite(str(savefilename.resolve()), img)
|
|
|
|
|
|
|
|
calib_info = {
|
|
|
|
|
|
|
|
"gridx": int(self._gridx),
|
|
|
|
|
|
|
|
"gridy": int(self._gridy),
|
|
|
|
|
|
|
|
"gridx_max": int(self._gridx_max),
|
|
|
|
|
|
|
|
"gridy_max": int(self._gridy_max),
|
|
|
|
|
|
|
|
"step_size_x": int(self._step_size_x),
|
|
|
|
|
|
|
|
"step_size_y": int(self._step_size_y),
|
|
|
|
|
|
|
|
"content_top": int(self._content_top),
|
|
|
|
|
|
|
|
"content_bottom": int(self._content_bottom),
|
|
|
|
|
|
|
|
"content_left": int(self._content_left),
|
|
|
|
|
|
|
|
"content_right": int(self._content_right),
|
|
|
|
|
|
|
|
"map_height": int(self._map_height),
|
|
|
|
|
|
|
|
"map_width": int(self._map_width),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
with open("./calib_info.json", "w") as fh:
|
|
|
|
|
|
|
|
json.dump(calib_info, fh)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_loadCalib(self):
|
|
|
|
|
|
|
|
with open("./calib_info.json") as fh:
|
|
|
|
|
|
|
|
calib_info = json.load(fh)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self._gridx = calib_info["gridx"]
|
|
|
|
|
|
|
|
self._gridy = calib_info["gridy"]
|
|
|
|
|
|
|
|
self._gridx_max = calib_info["gridx_max"]
|
|
|
|
|
|
|
|
self._gridy_max = calib_info["gridy_max"]
|
|
|
|
|
|
|
|
self._step_size_x = calib_info["step_size_x"]
|
|
|
|
|
|
|
|
self._step_size_y = calib_info["step_size_y"]
|
|
|
|
|
|
|
|
self._content_top = calib_info["content_top"]
|
|
|
|
|
|
|
|
self._content_bottom = calib_info["content_bottom"]
|
|
|
|
|
|
|
|
self._content_left = calib_info["content_left"]
|
|
|
|
|
|
|
|
self._content_right = calib_info["content_right"]
|
|
|
|
|
|
|
|
self._map_height = calib_info["map_height"]
|
|
|
|
|
|
|
|
self._map_width = calib_info["map_width"]
|
|
|
|
|
|
|
|
|
|
|
|
def getPanoramaMap(self):
|
|
|
|
def getPanoramaMap(self):
|
|
|
|
self.calibrateGrid()
|
|
|
|
self.calibrateGrid()
|
|
|
|
|
|
|
|
|
|
|
|
# Test getting pieces and stitching
|
|
|
|
|
|
|
|
stitcher = cv2.Stitcher.create(cv2.STITCHER_SCANS)
|
|
|
|
|
|
|
|
stitcher.setPanoConfidenceThresh(0.1) # Dont be confident
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
imgs_in_row = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get a row
|
|
|
|
|
|
|
|
self.setGridPos(0, 0)
|
|
|
|
|
|
|
|
time.sleep(self.sleep_after_panning)
|
|
|
|
|
|
|
|
for x in range(0, self.maxGridX + 1, 3):
|
|
|
|
|
|
|
|
self.setGridPos(x, self.curGridY)
|
|
|
|
|
|
|
|
time.sleep(self.sleep_after_panning)
|
|
|
|
|
|
|
|
img = self.capContent()
|
|
|
|
|
|
|
|
if img.shape[2] == 4:
|
|
|
|
|
|
|
|
img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
|
|
|
|
|
|
|
|
imgs_in_row.append(img)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status, strip = stitcher.stitch(imgs_in_row)
|
|
|
|
|
|
|
|
logger.debug(f"{len(imgs_in_row)} images. {status=} {strip=} {status == cv2.Stitcher_OK}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return None
|
|
|
|
return None
|
|
|
|
|