Byte & SandStorm
Привет, Байт, ты когда-нибудь пробовал картографировать лабиринт дроном над каньоном в пустыне? Только что пережил песчаную бурю и нашел просто невероятное место – думаю, у тебя найдется какой-нибудь крутой код для отслеживания.
Да, кое-как этим баловался. Главное – держать конвейер данных максимально простым, чтобы дрон мог его обрабатывать на лету. Вот набросок на Python, который можно запустить на Raspberry Pi или на любом узле, который ты прикрутил к дрону. Он берёт кадры с камеры, делает примерную оценку глубины с помощью стерео или модели определения глубины по одному изображению, а затем запускает базовый A*, чтобы построить карту каменистого ущелья. Пока не готово к производству, но суть передаёт.
import cv2
import numpy as np
from heapq import heappush, heappop
# Получаем кадр с камеры дрона
cap = cv2.VideoCapture(0)
# Упрощенная оценка глубины – замени на настоящую модель
def estimate_depth(frame):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# псевдо-глубина на основе краев
depth = cv2.Sobel(gray, cv2.CV_64F, 1, 1, ksize=5)
return np.abs(depth)
# Простой A* на сетке, полученной из карты глубины
def astar(start, goal, depth):
h = lambda p: abs(p[0]-goal[0]) + abs(p[1]-goal[1])
open_set = [(h(start), start)]
came_from = {}
g_score = {start: 0}
while open_set:
_, current = heappop(open_set)
if current == goal:
path = []
while current in came_from:
path.append(current)
current = came_from[current]
return path[::-1]
for dx, dy in [(1,0),(-1,0),(0,1),(0,-1)]:
nxt = (current[0]+dx, current[1]+dy)
if 0 <= nxt[0] < depth.shape[0] and 0 <= nxt[1] < depth.shape[1]:
# штрафуем большую глубину (крутой рельеф)
tentative_g = g_score[current] + 1 + depth[nxt]
if tentative_g < g_score.get(nxt, float('inf')):
came_from[nxt] = current
g_score[nxt] = tentative_g
heappush(open_set, (tentative_g + h(nxt), nxt))
return []
while True:
ret, frame = cap.read()
if not ret: break
depth = estimate_depth(frame)
# выбираем начальную и конечную точки на карте – для демонстрации используем углы
path = astar((0,0), (depth.shape[0]-1, depth.shape[1]-1), depth)
# визуализируем путь на кадре
for p in path:
cv2.circle(frame, (p[1], p[0]), 2, (0,0,255), -1)
cv2.imshow('maze', frame)
if cv2.waitKey(1) & 0xFF == ord('q'): break
cap.release()
cv2.destroyAllWindows()
Вот основная идея: захват, глубина, путь. Ты можешь заменить модель определения глубины на что-нибудь вроде MiDaS или стереопару, если у тебя две камеры. Для настоящего ущелья тебе понадобится слияние GPS-координат и более высокий уровень SLAM, но это даст тебе отправную точку. Если возникнут какие-то трудности, дай знать – я могу помочь подправить оценщик глубины или планировщик пути.