04. 합성 데이터 생성 (Replicator)
omni.replicator.core는 Isaac Sim의 합성 데이터 생성(SDG) 엔진이다. 카메라에 붙은 render_product를 BasicWriter에 연결하고 어떤 annotator를 켤지 플래그로만 지정하면 orchestrator.step() 한 번에 모든 채널을 동시에 라벨링한다.
이 기능의 강점
- RGB ↔ 라벨 채널이 모두 같은 픽셀 좌표계 — 후처리 정렬 불필요
- Tight / Loose 2D bbox, 3D bbox, instance / semantic seg, depth, normal, motion vector 모두 빌트인
SemanticLabel스키마로 USD prim에 클래스를 박아두면 자동 추출- Writer 백엔드 교체 가능 — 디스크 / Cosmos / 사용자 정의 backend
구현 방법
1) 라벨링할 prim에 rep.functional.modify.semantics(prim, {"class": name}, mode="add"). 2) BasicWriter.initialize(rgb=True, bounding_box_2d_tight=True, ...). 3) orchestrator.step().
최소 데모
검증 결과
오버레이 PNG에 세 큐브가 정확한 bbox + class label과 함께 표시됨.
핵심 코드 발췌
import omni.replicator.core as rep
cube = rep.functional.create.cube(parent="/World", name="red_box")
rep.functional.modify.semantics(cube, {"class": "red_box"}, mode="add")
cam = rep.functional.create.camera(position=(3,-3,2.5), look_at=(0,0,0.5))
rp = rep.create.render_product(cam, (1280, 720))
backend = rep.backends.get("DiskBackend"); backend.initialize(output_dir=OUT)
writer = rep.writers.get("BasicWriter")
writer.initialize(backend=backend, rgb=True, bounding_box_2d_tight=True)
writer.attach(rp)
rep.orchestrator.step()
코드 다운로드 (zip)
실무 예제 — Warehouse 환경 + YCB 5종 + 랜덤 카메라로 12장 데이터셋
Simple_Warehouse 환경에 YCB 데이터셋 5종 (cracker_box, soup_can, mustard_bottle, sugar_box, banana)을 배치하고, Replicator trigger.on_frame으로 카메라 위치를 매 프레임 균일 분포에서 샘플링해 12장 RGB + bbox + segmentation 데이터셋을 자동 생성. 실제 "창고 물체 인식" 학습 데이터 파이프라인 그대로.
한 번의 orchestrator.step() N번 호출로 같은 카메라 좌표계 정렬된 RGB · bbox · segmentation 3채널이 12쌍 출력. SemanticLabel로 박은 클래스명이 그대로 bbox label JSON에 떨어진다.
실무 데모 코드
ycb = [("003_cracker_box","cracker_box"), ("005_tomato_soup_can","soup_can"),
("006_mustard_bottle","mustard"), ("004_sugar_box","sugar_box"),
("011_banana","banana")]
for usd_name, cls in ycb:
p = add_reference_to_stage(assets+f"/Isaac/Props/YCB/Axis_Aligned/{usd_name}.usd",
f"/World/{cls}")
rep.functional.modify.semantics(p, {"class": cls}, mode="add")
with rep.new_layer():
cam = rep.functional.create.camera(...)
with rep.trigger.on_frame(num_frames=12):
with rep.get.prim_at_path("/World/Cam"):
rep.modify.pose(
position=rep.distribution.uniform((1.0,-1.8,0.9),(1.8,-1.2,1.5)),
look_at="/World/cracker_box")
writer.initialize(backend=backend, rgb=True,
bounding_box_2d_tight=True,
semantic_segmentation=True)
실무 데모 코드 zip