Без зору робот — сліпий автомат, що працює строго за програмою. CV додає адаптивність: захоплення довільно орієнтованих деталей, інспекція в процесі складання, навігація в динамічному середовищі, спільна робота з людиною з дотриманням ISO 15066. Ми інтегруємо системи комп'ютерного зору в промислові маніпулятори та мобільних роботів — це зв'язка: 6DoF pose estimation для захоплення деталей з контейнера (bin picking), depth-guided grasping та побудова семантичних карт для AMR. Економія на одній bin picking ділянці — суттєва за рахунок зниження ручної праці та браку.
Як CV вирішує проблему bin picking?
Bin picking — одна з найбільш затребуваних і складних задач. Деталі в контейнері перекривають одна одну, хаотично орієнтовані, часто мають відбивні поверхні. Основний метод — 6DoF pose estimation: визначаємо положення (x,y,z) та поворот (roll,pitch,yaw) кожної деталі. Для цього використовуємо RGB-D камери (RealSense, Azure Kinect) та одну з моделей:
- FoundationPose — state-of-the-art для деталей з відомою CAD-моделлю. Забезпечує ADD-0.1d 78–89%.
- GDR-Net — геометрично дискретизований рендеринг, працює без CAD, але точність нижча.
- PVPN (Point Voting) — для сильно зашумлених сцен, стійка до часткових перекриттів.
Приклад реалізації на PyTorch (скорочено):
import numpy as np
import cv2
import torch
from dataclasses import dataclass
from typing import Optional
@dataclass
class ObjectPose:
object_class: str
position_xyz: tuple[float, float, float] # мм в системі координат камери
rotation_matrix: np.ndarray # 3×3
euler_angles: tuple[float, float, float] # roll, pitch, yaw в градусах
confidence: float
grasp_point: tuple[float, float, float] # рекомендована точка захвату
grasp_approach: np.ndarray # вектор підходу захвату
class BinPickingSystem:
"""
Система bin picking: виявлення та визначення пози деталей в контейнері.
Методи:
1. FoundationPose / DenseFusion: на основі RGB-D
2. GDR-Net: геометрично дискретизований рендеринг
3. PVPN: point-wise voting
Камера: Intel RealSense D435i або Azure Kinect.
CAD модель деталі обов'язкова для FoundationPose.
"""
def __init__(self, pose_model_path: str,
cad_model_path: str,
object_classes: list[str],
camera_intrinsics: dict,
device: str = 'cuda'):
self.device = device
self.object_classes = object_classes
self.camera_intrinsics = camera_intrinsics # fx, fy, cx, cy
# Завантаження pose estimation моделі
self.pose_model = torch.load(pose_model_path,
map_location=device).eval()
# CAD модель для рендерингу (використовується FoundationPose)
self.cad_model = self._load_cad_model(cad_model_path)
# YOLO для первинного виявлення об'єктів
from ultralytics import YOLO
self.detector = YOLO(pose_model_path.replace('pose', 'det'))
def _load_cad_model(self, cad_path: str):
"""Завантаження .ply або .obj CAD моделі"""
try:
import open3d as o3d
return o3d.io.read_triangle_mesh(cad_path)
except ImportError:
return None
def estimate_poses(self, rgb: np.ndarray,
depth: np.ndarray) -> list[ObjectPose]:
"""
Оцінка пози об'єктів.
rgb: (H, W, 3) uint8
depth: (H, W) float32 в міліметрах
"""
# 1. Детекція об'єктів для ROI
detections = self.detector(rgb, conf=0.4, verbose=False)
poses = []
for box in detections[0].boxes:
cls_id = int(box.cls.item())
if cls_id >= len(self.object_classes):
continue
x1, y1, x2, y2 = map(int, box.xyxy[0])
# Вирізати RGB та depth патч
rgb_crop = rgb[y1:y2, x1:x2]
depth_crop = depth[y1:y2, x1:x2]
if rgb_crop.size == 0:
continue
# 2. Pose estimation на патчі
pose = self._estimate_single_pose(
rgb_crop, depth_crop, cls_id, (x1, y1)
)
if pose:
poses.append(pose)
# Сортування за висотою Z (верхні деталі першими)
poses.sort(key=lambda p: p.position_xyz[2])
return poses
@torch.no_grad()
def _estimate_single_pose(self, rgb_crop: np.ndarray,
depth_crop: np.ndarray,
cls_id: int,
offset: tuple) -> Optional[ObjectPose]:
"""Pose estimation для одного об'єкта"""
from torchvision import transforms
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
from PIL import Image
pil = Image.fromarray(cv2.cvtColor(rgb_crop, cv2.COLOR_BGR2RGB))
rgb_tensor = transform(pil).unsqueeze(0).to(self.device)
depth_tensor = torch.from_numpy(depth_crop).unsqueeze(0).unsqueeze(0).float().to(self.device)
# Конкатенація RGB + depth
depth_norm = depth_tensor / 1000.0 # мм → метри
# Спрощена модель приймає 4-channel input
input_tensor = torch.cat([
rgb_tensor,
torch.nn.functional.interpolate(
depth_norm, size=rgb_tensor.shape[-2:], mode='bilinear'
)
], dim=1)
output = self.pose_model(input_tensor)
# output: (1, 6) — translation(3) + rotation_euler(3)
if output is None or output.shape[-1] < 6:
return None
out_np = output.squeeze().cpu().numpy()
tx, ty, tz = out_np[:3] * 1000 # метри → мм
rx, ry, rz = np.degrees(out_np[3:6])
# Матриця обертання з ейлерових кутів
R, _ = cv2.Rodrigues(np.array([np.radians(rx),
np.radians(ry),
np.radians(rz)]))
# Точка захвату: центр об'єкта + зсув вгору по нормалі
grasp_z = tz - 30 # 30мм вище центру
grasp_point = (tx, ty, grasp_z)
approach_vec = R @ np.array([0, 0, -1]) # напрямок підходу
conf = float(torch.sigmoid(
self.pose_model.confidence_head(output) if hasattr(
self.pose_model, 'confidence_head') else torch.tensor(0.0)
).item()) if hasattr(self.pose_model, 'confidence_head') else 0.8
return ObjectPose(
object_class=self.object_classes[cls_id],
position_xyz=(round(tx, 1), round(ty, 1), round(tz, 1)),
rotation_matrix=R,
euler_angles=(round(rx, 1), round(ry, 1), round(rz, 1)),
confidence=round(conf, 3),
grasp_point=grasp_point,
grasp_approach=approach_vec
)
Чому 6DoF pose estimation критична для колаборативних роботів?
Колаборативні роботи працюють в одному просторі з людьми. Помилка у визначенні пози деталі призводить до зіткнення або пошкодження об'єкта. Для cobot-застосувань за ISO 15066 потрібна повторюваність захвату з точністю ±1 мм та затримка менше 50 мс. Саме 6DoF pose estimation дає необхідну точність для безпечного підходу та захвату.
Метрики порівняння методів:
| Задача | Метод | Метрика |
|---|---|---|
| 6DoF pose estimation (metallic parts) | FoundationPose | ADD-0.1d 78–89% |
| Bin picking (stacked bolts) | GDR-Net + depth | Success rate 82–91% |
| AMR obstacle detection | YOLOv8 + RealSense | [email protected] 87–93% |
| Human proximity (ISO 15066) | depth segmentation | <50ms latency |
| Assembly verification | Vision Transformer | Accuracy 91–96% |
FoundationPose краще GDR-Net в 1.2 рази за ADD при наявності CAD, але без CAD GDR-Net виграє за рахунок відсутності потреби в моделі. PVPN стійкіший до перекриттів, але повільніший (15 FPS проти 30 FPS у FoundationPose).
Як ми проектуємо систему комп'ютерного зору для роботів?
Процес починається з аудиту вашого виробництва: які операції виконуються, які деталі, які поточні проблеми. Далі ми підбираємо обладнання (камери, освітлення, контролери) та розробляємо алгоритм CV. Етапи:
- Збір даних: зйомка сцен на вашому виробництві, розмітка поз (6DoF) за допомогою наших інструментів.
- Вибір моделі: FoundationPose, GDR-Net або кастомний Transformer залежно від наявності CAD та допустимої затримки.
- Навчання та валідація: на синтетичних та реальних даних. Досягаємо ADD-0.1d > 85%.
- Інтеграція: в ROS2 node для маніпулятора або в OPC-UA для PLC. Забезпечуємо реальний час.
- Тестування: на виробничій лінії протягом 2 тижнів. Фіксуємо KPI (цикл захвату, відсоток успішних спроб).
Типовий склад команди проекту
- AI інженер CV (досвід PyTorch, OpenCV, 3D geometry) - Інженер-робототехнік (ROS2, промислові контролери) - Data engineer (збір та розмітка даних) - DevOps (контейнеризація, інференс на GPU)Vision для навігації AMR
Мобільні роботи (AMR/AGV) використовують CV для детекції перешкод, людей та побудови карти. Типова архітектура — YOLOv8 на RGB-D, segmentation depth, розділення на сектори для планування траєкторії. Приклад фрагмента коду:
class AMRNavigationVision:
"""
Computer vision для автономних мобільних роботів (AMR).
Завдання: obstacle detection, semantic mapping, людино-розпізнавання
для cobot safety (ISO/TS 15066 protected/restricted speed zones).
"""
def __init__(self, obstacle_model_path: str,
device: str = 'cuda'):
from ultralytics import YOLO
self.obstacle_model = YOLO(obstacle_model_path)
self.device = device
# Semantic map: {cell_id: label}
self.semantic_map: dict = {}
def process_navigation_frame(self, rgb: np.ndarray,
depth: np.ndarray) -> dict:
"""
Аналіз кадру для навігації AMR.
Повертає: obstacles, nearest_human_dist_m, clear_path_sectors.
"""
results = self.obstacle_model(rgb, conf=0.4, verbose=False)
obstacles = []
nearest_human_dist = float('inf')
h, w = depth.shape[:2]
sector_width = w // 5 # 5 секторів: LL/L/C/R/RR
for box in results[0].boxes:
x1, y1, x2, y2 = map(int, box.xyxy[0])
cls_name = results[0].names[int(box.cls.item())]
cx = (x1 + x2) // 2
cy = (y1 + y2) // 2
# Медіанна глибина в bbox
depth_crop = depth[y1:y2, x1:x2]
valid_depths = depth_crop[depth_crop > 0]
dist_m = float(np.median(valid_depths)) / 1000.0 if len(valid_depths) > 0 else 0
obstacles.append({
'class': cls_name,
'bbox': [x1, y1, x2, y2],
'distance_m': round(dist_m, 2),
'sector': min(cx // sector_width, 4)
})
if cls_name == 'person' and dist_m < nearest_human_dist:
nearest_human_dist = dist_m
# Визначити вільні сектори
blocked_sectors = {o['sector'] for o in obstacles if o['distance_m'] < 1.5}
clear_sectors = [s for s in range(5) if s not in blocked_sectors]
# ISO/TS 15066: якщо людина < 0.5м → STOP; 0.5–1.5м → reduced speed
safety_mode = ('STOP' if nearest_human_dist < 0.5
else 'REDUCED_SPEED' if nearest_human_dist < 1.5
else 'NORMAL')
return {
'obstacles': obstacles,
'nearest_human_m': round(nearest_human_dist, 2),
'clear_sectors': clear_sectors,
'safety_mode': safety_mode
}
Що входить в роботу над проектом CV?
Ми надаємо повний цикл: аналітика вимог, підбір обладнання, калібрування камери та робота, навчання моделей на ваших даних, інтеграція з контролером (ROS2/OPC-UA), тестування в production-умовах. У deliverables:
- Модель pose estimation (ONNX/TensorRT)
- Інтеграційний модуль для PLC
- Документація з безпечної експлуатації
- Навчання операторів
- Гарантійна підтримка 6 місяців
Терміни та вартість
Терміни — від 8 до 20 тижнів залежно від складності. Вартість розраховується індивідуально після аудиту вашого виробництва. Ми гарантуємо прозорість етапів і фіксуємо KPI в договорі.
| Задача | Термін |
|---|---|
| Pose estimation для одного типу деталі | 8–12 тижнів |
| Bin picking система з gripper integration | 14–20 тижнів |
| AMR navigation vision + safety monitoring | 12–18 тижнів |
Наш досвід та гарантії
Багаторічний досвід у промисловому CV, десятки проектів від bin picking до інспекції. Сертифіковані інженери з PyTorch, ROS2, OpenCV. Використовуємо офіційні бібліотеки: OpenCV та ISO 15066. Даємо гарантію на точність моделей (ADD і recall прописані в договорі).
Отримайте консультацію щодо вашого проекту — зв'яжіться з нами, щоб обговорити завдання та зробити прототип. Замовте попередній аудит вашого виробництва — це безкоштовно.







