RoboDine 프로젝트의 컴퓨터 비전 기술 구현
서론
RoboDine 프로젝트에서 저는 CookGPT 시스템의 컴퓨터 비전 부분을 담당하여 조리 로봇의 ‘눈’ 역할을 하는 시스템을 개발했습니다. 이 글에서는 YOLOv8을 활용한 객체 감지 시스템과 OpenCV 기반 영상 처리 기술을 어떻게 구현했는지, 그리고 프로젝트 과정에서 겪었던 기술적 도전과 해결 방안을 공유하겠습니다.
RoboDine의 컴퓨터 비전 시스템
RoboDine 프로젝트에서 컴퓨터 비전은 조리 로봇(COOKBOT)이 주방 환경을 인식하고 정밀한 작업을 수행할 수 있도록 하는 핵심 기술이었습니다.
시스템 구성 요소
우리가 구현한 비전 시스템의 주요 구성 요소는 다음과 같습니다:
- YOLOv8 객체 감지: 식재료 블록 실시간 인식
- OpenCV 영상 처리: 카메라 입력 처리 및 전처리
- UDP 통신: 저지연 비전 데이터 전송
- ROS2 연동: 로봇 제어 시스템과의 통합
기술적 구현
YOLOv8을 활용한 객체 감지 시스템
RoboDine의 CookGPT 시스템에서는 YOLOv8을 사용하여 주방 환경의 객체들을 실시간으로 감지했습니다.
import cv2
import numpy as np
from ultralytics import YOLO
import socket
class CookGPTVision:
def __init__(self):
# YOLOv8 모델 로드
self.model = YOLO('yolov8n.pt') # 경량화된 모델 사용
# UDP 소켓 설정 (포트 8003)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.server_address = ('localhost', 8003)
# 카메라 설정
self.cap = cv2.VideoCapture(0)
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
def detect_objects(self, frame):
"""객체 감지 수행"""
results = self.model(frame)
detections = []
for result in results:
boxes = result.boxes
if boxes is not None:
for box in boxes:
# 바운딩 박스 좌표
x1, y1, x2, y2 = box.xyxy[0].cpu().numpy()
confidence = box.conf[0].cpu().numpy()
class_id = int(box.cls[0].cpu().numpy())
class_name = self.model.names[class_id]
detection = {
'class': class_name,
'confidence': float(confidence),
'bbox': [int(x1), int(y1), int(x2), int(y2)]
}
detections.append(detection)
return detections
좌표계 변환의 중요성
로봇 시스템에서 가장 까다로운 부분 중 하나는 다양한 좌표계 간의 변환입니다. 우리 시스템에서는 다음과 같은 좌표계들을 다뤄야 했습니다:
- 카메라 좌표계: 카메라에서 인식된 물체의 좌표
- 로봇 베이스 좌표계: 로봇의 기준 좌표계
- 엔드이펙터 좌표계: 로봇 그리퍼의 좌표계
- 물체 좌표계: 대상 물체의 고유 좌표계
# 베이스 좌표계에서 타겟 위치 계산
T_base_2_target = T_ee_current @ T_ee_2_cam @ T_cam_2_obj
# 그리퍼 오프셋을 고려한 최종 목표 위치
T_base_2_ee_target = T_base_2_target @ T_gripper_2_ee
# 안전 오프셋 적용 (z축으로 50mm 띄우기)
target_pose6d = homogeneous_to_pose6d(T_base_2_ee_target)
target_pose6d[2] += 50.0
도전과 해결 과정
1. 조리 시 6D 추론 실패 문제
초기에는 조리 과정에서 6D 포즈 추정이 자주 실패하는 문제가 있었습니다. 주요 원인들은 다음과 같았습니다:
- 조명 변화: 조리 과정에서 발생하는 열과 증기로 인한 조명 환경 변화
- 물체 변형: 요리 재료들이 조리 과정에서 모양이 변하는 문제
- 가림 현상: 다른 재료나 도구에 의해 대상 물체가 부분적으로 가려지는 상황
2. 해결 방안
이러한 문제들을 해결하기 위해 다음과 같은 접근법을 적용했습니다:
다중 뷰포인트 활용
# 여러 각도에서 촬영한 이미지를 활용한 로버스트 추정
def multi_view_pose_estimation(images, camera_matrices):
poses = []
confidences = []
for img, K in zip(images, camera_matrices):
pose, confidence = estimate_6d_pose(img, K)
if confidence > threshold:
poses.append(pose)
confidences.append(confidence)
# 가중 평균으로 최종 포즈 결정
final_pose = weighted_average(poses, confidences)
return final_pose
적응적 임계값 조정
조리 환경의 변화에 대응하기 위해 적응적 임계값 시스템을 구현했습니다:
def adaptive_threshold_adjustment(lighting_condition, steam_level):
"""환경 조건에 따른 임계값 동적 조정"""
base_threshold = 0.7
# 조명 조건에 따른 조정
lighting_factor = max(0.8, min(1.2, lighting_condition / 100))
# 증기 수준에 따른 조정
steam_factor = max(0.6, 1.0 - steam_level * 0.1)
return base_threshold * lighting_factor * steam_factor
성능 최적화
Hand-Eye Calibration
로봇의 손과 눈(카메라) 간의 정확한 캘리브레이션이 6D 포즈 추정의 정확도에 미치는 영향은 매우 큽니다. 우리는 다음과 같은 방법으로 캘리브레이션 정확도를 향상시켰습니다:
- 체스보드 패턴 활용: 다양한 위치와 각도에서의 캘리브레이션 데이터 수집
- 반복적 최적화: 초기 추정값을 바탕으로 한 반복적 개선
- 검증 데이터셋: 캘리브레이션 결과의 정확성 검증
실시간 처리 최적화
class RealTimeProcessor:
def __init__(self):
self.frame_buffer = deque(maxlen=5)
self.pose_history = deque(maxlen=10)
def process_frame(self, frame):
# 이전 프레임들을 활용한 시간적 일관성 확보
if len(self.pose_history) > 0:
predicted_pose = self.predict_next_pose()
search_region = self.get_search_region(predicted_pose)
# 관심 영역만 처리하여 연산량 감소
roi_frame = self.extract_roi(frame, search_region)
current_pose = self.estimate_pose(roi_frame)
else:
current_pose = self.estimate_pose(frame)
# 칼만 필터를 활용한 노이즈 제거
filtered_pose = self.kalman_filter.update(current_pose)
self.pose_history.append(filtered_pose)
return filtered_pose
학습한 교훈
1. 데이터의 품질이 모든 것을 결정한다
아무리 좋은 알고리즘을 사용해도 입력 데이터의 품질이 낮으면 좋은 결과를 얻기 어렵습니다. 특히 로봇 환경에서는:
- 조명 일관성: 일정한 조명 환경 유지의 중요성
- 카메라 캘리브레이션: 정확한 내부/외부 파라미터 추정
- 노이즈 처리: 센서 노이즈와 환경 노이즈에 대한 대응
2. 실시간성과 정확도의 트레이드오프
실제 로봇 시스템에서는 완벽한 정확도보다는 실시간으로 ‘충분히 좋은’ 결과를 제공하는 것이 더 중요할 때가 많습니다.
3. 시스템 통합의 복잡성
개별 컴포넌트가 잘 작동한다고 해서 전체 시스템이 원활하게 동작하는 것은 아닙니다. 각 서브시스템 간의 인터페이스와 데이터 흐름을 신중히 설계해야 합니다.
결론
6D 포즈 추정 기술은 현대 로봇공학에서 핵심적인 역할을 하고 있습니다. 프로젝트를 통해 이론과 실제 구현 사이의 간극을 경험하고, 실용적인 해결책을 찾아가는 과정이 매우 의미 있었습니다.
앞으로는 딥러닝 기반의 6D 포즈 추정 방법들을 탐구하고, 더 복잡하고 동적인 환경에서도 안정적으로 작동하는 시스템을 개발해보고 싶습니다.
이 글이 로봇 비전 기술에 관심 있는 분들께 도움이 되었기를 바랍니다. 궁금한 점이나 함께 논의하고 싶은 내용이 있으시면 언제든 댓글로 남겨주세요.
Enjoy Reading This Article?
Here are some more articles you might like to read next: