Ultralytics YOLO27: 대기자 명단에 등록하세요.
Get Started
Ultralytics Platform으로 구축하기·데이터셋 구축·레슨 2/10
강의중급

데이터 추가 및 준비

업로드 전에 로컬에서 데이터셋을 검사하고, 동영상을 계획적으로 샘플링하여, 첫 시도에 플랫폼 데이터셋을 준비 완료 상태로 만드세요.

업로드 전에 발견하는 데이터셋 버그가 가장 저렴한 버그입니다. Pascal VOC 레이블은 아무런 알림 없이 건너뛰고, 28픽셀보다 작은 이미지는 거부되며, 30분짜리 동영상에서는 프레임 100개만 추출되는데 대부분 빈 장면입니다. 이 강의에서는 업로드 전 2분 점검을 수행하고, 동영상을 목적에 맞게 샘플링하며, 플랫폼의 처리 상태 신호를 확인해 학습 데이터를 온전히 준비합니다.

학습 성과

로컬 데이터셋을 업로드하기 전에 검사하고, 긴 동영상을 레이블을 지정할 가치가 있는 프레임으로 줄여 샘플링하며, Ready 배지가 표시되는 플랫폼 데이터셋을 만들 수 있습니다.

속성 과정
이미 사용법을 알고 계신다면, 간단히 요약해 드리겠습니다.
  1. 업로드 전 점검을 실행하세요. 분할별 이미지 및 레이블 수, 너무 작거나 큰 이미지, 지원되지 않는 파일, VOC 레이블을 확인합니다.

  2. Annotate에서 New Dataset을 클릭하고 소스, 작업 유형, 비공개 공개 범위를 선택합니다.

  3. 긴 동영상은 먼저 직접 샘플링하세요. 플랫폼은 동영상당 최대 100개의 프레임을 유지합니다.

  4. Errors 및 Charts 탭을 확인한 다음, 배지가 Ready로 표시될 때까지 클릭합니다.

실습형

데이터셋 만들기#

Ultralytics Platform 프로필 페이지에서 데이터셋 탭과 데이터셋 카드, 새 데이터셋 버튼을 보여줍니다

사이드바에서 Annotate을 열고 New Dataset을 클릭합니다. 대화상자에서 소스, 이름, 작업 유형, 선택적 라이선스, 얼굴 흐리게 처리 여부, 공개 범위를 지정합니다:

Ultralytics Platform의 새 데이터셋 대화상자에서 업로드, URL, 클라우드, 온프레미스 소스 탭, 허용되는 형식과 크기 제한을 표시하는 업로드 영역, 작업 유형, 라이선스, 얼굴 흐리게 처리, 공개 범위 설정을 보여줍니다

소스사용할 상황계획
업로드파일이 로컬 컴퓨터에 있는 경우: 이미지, 동영상, 아카이브 또는 NDJSON 내보내기 파일전체
URL공개 .zip, .tar, .tar.gz, .tgz 또는 .ndjson 링크가 있으며, 플랫폼이 서버 측에서 다운로드하는 경우전체
클라우드데이터가 이미 Google Cloud Storage, Amazon S3 또는 Azure Blob Storage에 있으며 해당 위치에 그대로 두어야 하는 경우Pro, Enterprise
온프레미스픽셀 데이터를 절대 로컬 컴퓨터 밖으로 내보내면 안 되는 경우Enterprise

결정 원칙: 이 과정에서는 복사본을 업로드하세요. 클라우드 및 온프레미스 데이터셋은 픽셀 데이터를 플랫폼 외부에 보관하므로 스마트 주석, 클러스터링, 복제, 버전 스냅샷을 사용할 수 없습니다.

작업 유형에 따라 표시되는 도구와 모델이 결정됩니다. 플랫폼은 Ultralytics YOLO의 7가지 작업을 모두 지원합니다:

작업레이블 지정 방법
탐지직사각형 또는 SAM 및 YOLO 스마트 주석
분할다각형 또는 SAM 및 YOLO 스마트 주석
의미론적 분할다각형 또는 SAM 및 YOLO 스마트 주석, PNG 마스크 직접 가져오기
자세 추정기본 제공 또는 사용자 지정 스켈레톤의 키포인트, 스마트 주석용 YOLO 포즈 모델
OBB회전 바운딩 박스 또는 SAM 및 YOLO 스마트 주석
분류사이드바의 클래스 선택기
깊이그리기 없음: 쌍을 이루는 깊이 맵이 있는 이미지를 업로드하세요(업로드 또는 URL만 가능).

실습 예제: 업로드 전에 데이터셋 확인하기#

Platform은 최대 50 MB이며 짧은 변의 길이가 28 px 이상인 JPEG, PNG, WebP, BMP, TIFF, HEIC, AVIF, JP2, DNG, MPO 이미지를 지원하고 YOLO, COCO, LabelMe, Ultralytics 또는 Labelbox NDJSON, 시맨틱 PNG 마스크 레이블을 읽습니다. Pascal VOC XML은 감지되지만 가져오지는 않습니다. 이 스크립트는 로컬 YOLO 데이터셋이 해당 규칙을 따르는지 확인합니다. 여기서는 공개 의료용 알약 데이터셋을 사용합니다.

from collections import Counter
from pathlib import Path

from PIL import Image

from ultralytics.data.utils import check_det_dataset

ACCEPTED = {".jpg", ".jpeg", ".png", ".webp", ".bmp", ".tif", ".tiff", ".heic", ".avif", ".jp2", ".dng", ".mpo"}
data = check_det_dataset("medical-pills.yaml")  # your local dataset YAML
root = Path(data["path"])

problems = Counter()
for split in ("train", "val", "test"):
    if not data.get(split):
        continue
    files = [p for p in Path(data[split]).rglob("*") if p.is_file()]
    images = [p for p in files if p.suffix.lower() in ACCEPTED]
    labeled = 0
    for img in images:
        label = Path(str(img).replace("images", "labels")).with_suffix(".txt")
        labeled += label.exists() and label.stat().st_size > 0
        if min(Image.open(img).size) < 28:
            problems["under 28 px (rejected)"] += 1
        if img.stat().st_size > 50 * 1024**2:
            problems["over 50 MB (rejected)"] += 1
    problems["unsupported files (skipped)"] += len(files) - len(images)
    print(f"{split:<5} {len(images):>4} images, {labeled:>4} labeled, {len(images) - labeled:>3} background")
problems["Pascal VOC .xml labels (not imported)"] += len(list(root.rglob("*.xml")))
print("classes:", data["names"])
print("problems:", {k: v for k, v in problems.items() if v} or "none")
train   92 images,   92 labeled,   0 background
val     23 images,   23 labeled,   0 background
classes: {0: 'pill'}
problems: none

출력 내용:

  • 분할별 개수. train/, val/, test/ 폴더에 있는 이미지는 업로드 시 해당 분할에 유지되므로, 이 수치가 Platform에 표시됩니다. val 행이 없다면 Platform에서 임의의 검증 분할을 만들어 줍니다(아래 주의 사항 참조).
  • 배경 이미지(레이블 파일이 없는 이미지)는 적당한 수라면 괜찮습니다. 모델이 "아무것도 없음"이 어떤 모습인지 학습하는 데 도움이 됩니다. 수백 장에 달한다면 대개 레이블 내보내기에 실패한 것입니다.
  • problems: none은 모든 이미지가 처리된다는 뜻입니다. 여기에 표시되는 개수만큼의 파일은 Errors 탭으로 이동하거나 아예 도착하지 않습니다.

데이터셋 폴더와 그 안의 data.yaml을 함께 압축한 다음, 아카이브를 갤러리로 끌어다 놓으세요. Platform은 형식을 자동으로 감지하고 동일한 이미지는 한 번만 저장합니다. 또한 업로드한 이미지가 데이터셋의 기존 이미지와 충돌하면 건너뛰기, 둘 다 유지, 바꾸기 중에서 선택하라는 메시지를 표시합니다.

실습 예제: Platform이 처리하기 전에 동영상 샘플링하기#

Platform은 각 동영상에서 초당 1프레임을 샘플링하고 최대 100프레임을 유지합니다. 100초보다 긴 클립은 간격을 넓힙니다.

클립 길이유지되는 프레임간격
60초601초
100초1001초
30분(30 fps에서 54,000프레임)10018초

빠르게 살펴보기에는 적합하지만 대부분의 실제 프로젝트에는 부족합니다. 30분 동안 촬영한 교대 근무 영상이 100프레임으로 줄어들고, 대부분은 텅 빈 통로일 것입니다. 긴 영상을 직접 샘플링하고 프레임을 업로드하세요.

균일하게 샘플링하려면 FFmpeg로 충분합니다.

mkdir -p frames
ffmpeg -i source.mp4 -vf fps=1 frames/%06d.jpg

이벤트 기반 샘플링을 하려면 사전 학습된 Ultralytics YOLO 모델을 사용하여 대상 객체가 포함된 프레임만 유지하세요.

from pathlib import Path

import cv2

from ultralytics import YOLO

model = YOLO("yolo26n.pt")  # or your latest fine-tune
out = Path("frames")
out.mkdir(exist_ok=True)

source = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
seen = kept = 0
for i, result in enumerate(model.predict(source, stream=True, vid_stride=5, classes=[0], conf=0.5, verbose=False)):
    seen += 1
    if len(result.boxes):  # keep only frames where a person was detected
        cv2.imwrite(str(out / f"frame_{i:05d}.jpg"), result.orig_img)
        kept += 1
print(f"Kept {kept} of {seen} sampled frames")
Kept 12 of 12 sampled frames

vid_stride=5은 5프레임마다 확인하고, classes=[0]은 사람만 탐지하며, conf=0.5는 신뢰도가 낮은 예측을 무시합니다. 이 분주한 데모 클립에는 샘플링된 모든 프레임에 사람이 있습니다. 대부분 비어 있는 장면을 촬영한 영상에서는 유지되는 프레임의 비율이 급격히 낮아지고, 레이블링 비용도 줄어듭니다. 인접한 유지 프레임이 더 이상 비슷해 보이지 않을 때까지 vid_stride을 높이세요.

Platform의 처리 신호 읽기#

업로드 후 Platform은 검증, 정규화(4,096 px를 초과하는 이미지는 크기 조정), 썸네일 생성, 레이블 파싱, 통계 계산을 수행합니다. 다음 세 곳을 확인하세요.

오류 탭이 열린 Ultralytics Platform 데이터셋 페이지. 이미지 1개를 처리하지 못했다는 배너와 '이미지 파일을 읽을 수 없음'이라는 내용 및 해결 방법 안내가 표시된 표 행이 보입니다

  • Errors 탭은 파일이 처리되지 않을 때만 표시됩니다. 손상된 파일, 지원되지 않는 형식, 28 px 미만의 이미지, CMYK 및 인덱스 색상 모드가 여기에 해당하며 각각 해결 방법이 안내됩니다. 해당 파일을 다시 내보내거나 업로드하세요.
  • Charts 탭에는 분할 분포, 상위 클래스, 이미지 크기, 파일 크기, 어노테이션 위치, 박스 크기, 이미지당 객체 수가 표시됩니다. 거의 나타나지 않는 클래스, 지나치게 작은 이미지, 한쪽 구석에 몰린 박스가 있는지 살펴보세요.
  • 데이터셋 헤더의 배지는 처리가 완료되고 데이터셋에 train 이미지 1개 이상, val 또는 test 이미지 1개 이상, 레이블이 지정된 이미지 1개 이상이 있으면 Ready으로 표시됩니다. Not Ready를 클릭하면 충족되지 않은 조건을 확인할 수 있습니다.

의료용 알약 데이터셋의 Ultralytics Platform 차트 탭. 분할 분포 및 상위 클래스 도넛 차트와 이미지 크기 및 이미지 파일 크기 히스토그램이 표시됩니다

공개 데이터셋에서 시작하기#

공개 건설 PPE 데이터셋의 Ultralytics Platform 데이터셋 복제 대화상자. 새 이름, URL 슬러그, 설명, 작업 유형, 라이선스 입력란과 공개 여부 스위치가 표시됩니다

아직 데이터가 없으신가요? 탐색 페이지에서 공식 데이터셋과 커뮤니티 데이터셋을 확인할 수 있습니다. 데이터셋 복제는 이미지, 어노테이션, 클래스를 작업 공간에 복사하며 저장 공간을 차지합니다. 기본적으로 원본의 공개 여부도 유지하므로, 민감한 데이터를 추가하려면 대화상자의 스위치를 전환하세요.

주의할 점#

Pascal VOC 레이블이 알림 없이 사라집니다

증상: 업로드는 성공하지만 모든 이미지에 레이블이 없는 상태로 들어옵니다. 해결 방법: Platform은 Pascal VOC XML을 감지하지만 가져오지는 않습니다. 먼저 YOLO .txt 레이블 또는 COCO JSON으로 변환합니다. 업로드 전 검사는 .xml 파일 수를 집계하므로 업로드 전에 이 문제를 파악할 수 있습니다.

자동 검증 분할에서 비디오 프레임이 누수됩니다

증상: 검증 mAP는 매우 높지만 배포된 모델의 성능은 그렇지 않습니다. 해결 방법: 분할을 선택하지 않은 업로드로 val이 비어 있으면 Platform은 학습 이미지의 약 20%를 무작위로 val로 옮깁니다. 비디오 프레임에서는 서로 거의 동일한 이웃 프레임이 두 분할에 들어갑니다. 대신 train/ 및 val/ 폴더로 업로드하고, 비디오 또는 카메라별로 분할합니다(강의 4).

어노테이션 도구를 찾을 수 없습니다

증상: 다각형 도구나 키포인트를 찾을 수 없습니다. 해결 방법: 작업 유형에 따라 도구가 결정됩니다. 데이터셋 헤더에서 작업 유형을 변경하세요. 각 이미지는 모든 작업의 레이블을 저장하므로 작업 유형을 전환해도 다른 작업의 레이블이 삭제되지 않고 숨겨집니다.

사용해 보기

자체 데이터셋(또는 의료용 알약 데이터셋)에 preflight.py을 실행하고 보고된 문제를 모두 해결하세요. 그런 다음 비공개 Platform 데이터셋을 만들고 데이터셋과 동영상 하나를 업로드하세요. 갤러리를 확인하기 전에 표를 보고 동영상에서 생성될 프레임 수를 예상하세요.

완료 조건
다음 조건을 모두 충족하면 레슨을 완료한 것입니다.
  • preflight.py에서 업로드한 데이터셋의 problems: none을 보고합니다.

  • 갤러리의 이미지 수는 이미지 수에 예상한 동영상 프레임 수를 더한 값과 같습니다.

  • 데이터셋 헤더에 Ready이 표시되거나, 충족되지 않은 조건이 무엇인지 정확히 적어 두었습니다.

정답 보기

의료용 알약 데이터셋과 4분 길이의 라인 카메라 동영상을 사용한 정답 예시입니다. 업로드 전 확인 결과: train 이미지 92개, val 이미지 23개이며 모두 레이블이 있고 문제는 없습니다. 동영상은 240초로 100초를 초과하므로 간격이 ceil(240 / 100) = 3초로 늘어나고 Platform은 80프레임을 유지합니다(0초, 3초, …, 237초에 하나씩). 예상 갤러리 이미지 수: 92 + 23 + 80 = 195개입니다. 동영상 프레임에는 레이블이 지정되지 않은 채 갤러리 필터에서 선택한 분할로 들어오므로, val에 포함되지 않도록 동영상을 놓기 전에 Train을 선택하세요. train, val, 레이블이 지정된 이미지가 모두 있으므로 배지에는 Ready이 표시됩니다. 동영상만 업로드했다면 레이블이 지정된 이미지가 아직 없으므로 배지에 Not Ready이 표시됩니다.

다음 단계

다음 단계에서는 모델로 이미지에 사전 레이블을 지정하고, 신뢰도 임계값별 검수 작업량을 측정합니다.