안녕하세요! 오늘은 해수욕장 안전을 위한 이안류(Rip Current) 탐지 모델 구축 과정과, 이미지 분석의 꽃이라 불리는 세그멘테이션(Segmentation)의 기초를 정리해 보겠습니다.
1️⃣이안류 CCTV 데이터셋을 활용한 객체 탐지 (Object Detection)
이안류는 파도가 해안에서 바다 쪽으로 급격히 빠져나가는 현상으로, 인명 사고의 주요 원인입니다. AI Hub의 데이터를 활용해 이를 자동으로 감지하는 YOLOv8 모델을 학습시켜 보았습니다.
1. 데이터 준비 및 환경 설정
먼저 YOLOv8 사용을 위한 ultralytics 라이브러리를 설치하고, 데이터를 학습/검증/테스트(Train/Valid/Test) 세트로 나누기 위한 폴더 구조를 생성합니다.
data_root = '/content/drive/MyDrive/랭체인 AI 영상객체탐지분석 플랫폼 구축/11. 멀티모달/data'
file_root = f'{data_root}/Sample'
pjt_name = 'ripcurrent'
train_root = f'{data_root}/{pjt_name}/train'
valid_root = f'{data_root}/{pjt_name}/valid'
test_root = f'{data_root}/{pjt_name}/test'
for folder in [train_root, valid_root, test_root]:
if not os.path.exists(folder):
os.makedirs(folder)
for s in ['images', 'labels']:
s_folder = f'{folder}/{s}'
if not os.path.exists(s_folder):
os.makedirs(s_folder)
2. AI Hub JSON을 YOLO 포맷으로 변환
AI Hub 데이터는 주로 JSON 형태입니다. YOLO 모델 학습을 위해서는 (class, x_center, y_center, width, height) 형태의 정규화된(0~1 사이 값) .txt 파일이 필요합니다.
- 변환 공식:
- $x\_center = \frac{(xmin + xmax)}{2 \times width}$
- $y\_center = \frac{(ymin + ymax)}{2 \times height}$
def json_to_yolo_bbox(bbox, w, h):
# xcenter = xmin, xmax / 2 더하고 나누기
# ycenter = ymin, ymax / 2
'''
bbox[0] = [743, 243]
bbox[0][0] = 743 ->좌상 x좌표
bbox[0][1] = 243 -> 좌상 y좌표
bbox[1][0] = 1494 -> 우상 x좌표
bbox[3][1] = 309 좌하단 y좌표
'''
x_center = ((bbox[0][0] + bbox[1][0]) / 2) / w
y_center = ((bbox[0][1] + bbox[3][1]) / 2) / h
width = (bbox[1][0]- bbox[0][0]) / w
height = (bbox[3][1]- bbox[0][1]) / h
return [x_center, y_center, width, height]
2-1 Json -> txt 파일로 변환
file = file_list[301]
result = set()
with open(file, 'r') as f:
json_data = json.load(f)
width, height = list(map(int, json_data['image_info']['resolution'].split(',')))
# print(width, height) # 1920 1080
cls = 0
if json_data['annotations'].get('drawing'):
for b in json_data['annotations']['drawing']:
yolo_bbox = json_to_yolo_bbox(b, width, height)
bbox_string = " ".join([str(x) for x in yolo_bbox])
result.add(f'{cls} {bbox_string}')
result = list(result)
if result:
with open(file.replace('json', 'txt'), 'w', encoding='utf-8') as t:
t.write('\n'.join(result))
print(file)
3. 모델 학습 (YOLOv8)
가장 가벼운 모델 중 하나인 yolov8s.pt를 사용하여 학습을 진행했습니다.
- Epochs: 10 (학습 횟수)
- imgsz: 224 (이미지 크기)
- amp=False: 혼합 정밀도 학습을 끄고 안정성을 높임
model = YOLO('yolov8s.pt')
results = model.train(data='ripcurrent.yaml', epochs=10, batch=8, imgsz=224)
4. 성능 평가 및 결과 시각화
학습이 완료되면 mAP(Mean Average Precision)를 통해 성능을 확인합니다.
metrics.box.map
# np.float64(0.4149619355972097)
metrics.box.map50
# np.float64(0.8311188076870113)
- mAP@0.5: IoU가 0.5 이상일 때의 정확도
- mAP@0.5:0.95: 다양한 IoU 임계값에서의 평균 성능 (0.8 이상이면 매우 우수)
- 테스트 해본 데이터는 샘플 데이터이기 때문에 데이터셋양도 적고, 그 데이터로 또 test, valid, train으로 나누었기 때문에 당연히 학습 정확도는 높지 않다.
4-1 학습 후 시각화
plt.figure(figsize = (12,6))
for idx in range(6):
test_img = cv2.imread(test_file_list[idx])
img_src = cv2.cvtColor(test_img, cv2.COLOR_BGR2RGB)
results = model(test_img)
for result in results:
annotator = Annotator(img_src)
boxes = result.boxes
for box in boxes:
b = box.xyxy[0] # get box coordinates in (top, left, bottom, right) format
cls = box.cls
annotator.box_label(b, model.names[int(cls)], color_dict[int(cls)])
img_src = annotator.result()
plt.subplot(2, 3, (idx+1))
plt.imshow(img_src)
plt.show()

2️⃣이미지 세그멘테이션 (Segmentation) 이해하기
Segmentation은 컴퓨터 비전에서 이미지나 영상을 픽셀 단위로 분할하여 각 영역이 무엇을 나타내는지 구분하는 기술입니다. 이는 크게 Semantic Segmentation과 Instance Segmentation으로 나뉘는데, Semantic Segmentation은 같은 종류의 객체를 동일한 클래스로 분류하는 반면, Instance Segmentation은 같은 클래스 내에서도 개별 객체를 구분합니다. 이를 통해 의료 영상 분석, 자율주행, 위성 이미지 처리 등 다양한 분야에서 정밀한 객체 인식을 수행할 수 있습니다. Segmentation 모델로는 U-Net, DeepLab, Mask R-CNN 등이 널리 사용됩니다.
핵심 개념
- Semantic Segmentation: 같은 클래스(예: 사람)는 모두 같은 색으로 칠함.
- Instance Segmentation: 같은 사람이라도 개체별로(사람1, 사람2) 구분하여 인식.
COCO 데이터셋 시각화 실습
데이터 분석 시 가장 많이 접하는 COCO(Common Objects in Context) 포맷의 JSON 파일을 파싱하여 이미지 위에 직접 영역을 그려보았습니다.
COCO 데이터 시각화의 핵심 로직:
- JSON 로드: image_id를 기준으로 해당 이미지의 어노테이션(Annotation) 정보를 가져옵니다.
- Segmentation 좌표 추출: 리스트 형태로 저장된 다각형(Polygon) 좌표를 넘파이 배열로 변환합니다.
- 그리기: OpenCV의 cv2.polylines 함수를 이용해 이미지 위에 다각형 선을 그립니다.
# 좌표 변환 및 그리기 예시
points = np.array(seg).reshape(-1, 2).astype(np.int32)
cv2.polylines(image, [points], isClosed=True, color=(0, 255, 0), thickness=2)
마무리
오늘 실습을 통해 데이터 전처리(JSON -> TXT) -> 모델 학습(YOLOv8) -> 성능 평가 -> 결과 시각화로 이어지는 객체 탐지의 전체 파이프라인을 경험했습니다. 또한, 세그멘테이션을 통해 단순 탐지를 넘어 픽셀 단위 분석의 기초를 다질 수 있었습니다.
'개념 정리 step2 > 멀티모달(Multi-modal)' 카테고리의 다른 글
| [Deep Learning] TensorFlow 기초와 날씨 분류 모델 실습 (0) | 2026.01.12 |
|---|---|
| [CV Archive] YOLOv8 Segmentation: 스타벅스 로고 추출하기 (0) | 2026.01.11 |
| [YOLO] 축구 영상 객체 탐지 프로젝트: Nano vs Small 모델 성능 비교 분석 (0) | 2026.01.10 |
| [CV Archive] 컴퓨터 비전과 객체 탐지(Object Detection) (0) | 2026.01.07 |
| [OpenCV] Open Source Computer Vision Library 개념 정리 (0) | 2026.01.06 |