from PIL import Image from datetime import datetime from urllib.parse import parse_qs, urlparse, unquote import constants import cv2 import numpy as np import re def cv2_to_pil(cv_image: np.ndarray) -> Image.Image: """ cv2.MatLike (BGR/RGB/Grayscale) → PIL.Image """ if len(cv_image.shape) == 3 and cv_image.shape[2] == 3: cv_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB) return Image.fromarray(cv_image) def image_to_numpy(self, image: Image.Image) -> np.ndarray: """Конвертирует PIL Image в numpy array для OpenCV""" return np.array(image) def get_normals(H: np.ndarray, R: np.ndarray, T: np.ndarray) -> np.ndarray: n = cv2.decomposeHomographyMat(H, constants.K, R, T) return n def estimate_transformation_matrix(src_pts: np.ndarray, dst_pts: np.ndarray) -> tuple[np.ndarray, np.ndarray]: """Оценивает матрицу трансформации на основе сопоставленных точек""" # Используем RANSAC для оценки матрицы гомографии return cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 3.0, maxIters=1000) def calc_camera_matrix(w: float, h: float): f = constants._K_FOCUS_DISTANCE return np.array([ [f, 0, w / 2], [0, f, h / 2], [0, 0, 1] ]) def generate_folder_name(): """ Генерирует название для папки с текущей датой и временем до секунд. Формат: YYYY-MM-DD_HH-MM-SS """ now = datetime.now() folder_name = now.strftime("%Y-%m-%d_%H-%M-%S") return folder_name def parse_yandex_maps_url(url): """ Парсит URL Яндекс.Карт и извлекает lat, lon и zoom Формат: ?ll=lon,lat&z=zoom """ # Декодируем URL (на случай %2C вместо запятых) url = unquote(url) # Парсим URL parsed_url = urlparse(url) params = parse_qs(parsed_url.query) if 'll' in params and 'z' in params: # ll содержит "lon,lat" ll_value = params['ll'][0] lat, lon = map(float, ll_value.split(',')) zoom = int(params['z'][0]) return { 'lat': lat, 'lon': lon, 'zoom': zoom } return None def parse_google_maps_url(url): """ Парсит URL Google Maps и извлекает lat, lon и zoom Формат: /@lat,lon,zoom[m|z] """ pattern = r'/@([-\d.]+),([-\d.]+),(\d+)([mz])' match = re.search(pattern, url) if match: lon = float(match.group(1)) lat = float(match.group(2)) zoom_value = int(match.group(3)) zoom_unit = match.group(4) return { 'lat': lat, 'lon': lon, 'zoom': zoom_value, 'zoom_unit': zoom_unit } return None def google_map_js_move_script(dx, dy) -> str: return """ async function sleep(ms) { return new Promise((resolve, reject) => { setTimeout(() => resolve(), ms); }); } async function simulateDrag(element, offsetX, offsetY) { const rect = element.getBoundingClientRect(); const startX = rect.left + rect.width / 2; const startY = rect.top + rect.height / 2; const step = 10 const endX = startX + offsetX + step; const endY = startY + offsetY + step; element.dispatchEvent(new MouseEvent('mousedown', { view: window, bubbles: true, cancelable: true, clientX: startX, clientY: startY, button: 0 })); let currentX = startX; let currentY = startY; function move(stepX, stepY) { currentX += stepX; currentY += stepY; document.dispatchEvent(new MouseEvent('mousemove', { view: window, bubbles: true, cancelable: false, clientX: currentX, clientY: currentY })); } await sleep(50); move(step, step) while (currentX != endX || currentY != endY) { await sleep(50); const stepX = Math.min(step, Math.max(-step, endX - currentX)); const stepY = Math.min(step, Math.max(-step, endY - currentY)); move(stepX, stepY); } await sleep(50) document.dispatchEvent(new MouseEvent('mouseup', { view: window, bubbles: true, cancelable: false, clientX: endX, clientY: endY, button: 0 })); } { const canvas = document.querySelector('canvas.H1VXrf.JRr1M.DnOnV'); """ + f"simulateDrag(canvas, {int(-dx)}, {int(dy)});" + """ } """