170 lines
4.6 KiB
Python
170 lines
4.6 KiB
Python
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) -> np.ndarray | None:
|
||
"""Оценивает матрицу трансформации на основе сопоставленных точек"""
|
||
# Используем RANSAC для оценки матрицы гомографии
|
||
H, _ = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 3.0, maxIters=1000)
|
||
return H
|
||
|
||
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)});" + """
|
||
}
|
||
""" |