YOLO Vision 2026:

Ultralytics YOLO26의 엔드투엔드(End-to-End) 탐지 이해하기#

YOLOv8 또는 YOLO11과 같은 이전 모델에서 YOLO26으로 업그레이드하는 경우, 가장 크게 체감할 수 있는 변화 중 하나는 Non-Maximum Suppression(NMS)이 제거되었다는 점입니다. 기존의 YOLO 모델들은 수천 개의 겹치는 예측을 생성하며, 최종 감지 결과만 남기기 위해 별도의 NMS 후처리가 필요했습니다. 이는 지연 시간을 증가시키고, 내보내기 그래프를 복잡하게 만들며, 다양한 하드웨어 플랫폼에서 일관되지 않은 동작을 유발할 수 있습니다.

YOLO26은 다른 접근 방식을 취합니다. 외부 필터링 없이 모델에서 직접 최종 검출 결과를 출력합니다. 이를 **엔드투엔드 객체 검출**이라고 하며, 모든 YOLO26 모델에서 기본적으로 활성화되어 있습니다. 그 결과 더 간단한 배포 파이프라인, 더 낮은 지연 시간, 그리고 CPU에서 최대 43% 더 빠른 추론 속도를 제공합니다.

이 가이드에서는 변경된 내용, 코드 업데이트 필요 여부, 엔드투엔드 추론을 지원하는 내보내기 형식, 그리고 이전 YOLO 모델에서 원활하게 마이그레이션하는 방법을 안내합니다.

이러한 아키텍처 전환의 배경에 대한 자세한 내용은 YOLO26이 NMS를 제거한 이유에 관한 Ultralytics 블로그 게시물을 참조하세요.

간략 요약
  • Ultralytics API 또는 CLI를 사용하고 계신가요? 변경 사항이 필요하지 않습니다. 모델 이름을 yolo26n.pt(으)로 변경하기만 하면 됩니다.
  • 사용자 정의 추론 코드(ONNX Runtime, TensorRT 등)를 사용하고 계신가요? 후처리를 업데이트하세요. 이제 감지 출력은 NMS가 필요 없는 xyxy 형식의 (N, 300, 6)입니다. 기타 작업의 경우 추가 데이터(마스크 계수, 키포인트 또는 각도)가 뒤에 붙습니다.
  • 내보내기를 진행하시나요? 대부분의 형식은 엔드투엔드 출력을 기본적으로 지원합니다. 그러나 일부 형식(NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU, QNN)은 지원되지 않는 연산자 제약(예: torch.topk)으로 인해 전통적인 출력으로 자동으로 대체됩니다. Hailo HEF 워크플로우는 Hailo 전용 스크립트와 함께 ONNX에서 컴파일되므로, 모델에 맞는 검출 헤드와 NMS 구성을 확인하세요.

엔드투엔드 탐지의 작동 방식#

YOLO26은 학습 중에 듀얼 헤드 아키텍처를 사용합니다. 두 헤드 모두 동일한 백본과 넥을 공유하지만, 서로 다른 방식으로 출력을 생성합니다.

헤드목적탐지 출력후처리
One-to-One (기본값)엔드투엔드 추론(N, 300, 6)신뢰도 임계값만 적용
One-to-Many기존 YOLO 출력(N, nc + 4, 8400)NMS 필요

위의 형태는 검출을 위한 것입니다. 다른 태스크에서는 1대1 출력에 검출당 추가 데이터를 확장합니다.

작업엔드투엔드 출력추가 데이터
탐지(N, 300, 6)
인스턴스 세그멘테이션(N, 300, 6 + nm) + 프로토 (N, nm, H, W)nm 마스크 계수(기본값 32)
Pose(N, 300, 57)17개 키포인트 × 3 (x, y, 가시성)
OBB(N, 300, 7)회전 각도

학습 중에는 두 헤드가 동시에 실행됩니다. 1대다 헤드는 더 풍부한 학습 신호를 제공하고, 1대1 헤드는 깔끔하고 겹치지 않는 예측을 생성하는 법을 학습합니다. 추론내보내기 중에는 기본적으로 1대1 헤드만 활성화되어 이미지당 최대 300개의 검출 결과를 [x1, y1, x2, y2, confidence, class_id] 형식으로 생성합니다.

model.fuse()을(를) 호출하면 더 빠른 추론을 위해 Conv + BatchNorm 레이어가 병합되며, 엔드투엔드 모델의 경우 1대다 헤드도 제거되어 모델 크기와 FLOP가 감소합니다. 듀얼 헤드 아키텍처에 대한 자세한 내용은 YOLO26 모델 페이지를 참조하세요.

코드를 변경해야 합니까?#

Ultralytics Python API 또는 CLI 사용#

변경 사항이 필요하지 않습니다. 표준 Ultralytics Python API 또는 CLI를 사용하는 경우 예측, 검증, 내보내기 모두 엔드투엔드 모델을 기본적으로 지원하므로 모든 것이 자동으로 작동합니다.

Ultralytics API 사용 시 코드 변경 불필요
from ultralytics import YOLO

# Load a YOLO26 model
model = YOLO("yolo26n.pt")

# Predict — no NMS step, no code changes
results = model.predict("image.jpg")

사용자 정의 추론 코드 사용#

네, 출력 형식이 다릅니다. YOLOv8 또는 YOLO11용 사용자 정의 후처리 로직을 작성한 경우(ONNX Runtime 또는 TensorRT로 추론을 실행할 때 등), 새로운 출력 형태를 처리하도록 업데이트해야 합니다.

YOLOv8 / YOLO11YOLO26 (엔드투엔드)
탐지 출력(N, nc + 4, 8400)(N, 300, 6)
박스 형식xywh (중심 x, 중심 y, 너비, 높이)xyxy (좌측 상단 x, 좌측 상단 y, 우측 하단 x, 우측 하단 y)
레이아웃앵커당 박스 좌표 + 클래스 점수[x1, y1, x2, y2, conf, class_id]
NMS 필요아니요
후처리NMS + 신뢰도 필터신뢰도 필터만 적용

세그멘테이션, 포즈, OBB 태스크의 경우, YOLO26은 각 검출에 태스크별 데이터를 추가합니다. 출력 형태 표를 참조하세요.

여기서 N배치 크기이고, nc는 클래스 수입니다(예: COCO의 경우 80).

엔드투엔드 모델을 사용하면 후처리가 훨씬 간단해집니다(예: ONNX Runtime을 사용할 때).

import onnxruntime as ort

# Load and run the exported end-to-end model
session = ort.InferenceSession("yolo26n.onnx")
output = session.run(None, {session.get_inputs()[0].name: input_tensor})

# End-to-end output: (batch, 300, 6) → [x1, y1, x2, y2, confidence, class_id]
detections = output[0][0]  # first image in batch
detections = detections[detections[:, 4] > conf_threshold]  # confidence filter — that's it!

One-to-Many 헤드로 전환#

기존 YOLO 출력 형식이 필요한 경우(예: 기존의 NMS 기반 후처리 코드를 재사용하기 위해), end2end=False을(를) 설정하여 사용 가능한 경우 1대다 헤드로 전환할 수 있습니다.

기존의 NMS 기반 출력을 위해 One-to-Many 헤드 사용
from ultralytics import YOLO

model = YOLO("yolo26n.pt")

# Prediction with NMS (traditional behavior)
results = model.predict("image.jpg", end2end=False)

# Validation with NMS
metrics = model.val(data="coco.yaml", end2end=False)

# Export without end-to-end
model.export(format="onnx", end2end=False)

내보내기 형식 호환성#

대부분의 내보내기 형식ONNX, TensorRT, CoreML, OpenVINO, LiteRT, MNN을 포함하여 엔드투엔드 추론을 기본적으로 지원합니다.

다음 형식은 엔드투엔드를 지원하지 않으며 자동으로 1대다 헤드로 대체됩니다: NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU, Qualcomm QNN.

엔드투엔드가 지원되지 않을 때 발생하는 현상

이러한 형식 중 하나로 내보내면 Ultralytics가 자동으로 1대다 헤드로 전환하고 경고를 기록하므로 수동으로 개입할 필요가 없습니다. 즉, YOLOv8이나 YOLO11과 마찬가지로 이러한 형식에는 추론 파이프라인에 NMS가 필요합니다.

Hailo HEF의 경우, 컴파일 단계는 ONNX 내보내기 후 model.export(format=...) 외부에서 발생합니다. 정확한 검출 모델과 일치하는 Hailo DFC 로그, .alls 모델 스크립트, NMS JSON을 사용하세요. 엔드투엔드 YOLO26 그래프가 Hailo 툴체인에서 지원되지 않는 경우, end2end=False(으)로 ONNX 모델을 내보내고 전통적인 검출 헤드를 컴파일하세요.

TensorRT + INT8

TensorRT는 엔드투엔드를 지원하지만, JetPack 6의 TensorRT 10.3.0에서 quantize=8(으)로 내보낼 때는 자동으로 비활성화됩니다.

정확도와 속도 간의 트레이드오프#

엔드투엔드 검출은 정확도에 미치는 영향이 최소화되면서도 상당한 배포 이점을 제공합니다.

지표엔드투엔드 (기본값)1대다 + NMS (end2end=False)
CPU 추론 속도최대 43% 빠름기준값
mAP 영향~0.5 mAP 낮음YOLO11과 동등하거나 우수
후처리신뢰도 필터만 적용전체 NMS 파이프라인
배포 복잡성최소화NMS 구현 필요

대부분의 실제 애플리케이션에서 ~0.5의 mAP 차이는 속도와 단순성 향상과 비교할 때 무시할 수 있는 수준입니다. 최고 정확도가 최우선 과제인 경우, 언제든지 end2end=False을(를) 사용하여 1대다 헤드로 대체할 수 있습니다.

모든 모델 크기(n, s, m, l, x)에 대한 자세한 벤치마크는 YOLO26 성능 지표를 참조하세요.

YOLOv8 또는 YOLO11에서 마이그레이션하기#

기존 프로젝트를 YOLO26으로 업그레이드하는 경우, 원활한 전환을 위한 빠른 체크리스트는 다음과 같습니다:

  • Ultralytics API / CLI 사용자: 변경 사항이 없습니다. 모델 이름을 yolo26n.pt(또는 yolo26n-seg.pt, yolo26n-pose.pt, yolo26n-obb.pt)으로 업데이트하기만 하면 됩니다.
  • 사용자 정의 후처리 코드: 새로운 출력 형태를 처리하도록 업데이트하세요. 검출의 경우 (N, 300, 6), 세그멘테이션, 포즈, OBB에 대한 태스크별 데이터가 포함됩니다. 또한 박스 형식 변경 사항을 xywh에서 xyxy(으)로 확인하세요.
  • 내보내기 파이프라인: 대상 형식에 대한 형식 호환성 섹션을 확인하세요.
  • TensorRT + INT8: JetPack 6에서 TensorRT 10.3.0은 quantize=8을(를) 사용할 때 엔드투엔드를 자동으로 비활성화합니다. 엔드투엔드를 유지하려면 다른 TensorRT 버전을 사용하세요.
  • FP16 내보내기: 모든 출력이 FP16 형식이어야 하는 경우 end2end=False(으)로 내보내세요. output0이 FP32로 유지되는 이유를 참조하세요.
  • iOS / CoreML: 엔드투엔드가 완벽하게 지원됩니다. Xcode Preview 지원이 필요한 경우 nms=True과 함께 end2end=False을 사용하세요.
  • 엣지 기기(NCNN, RKNN): 이러한 형식은 자동으로 One-to-Many로 돌아가므로, 온디바이스 파이프라인에 NMS를 포함하십시오.

결론#

엔드투엔드 검출은 YOLO26의 기본값이며 Ultralytics Python API 또는 CLI를 사용하는 경우 코드 변경이 필요하지 않습니다. 새로운 (N, 300, 6) 출력을 읽고 NMS 단계를 제거하도록 사용자 정의 후처리 파이프라인만 업데이트하면 됩니다. 단, 1대다 출력으로 대체되는 내보내기 형식(예: NCNN 및 RKNN)은 온디바이스에서 여전히 NMS가 필요합니다. 모든 모델 크기에 대한 자세한 속도 및 정확도 벤치마크는 YOLO26 모델 페이지를 참조하고, 전체 내보내기 옵션 및 형식 세트는 Export 모드 설명서를 참조하세요.

FAQ#

end2end=True와 nms=True를 함께 사용할 수 있나요?#

아니요. 이 옵션들은 상호 배타적입니다. export 과정에서 엔드투엔드 모델에 nms=True을 설정하면, 경고와 함께 자동으로 nms=False(으)로 강제 설정됩니다. 엔드투엔드 헤드가 내부적으로 중복 필터링을 이미 처리하므로 외부 NMS는 필요하지 않습니다.

그러나 end2end=False과(와) nms=True의 조합은 유효한 구성으로, 전통적인 NMS를 내보내기 그래프에 포함합니다. 이는 검출 모델과 함께 Xcode의 미리보기(Preview) 기능을 직접 사용할 수 있게 해주므로 CoreML 내보내기에 유용할 수 있습니다.

엔드투엔드 모델에서 max_det 파라미터는 무엇을 제어합니까?#

max_det 매개변수(기본값: 300)는 이미지당 반환되는 최대 검출 수를 설정합니다. 추론 또는 내보내기 시점에 조정할 수 있습니다.

model.predict("image.jpg", max_det=100)  # fewer detections
model.export(format="onnx", max_det=500)  # more detections for dense scenes

기본 YOLO26 체크포인트는 max_det=300을(를) 사용하여 학습되었습니다. 이 값을 늘릴 수는 있지만, 1대1 헤드는 최대 300개의 깔끔한 검출을 생성하도록 학습 중에 최적화되었으므로 그 제한을 초과하는 검출은 품질이 낮을 수 있습니다. 이미지당 300개 이상의 검출이 필요한 경우 더 높은 max_det 값으로 재학습하는 것을 고려해 보세요.

내보낸 ONNX 모델 출력이 (1, 300, 6)인데, 이것이 맞습니까?#

네, 그것이 검출에 예상되는 엔드투엔드 출력 형식입니다: 배치 크기 1, 최대 300개의 검출 결과, 각각 6개의 값([x1, y1, x2, y2, confidence, class_id]). 신뢰도 임계값으로 필터링하기만 하면 완료됩니다. NMS가 필요하지 않습니다.

다른 작업의 경우 출력 형태가 다릅니다:

작업출력 형태설명
탐지(1, 300, 6)[x1, y1, x2, y2, conf, class_id]
세그멘테이션(1, 300, 38) + (1, 32, 160, 160)6개의 박스 값 + 32개의 마스크 계수, 그리고 프로토타입 마스크 텐서
포즈(Pose)(1, 300, 57)6개의 박스 값 + 17개의 키포인트 × 3 (x, y, 가시성)
OBB(방향성 경계 상자)(1, 300, 7)6개의 박스 값 + 1개의 회전 각도

내보낸 모델이 엔드투엔드 모델인지 어떻게 확인합니까?#

Ultralytics Python API를 사용하거나 내보낸 ONNX 모델 메타데이터를 직접 검사하여 확인할 수 있습니다:

모델이 엔드투엔드인지 확인
from ultralytics import YOLO

model = YOLO("yolo26n.onnx")
model.predict(verbose=False)  # run predict to setup predictor first
print(model.predictor.model.end2end)  # True if end-to-end is enabled

또는 출력 형태를 확인하세요. 엔드투엔드 검출 모델은 (1, 300, 6)을(를) 출력하고, 전통적인 모델은 (1, nc + 4, 8400)을(를) 출력합니다. 다른 태스크 형태에 대해서는 출력 형태 FAQ를 참조하세요.

인스턴스 세그멘테이션, 포즈, OBB 작업에서 엔드투엔드가 지원됩니까?#

네. YOLO26 검출 스타일 태스크 변형(검출, 인스턴스 세그멘테이션, 포즈 추정, 지향성 객체 검출(OBB))은 기본적으로 엔드투엔드 추론을 지원합니다. end2end=False 대체 기능도 이러한 태스크에서 사용할 수 있습니다.

각 작업은 기본 탐지 출력에 작업별 데이터를 추가하여 확장합니다:

작업모델엔드투엔드 출력
탐지yolo26n.pt(N, 300, 6)
인스턴스 세그멘테이션yolo26n-seg.pt(N, 300, 38) + 프로토 (N, 32, 160, 160)
포즈(Pose)yolo26n-pose.pt(N, 300, 57)
OBB(방향성 경계 상자)yolo26n-obb.pt(N, 300, 7)

댓글