OBB
Axis-Aligned Bounding Box
- 일반적인 물체 탐지에서 사용하는 직사각형 박스. 항상 이미지 축에 평행
- 회전된 객체: 객체가 기울어져 있으면 AABB가 필요 이상으로 커짐
- 불필요한 배경 영역 포함
- 주변 객체와 과도하게 겹침
- 객체들이 서로 바싹 붙어 있거나 겹쳐 있을 때, 여러 객체가 하나의 상자 안에 포함될 수 있음
- 객체별 정확한 분리 어려움
- 정확한 위치 파악 어려움: 객체의 실제 방향성 정보 손실
Oriented Bounding Box
- 객체의 방향에 맞춰 회전 가능한 직사각형 박스.
- 일반적으로 중심점, 너비, 높이, 회전 각도로 표현.
- OBB의 필요성:
- 항공 사진의 건물, 차량, 선박 등 회전된 객체 탐지.
- 제조 공정에서 부품의 정확한 위치 및 방향 파악.
- 문서 이미지에서 텍스트 블록 탐지.
- 장점:
- 정확한 객체 영역 표현: 불필요한 배경 포함 감소.
- 겹치는 객체 분리 용이: 박스 간 IoU를 더 정확히 계산.
- 객체 방향 정보 제공: 후속 처리(예: 로봇 팔 제어)에 유용.
OBB 탐지
- 모델
from ultralytics import YOLO
model = YOLO('yolo11n-obb.pt')
- 이미지 불러오기
import cv2 as cv
img = cv.imread('boats.jpg')
- 탐지
results = model(img)
- 미세조정을 할 때는 Label Studio에서 내보내기 할 때 YOLOv8 OBB with Images 로
탐지 결과 시각화
# 임포트
from PIL import Image, ImageDraw, ImageFont
# 글꼴 설정: 같은 폴더에 ttf 글꼴 파일이 있어야 함. 없으면 기본 글꼴 사용.
try:
font = ImageFont.truetype("NanumGothic.ttf", 20)
except IOError:
font = ImageFont.load_default()
import math
# 결과를 그릴 새 이미지 만듦
img_bbox = Image.fromarray(cv.cvtColor(img, cv.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img_bbox)
# 결과
result = results[0] # 이미지가 하나이므로 결과도 하나
positions = result.obb.xyxyxyxy.cpu().numpy()
boxes = result.obb.xywhr.cpu().numpy()
clss = result.obb.cls.int().cpu().numpy()
confs = result.obb.conf.cpu().numpy()
for pos, box, cls, conf in zip(positions, boxes, clss, confs):
# 초록색 경계 상자 그리기
# pos는 4개의 꼭짓점 좌표 (x1,y1, x2,y2, x3,y3, x4,y4)를 포함
# PIL의 polygon은 (x1,y1), (x2,y2)... 형태의 튜플 리스트를 인자로 받으므로 변환
draw.polygon([tuple(p) for p in pos], outline="#00FF00", width=3)
# 클래스 이름 및 신뢰도 레이블 생성
name = result.names[cls]
label = f"{name}({conf:.2f})"
# 박스 정보: 중심 x, 중심 y, 너비, 높이, 각도(라디안)
x, y, w, h, r_rad = box
# 1. 방향 선의 길이를 박스 너비의 절반으로 설정
arrow_length = w / 2.0
# 2. 삼각함수를 사용하여 방향 선의 끝점 계산
# 각도 r_rad는 x축 양의 방향에서 시작하는 반시계 방향 각도
# 끝점 x = 시작점 x + 길이 * cos(각도)
# 끝점 y = 시작점 y + 길이 * sin(각도)
end_x = x + arrow_length * math.cos(r_rad)
end_y = y + arrow_length * math.sin(r_rad)
# 3. 중심점에 작은 빨간 원 그리기
center_radius = 4
draw.ellipse(
(x - center_radius, y - center_radius, x + center_radius, y + center_radius),
fill="#FF0000" # 빨간색
)
# 4. 중심점에서 끝점을 향하는 빨간 선(방향 표시) 그리기
draw.line(
[(x, y), (end_x, end_y)],
fill="#FF0000", # 빨간색
width=3)
# 텍스트 레이블 위치를 첫 번째 꼭짓점 근처로 설정
text_position = tuple(pos[0])
draw.text(text_position, label, fill="#00FF00", font=font)
img_bbox # 이미지 보기
사용자 정보 입력
퀴즈를 시작하기 전에 이름과 소속을 입력해주세요.