refactor(core): 重构分辨率获取逻辑
This commit is contained in:
parent
18ac6af3f4
commit
25b5ff897d
|
@ -151,7 +151,7 @@ def cropped(
|
|||
def _screenshot_hook(img: MatLike) -> MatLike:
|
||||
return crop(img, x1, y1, x2, y2)
|
||||
def _click_hook(x: int, y: int) -> tuple[int, int]:
|
||||
h, w = device.screen_size # 竖屏下宽高反转
|
||||
w, h = device.screen_size
|
||||
x_px = int(x1 * w + x)
|
||||
y_px = int(y1 * h + y)
|
||||
return x_px, y_px
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import logging
|
||||
from typing import Callable, cast
|
||||
from typing_extensions import override
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
@ -18,9 +19,11 @@ class AdbDevice(DeviceABC):
|
|||
super().__init__()
|
||||
self.device = device
|
||||
|
||||
@override
|
||||
def launch_app(self, package_name: str) -> None:
|
||||
self.device.shell(f"monkey -p {package_name} 1")
|
||||
|
||||
@override
|
||||
def click(self, arg1=None, arg2=None) -> None:
|
||||
if arg1 is None:
|
||||
self.__click_last()
|
||||
|
@ -55,11 +58,13 @@ class AdbDevice(DeviceABC):
|
|||
def __click_clickable(self, clickable: ClickableObjectProtocol) -> None:
|
||||
self.click(clickable.rect)
|
||||
|
||||
@override
|
||||
def swipe(self, x1: int, y1: int, x2: int, y2: int, duration: float|None = None) -> None:
|
||||
if duration is not None:
|
||||
logger.warning("Swipe duration is not supported with AdbDevice. Ignoring duration.")
|
||||
self.device.shell(f"input touchscreen swipe {x1} {y1} {x2} {y2}")
|
||||
|
||||
@override
|
||||
def screenshot(self) -> MatLike:
|
||||
if self.screenshot_hook_before is not None:
|
||||
logger.debug("execute screenshot hook before")
|
||||
|
@ -72,6 +77,7 @@ class AdbDevice(DeviceABC):
|
|||
img = self.screenshot_hook_after(img)
|
||||
return img
|
||||
|
||||
@override
|
||||
def screenshot_raw(self) -> MatLike:
|
||||
return cv2.cvtColor(np.array(self.device.screenshot()), cv2.COLOR_RGB2BGR)
|
||||
|
||||
|
@ -79,19 +85,31 @@ class AdbDevice(DeviceABC):
|
|||
def screen_size(self) -> tuple[int, int]:
|
||||
ret = cast(str, self.device.shell("wm size")).strip('Physical size: ')
|
||||
spiltted = tuple(map(int, ret.split("x")))
|
||||
spiltted = tuple(sorted(spiltted, reverse=True))
|
||||
landscape = self.orientation == 'landscape'
|
||||
spiltted = tuple(sorted(spiltted, reverse=landscape))
|
||||
if len(spiltted) != 2:
|
||||
raise ValueError(f"Invalid screen size: {ret}")
|
||||
return spiltted
|
||||
|
||||
|
||||
@staticmethod
|
||||
def list_devices() -> list[str]:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@override
|
||||
def start_app(self, package_name: str) -> None:
|
||||
self.device.shell(f"monkey -p {package_name} 1")
|
||||
|
||||
@override
|
||||
def detect_orientation(self):
|
||||
# 判断方向:https://stackoverflow.com/questions/10040624/check-if-device-is-landscape-via-adb
|
||||
# 但是上面这种方法不准确
|
||||
# 因此这里直接通过截图判断方向
|
||||
img = self.screenshot()
|
||||
if img.shape[0] > img.shape[1]:
|
||||
return 'portrait'
|
||||
return 'landscape'
|
||||
|
||||
@override
|
||||
def current_package(self) -> str:
|
||||
raise NotImplementedError
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from time import sleep
|
||||
from typing import Callable, Protocol, TYPE_CHECKING, overload, runtime_checkable
|
||||
from typing import Callable, Protocol, TYPE_CHECKING, overload, runtime_checkable, Literal
|
||||
from abc import ABC
|
||||
|
||||
from cv2.typing import MatLike
|
||||
|
@ -74,6 +74,12 @@ class DeviceABC(ABC):
|
|||
"""点击前调用的函数。返回修改后的点击坐标。"""
|
||||
self.last_find: Rect | ClickableObjectProtocol | None = None
|
||||
"""上次 image 对象或 ocr 对象的寻找结果"""
|
||||
self.orientation: Literal['portrait', 'landscape'] = 'portrait'
|
||||
"""
|
||||
设备当前方向。默认为竖屏。
|
||||
|
||||
横屏时为 'landscape',竖屏时为 'portrait'。
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def list_devices() -> list[str]:
|
||||
|
@ -121,7 +127,11 @@ class DeviceABC(ABC):
|
|||
|
||||
def click_center(self) -> None:
|
||||
"""
|
||||
点击屏幕中心
|
||||
点击屏幕中心。
|
||||
|
||||
此方法会受到 `self.orientation` 的影响。
|
||||
调用前确保 `orientation` 属性与设备方向一致,
|
||||
否则点击位置会不正确。
|
||||
"""
|
||||
x, y = self.screen_size[0] // 2, self.screen_size[1] // 2
|
||||
self.click(x, y)
|
||||
|
@ -214,10 +224,13 @@ class DeviceABC(ABC):
|
|||
"""
|
||||
屏幕尺寸。格式为 `(width, height)`。
|
||||
|
||||
**注意**: `width` 总为分辨率中较长的那一边,
|
||||
并不会随横竖屏变化,即此属性返回的总是
|
||||
横屏下的分辨率。如果当前设备 APP 为竖屏运行,
|
||||
需要反转元组顺序。
|
||||
**注意**: 此属性返回的分辨率会随设备方向变化。
|
||||
如果 `self.orientation` 为 `landscape`,则返回的分辨率是横屏下的分辨率,
|
||||
否则返回竖屏下的分辨率。
|
||||
|
||||
`self.orientation` 属性默认为竖屏。如果需要自动检测,
|
||||
调用 `self.detect_orientation()` 方法。
|
||||
如果已知方向,也可以直接设置 `self.orientation` 属性。
|
||||
"""
|
||||
...
|
||||
|
||||
|
@ -227,6 +240,14 @@ class DeviceABC(ABC):
|
|||
"""
|
||||
...
|
||||
|
||||
def detect_orientation(self) -> Literal['portrait', 'landscape'] | None:
|
||||
"""
|
||||
检测当前设备方向并设置 `self.orientation` 属性。
|
||||
|
||||
:return: 检测到的方向,如果无法检测到则返回 None。
|
||||
"""
|
||||
...
|
||||
|
||||
def start_app(self, package_name: str) -> None:
|
||||
"""
|
||||
启动某个 APP
|
||||
|
|
Loading…
Reference in New Issue