본문으로 건너뛰기

노드

Node는 SiMa.ai Neat에서 가장 작은 구성 단위입니다. 노드는 Graph가 연결하는 요소입니다. 여기에는 디코딩 단계, 전처리 단계, 모델 단계, 후처리 단계, 소스, 싱크, 애플리케이션 경계 등이 포함됩니다.

참조:

노드가 나타내는 것​

노드는 하나의 논리적 작업과 빌더가 안전하게 연결하는 데 필요한 메타데이터를 제공합니다.

  • 런타임 작업(예: 디코딩, 변환, 전처리, 추론, 후처리 또는 싱크 동작)
  • 입력/출력 계약(예: 예상되는 미디어 유형, 텐서 모양, dtype 또는 캡)
  • 결정론적 백엔드 명명 규칙을 통해 describe(), 진단, 메트릭 및 프로브가 안정적으로 유지됩니다.

주요 규칙은 간단합니다.

Graph = nodes wired together

Model은 모델을 인식하는 노드 소스입니다. Model은 Graph에 직접 추가하거나, 전처리, 추론, 후처리 등과 같이 재사용 가능한 스테이지 조각을 제공할 수 있습니다.

미리 만들어진 노드 그룹​

일반적으로 사용되는 일부 패턴은 여러 개의 하위 수준 노드로 구성됩니다. Neat은 이러한 노드들을 미리 만들어진 그룹으로 제공하여 사용자가 모든 소스, 디코더, 변환기, 큐 또는 싱크를 수동으로 연결할 필요가 없도록 합니다.

그룹은 재사용 가능한 작은 그래프로 생각할 수 있습니다. 즉, 명확한 인터페이스를 가진 이름이 지정된 노드들의 묶음입니다.

예시:

  • VideoInputGroup(...): 파일/비디오 소스 + 디코딩 경로.
  • RtspDecodedInput(...): RTSP 소스 + 디코딩 경로.
  • 모델 라우트 조각: 전처리 + 추론 + 컴파일된 모델을 중심으로 하는 디코딩/후처리.
#include "neat/runtime.h"
#include "neat/node_groups.h"

simaai::neat::Graph graph;

simaai::neat::nodes::groups::VideoInputGroupOptions vopt;
vopt.path = "/data/sample.mp4";
graph.add(simaai::neat::nodes::groups::VideoInputGroup(vopt));

표준 형식을 사용하고 앱의 흥미로운 부분이 내부 미디어 파이프라인이 아닌 경우 미리 빌드된 그룹을 사용하세요. 사용자 지정 토폴로지가 필요한 경우 하위 수준 노드에서 해당 Graph를 직접 구축하세요.

노드 또는 그룹 선택​

전체 API 참조를 열기 전에 이 지도를 사용하세요.

작업C++ 시작점Python 시작점
앱이 텐서, 이미지 또는 샘플을 푸시nodes::Input("name", options)pyneat.nodes.input("name", options)
앱이 전체 샘플을 가져옴nodes::Output("name", options)pyneat.nodes.output("name", options)
파일에서 프레임 읽기nodes::FileInput(...) 더하기 디코딩 노드, 또는 nodes::groups::VideoInputGroup(...)pyneat.nodes.file_input(...) 더하기 디코딩 노드, 또는 pyneat.groups.video_input(...)
소스로 단일 이미지 읽기nodes::StillImageInput(...)pyneat.nodes.still_image_input(...)
MIPI/libcamera 카메라 읽기nodes::CameraInput(...)pyneat.nodes.camera_input(...)
USB(UVC) MJPEG 카메라 읽기nodes::UsbCameraInput(...)pyneat.nodes.usb_camera_input(...)
RTSP 스트림 읽기nodes::RTSPInput(...), nodes::groups::RtspEncodedInput(...), 또는 nodes::groups::RtspDecodedInput(...)pyneat.nodes.rtsp_input(...), pyneat.groups.rtsp_encoded_input(...), 또는 pyneat.groups.rtsp_decoded_input(...)
HTTP 멀티파트 MJPEG 읽기nodes::groups::HttpMjpegDecodedInput(...), 또는 nodes::HttpSource(...), MultipartJpegDemux(), JpegParse() (수동 프레임 구성)pyneat.groups.http_mjpeg_decoded_input(...), 또는 pyneat.nodes.http_source(...), pyneat.nodes.multipart_jpeg_demux(), pyneat.nodes.jpeg_parse()
이미지 디코딩nodes::ImageDecode() 또는 nodes::JpegDecode()pyneat.nodes.image_decode() 또는 pyneat.nodes.jpeg_decode()
원시 비디오 인코딩nodes::SimaEncode(SimaEncodeOptions{...})pyneat.nodes.sima_encode(options)
인코딩된 비디오 디코딩nodes::SimaDecode(SimaDecodeOptions{...})pyneat.nodes.sima_decode(options)
MJPEG 카메라 프레임 디코딩 (4:2:0 또는 4:2:2)usb_camera_info(...).decoded_format을 nodes::SimaDecode(...)의 out_format으로 사용, 모델 입력 형식을 같게 설정pyneat.usb_camera_info(...).decoded_format을 pyneat.nodes.sima_decode(...)의 out_format으로 사용, 모델 입력 형식을 같게 설정
비디오 크기 조정 또는 속도 제한nodes::VideoScale(), VideoRate(), ImageFreeze()pyneat.nodes.video_scale(), video_rate(), image_freeze()
재사용 가능한 이미지 입력 경로 구축nodes::groups::ImageInputGroup(...)pyneat.groups.image_input(...)
재사용 가능한 비디오 입력 경로 구축nodes::groups::VideoInputGroup(...)pyneat.groups.video_input(...)
비디오 출력nodes::groups::VideoSender(...) 또는 H.264/UDP 출력 도우미pyneat.groups.video_sender(...) 또는 H.264/UDP 출력 도우미
메타데이터 출력MetadataSenderpyneat.MetadataSender
감지 결과 렌더링nodes::SimaRender(...)pyneat.nodes.sima_render(...)
로짓을 클래스 인덱스로 변환nodes::SimaArgMax(...)pyneat.nodes.sima_argmax(...)
LiDAR 스윕을 필러로 복셀화nodes::SimaVoxelize(SimaVoxelizeOptions{...})pyneat.nodes.sima_voxelize(options)
필러 특징을 BEV 캔버스에 분산nodes::SimaPillarScatter(SimaPillarScatterOptions{...})pyneat.nodes.sima_pillar_scatter(options)
카메라 특징을 BEV 격자로 풀링nodes::SimaBEVPoolPlan(...) 및 nodes::SimaBEVPool(...)pyneat.nodes.sima_bev_pool_plan(options) 및 pyneat.nodes.sima_bev_pool(options)

테스트된 조각을 원할 때 그룹을 사용하고, 명시적인 토폴로지가 필요할 때 개별 노드를 사용하세요. 중복된 출력을 통해 토폴로지를 숨기는 대신 Graph와 같은 도우미(예: graphs::Branch(...) 및 graphs::Combine(...))를 사용하여 팬아웃 및 팬인을 수행하세요.

nodes::H264Decode(...) 및 pyneat.nodes.h264_decode(...)는 더 이상 사용되지 않는 호환성 래퍼입니다. 새로운 H.264 디코딩 그래프는 SimaDecode와 SimaDecodeType::H264를 사용해야 합니다.

인코딩된 디코딩 경로​

그래프에 제공되는 입력에 따라 API를 선택하세요.

그래프에 제공되는 입력API출력
완전하고 파싱된 인코딩된 액세스 단위SimaDecode(...)원시 디코딩된 비디오
인코딩된 상태를 유지해야 하는 RTSP 스트림RtspEncodedInput(...)파싱된 인코딩된 액세스 단위
디코딩해야 하는 RTSP 스트림RtspDecodedInput(...)원시 디코딩된 비디오

SimaDecode는 RTSP에 연결하거나, RTP을 디패킷화하거나, 기본 스트림을 파싱하지 않습니다. 상위 단계 또는 애플리케이션이 이미 완전한 인코딩된 샘플을 제공하는 경우에 사용하세요.

인코딩된 입력기본 디코더 옵션일반적인 상위 경로
H.264/AVC 액세스 단위SimaDecodeType::H264 또는 SimaDecodeType::AVCRTSP H.264 디패킷화 + 파싱, 또는 다른 파싱된 H.264 소스
H.265/HEVC 액세스 단위SimaDecodeType::H265 또는 SimaDecodeType::HEVCRTSP H.265 디패킷화 + 파싱, 또는 다른 파싱된 H.265 소스
단일 JPEG 프레임SimaDecodeType::JPEGJpegParse() 또는 애플리케이션에서 제공하는 인코딩된 JPEG 샘플
MJPEG 프레임 스트림SimaDecodeType::MJPEGHTTP 멀티파트 디멀티플렉스 + JpegParse(), 또는 RTSP JPEG 디패킷화 + JpegParse()

별칭은 동일한 디코더 경로를 선택합니다. H264는 AVC와 같고, H265는 HEVC와 같습니다. 동일한 별칭은 C++ 및 Python에서 RtspCodec 및 FormatTag를 통해 사용할 수 있습니다.

H.264 입력은 8비트, 4:2:0 크로마와 프로그레시브 프레임을 사용해야 합니다. High 10, High 4:2:2 및 인터레이스 비트스트림은 지원되지 않습니다.

H.265 입력은 8비트, 4:2:0 크로마를 사용하는 HEVC Main 프로필을 사용해야 합니다. 직접 기본 스트림 입력은 파싱되고, Annex-B 바이트 스트림이며, 액세스 단위가 정렬되어야 합니다. 해당 매개변수 세트(VPS, SPS 및 PPS)는 해당 매개변수에 의존하는 프레임이 도달하기 전에 디코더에 도달해야 합니다. RtspEncodedInput는 RTSP 경로에 대한 RTP 디패킷화 및 H.265 파싱을 처리합니다. Main 10, 10비트, 4:2:2 및 모노크롬 4:0:0 비트스트림은 지원되지 않습니다. 회색조 콘텐츠의 경우, Y 평면에 회색조 이미지가 포함되고 U 및 V 샘플은 중립 값 128을 사용하는 8비트 4:2:0 스트림을 인코딩하세요.

사용하기 전에 스트림을 확인하세요.

ffprobe -v error -rtsp_transport tcp -select_streams v:0 \
-show_entries stream=codec_name,profile,pix_fmt \
-of default=noprint_wrappers=1 rtsp://camera.example/live

H.265 디코더는 codec_name=hevc, profile=Main 및 pix_fmt=yuv420p를 필요로 합니다.

SimaDecodeOptions::raw_output은 디코더의 즉각적인 출력을 제어합니다.

값디코더 출력
true (기본값)디코더 출력 버퍼입니다. 기본적으로 네이티브 NV12이며 I420을 선택하면 변환됩니다.
falseCPU 소비자를 위한 변환된 video/x-raw(memory:SystemMemory) 출력입니다.

SimaDecode는 NV12에 대해 제로카피 디코더 출력을 요청합니다. I420을 선택하면 복사 모드가 하드웨어의 NV12 픽셀을 최종 I420 평면으로 직접 변환합니다. 두 모드 모두 디코더의 DMA-BUF 출력 풀을 사용합니다. raw_output=false는 시스템 메모리 출력을 위한 소프트웨어 어댑터를 추가합니다. RunOptions::output_memory는 최종 출력이 기존 버퍼를 공유할지(ZeroCopy), 프레임워크 소유 메모리로 복사할지(Owned) 별도로 제어합니다.

디코더 플러그인이 하드웨어 세션을 소유합니다. Core는 승인 데몬을 통해 용량을 예약하거나 디코더 임대를 유지하지 않습니다. 시작 실패는 일반 파이프라인 오류 경로로 보고됩니다.

상위 입력의 크기나 프레임 속도를 재정의해야 할 때만 dec_width, dec_height, dec_fps를 사용합니다. -1은 상위 입력의 값을 유지합니다. 이 옵션은 디코더 용량을 예약하지 않습니다. Core는 명시적인 num_buffers 값을 디코더로 전달하며 디코더가 하드웨어 풀 요구사항을 적용합니다. -1은 디코더 정책을 유지합니다.

플러그인 기본값을 유지하려면 decoder_tuning을 비워 둡니다. default, auto를 포함한 명시적 값은 memory_opt와 버퍼 수 재정의와 함께 플러그인에 전달되어 디코더가 튜닝 우선순위를 적용합니다. throughput-low-latency는 디코딩된 프레임의 표시 순서 재정렬을 비활성화하고 720p 이하에서는 명령 깊이 1, 더 큰 프레임에서는 2를 사용합니다. B 프레임 없이 인코딩된 스트림에만 사용하고 일반 스트림은 튜닝을 설정하지 않습니다.

nodes::JpegDecode() 및 pyneat.nodes.jpeg_decode()는 별도의 CPU/GStreamer JPEG 디코딩 노드입니다. 간단한 CPU 이미지 파이프라인에 사용합니다. 모델 전처리기 전에 기본 MJPEG 비디오 디코딩에는 사용하지 마십시오.

RTSP의 경우 소스 형식이 표준일 때 코덱을 인식하는 그룹을 사용하는 것이 좋습니다. H.264는 기본값으로 유지됩니다. H.265 또는 HEVC를 명시적으로 선택합니다.

MJPEG 카메라 디코딩​

USB 카메라는 4:2:0 또는 4:2:2 색 샘플링으로 MJPEG를 보내며, 대부분은 4:2:2를 사용합니다. 제로 카피 출력에서는 디코더가 스트림 고유의 샘플링으로만 쓸 수 있으므로, 그래프를 빌드하기 전에 이를 알아야 합니다. USB 카메라의 경우 usb_camera_info(...)가 이를 decoded_format으로 알려 주므로, 그 값을 디코더의 out_format으로 사용하세요. 다른 MJPEG 소스에서는 4:2:0이면 NV12, 4:2:2이면 NV16으로 out_format을 설정하세요. 모델은 NV16을 직접 읽습니다. 모델의 전처리 입력 형식을 같은 값으로 설정하면 4:2:2 프레임이 변환 단계 없이 모델에 전달됩니다.

#include "neat.h"

// camera: your UsbCameraInputOptions; also pass info to UsbCameraInput(camera, info).
const simaai::neat::UsbCameraInfo info = simaai::neat::usb_camera_info(camera);
simaai::neat::SimaDecodeOptions decode;
decode.type = simaai::neat::SimaDecodeType::MJPEG;
decode.out_format = info.decoded_format; // NV12 or NV16
decode.dec_width = 1920;
decode.dec_height = 1080;
decode.dec_fps = 30;
decode.raw_output = true; // zero-copy: the decoder writes the camera's own sampling
graph.add(simaai::neat::nodes::JpegParse());
graph.add(simaai::neat::nodes::SimaDecode(decode));

simaai::neat::Model::Options model_options;
model_options.preprocess.color_convert.input_format =
decode.out_format == simaai::neat::FormatTag::NV16 ? simaai::neat::PreprocessColorFormat::NV16
: simaai::neat::PreprocessColorFormat::NV12;

HttpMjpegDecodedInput(...)와 RtspDecodedInput(...)는 여전히 디코더에 NV12를 요청하므로 4:2:0 MJPEG 스트림만 지원합니다.

RTSP 입력을 인코딩된 상태로 유지​

RtspEncodedInput(...)을 사용하여 디코딩하지 않고 스트림을 디멀티플렉싱하고 구문 분석합니다.

simaai::neat::nodes::groups::RtspEncodedInputOptions encoded;
encoded.url = "rtsp://camera.example/live";
encoded.codec = simaai::neat::nodes::groups::RtspCodec::HEVC;
encoded.source_fps = 30;

auto encoded_graph =
simaai::neat::nodes::groups::RtspEncodedInput(encoded);

RtspEncodedInput(...)은 소스에서 패킷 분리 및 파싱/프레임 구성이 완료된 후 작동을 중단합니다. 앱에서 인코딩된 샘플이 필요한 경우, 예를 들어 파싱된 스트림 하나를 디코딩 및 비디오 출력 그래프로 분할하려는 경우에 사용합니다. H.265의 경우, 유효한 프레임 속도가 스트림에 표시되지 않으면 파싱된 인코딩된 캡에 source_fps가 기록됩니다.

RTSP 입력 디코딩​

SimaDecode(...)를 추가하고 원시 디코딩된 비디오를 반환하려면 RtspDecodedInput(...)를 사용합니다.

simaai::neat::nodes::groups::RtspDecodedInputOptions decoded;
decoded.url = "rtsp://camera.example/live";
decoded.codec = simaai::neat::nodes::groups::RtspCodec::H265;
decoded.source_fps = 30;

simaai::neat::Graph graph;
graph.add(simaai::neat::nodes::groups::RtspDecodedInput(decoded));
graph.add(simaai::neat::nodes::Output("frames"));

H.265의 경우 RtspDecodedInput(...)은 source_fps를 파싱된 caps와 디코더 dec-fps에 모두 사용합니다. RTSP caps에 유효한 프레임 속도가 없으면 설정해야 합니다. 둘 다 없으면 디코더 시작이 실패합니다. Neat는 RTSP URL을 탐색하여 이 값을 알아내지 않습니다. 이 값은 소스 주기를 선언하며 속도 변환을 요청하지 않습니다. 출력 주기를 바꾸려면 use_videorate를 활성화하고 video_rate_fps를 설정합니다. 속도 변환은 초과 프레임을 버리고 소스 타임스탬프를 유지합니다. nodes::VideoRate()와 pyneat.nodes.video_rate() 팩토리는 인수를 받지 않으며 소스 그룹에서 삽입할 때도 항상 drop-only=true를 사용합니다. 출력 속도를 높이기 위해 프레임을 복제하지 않습니다.

HTTP 멀티파트 MJPEG의 경우, HttpMjpegDecodedInput(...)을 사용하십시오. HTTP 멀티파트 MJPEG는 RTP가 아니므로 RTSP 디패킷화 대신 HttpSource -> MultipartJpegDemux -> JpegParse -> SimaDecode(MJPEG)를 사용합니다.

소스 소유 및 싱크 그룹​

그래프가 자체적으로 미디어를 읽도록 해야 하는 경우 소스 소유 그룹을 사용하십시오. 앱 입력 없이 해당 그래프를 구축한 다음 출력을 가져오거나 싱크 노드가 전송을 처리하도록 합니다. 그래프가 앱이 모든 프레임을 가져오지 않고 비디오를 전송해야 하는 경우 싱크 그룹을 사용하십시오. 싱크 그래프는 Input 경계가 있는 경우에도 앱에서 푸시할 수 있습니다.

필요그룹먼저 설정할 주요 필드일반적인 후속 필드
정지 이미지nodes::groups::ImageInputGroup(...) / pyneat.groups.image_input(...)pathfps, imagefreeze_num_buffers, output_caps
비디오 파일nodes::groups::VideoInputGroup(...) / pyneat.groups.video_input(...)pathout_format, output_caps, sync_mode
라이브 MIPI/libcamera 카메라nodes::CameraInput(...) / pyneat.nodes.camera_input(...)width, height, framerate_num, format; 선택 사항 camera_nameallow_cpu_fallback, 큐 필드, buffer_name
라이브 RTSP 인코딩된 H.264, H.265 또는 MJPEG 스트림nodes::groups::RtspEncodedInput(...) / pyneat.groups.rtsp_encoded_input(...)url, H.264가 아닌 경우 codecsource_fps, latency_ms, tcp, drop_on_latency, buffer_mode, RTP 페이로드 유형
라이브 RTSP 디코딩된 H.264, H.265 또는 MJPEG 스트림nodes::groups::RtspDecodedInput(...) / pyneat.groups.rtsp_decoded_input(...)url, H.264가 아닌 경우 codecsource_fps, latency_ms, tcp, drop_on_latency, buffer_mode, 디코딩된 너비/높이, out_format, output_caps
HTTP 멀티파트 MJPEG 스트림nodes::groups::HttpMjpegDecodedInput(...) / pyneat.groups.http_mjpeg_decoded_input(...)urlout_format, decoder_next_element, 디코딩된 너비/높이/FPS, output_caps
원시 또는 인코딩된 H.264/H.265/MJPEG 비디오 출력nodes::groups::VideoSender(...) / pyneat.groups.video_sender(...)VideoSenderOptions::FromRaw(encode_options) 또는 Passthrough(codec)host, channel, video_port_base, 인코더/RTP 옵션
RTP/H.264 over UDP 출력nodes::groups::UdpH264OutputGroup(...) / pyneat.groups.udp_h264_output_group(...)기본값이 올바르지 않은 경우 대상 호스트/포트h264_caps, payload_type, config_interval

소스 소유 그래프는 앱에서 푸시하는 그래프와 다른 런타임 구조입니다.

source group -> model -> output

MIPI 카메라의 경우, 앱에서 제공하는 Input으로 카메라를 감싸는 대신 CameraInput을 직접 사용하십시오. 먼저 libcamera/GStreamer를 사용하여 카메라를 검증한 다음, CameraInput -> model -> Output로 그래프를 구축하십시오. 전체 경로는 MIPI 카메라를 사용하세요.를 참조하십시오.

입력 인수를 사용하지 않고 graph.build() 또는 graph.run()을 사용하여 실행하십시오. 앱에 실제로 두 번째 공개 입력을 제공할 수 있는 경우가 아니라면 소스 그룹 앞에 Input("image")를 추가하지 마십시오.

simaai::neat::nodes::groups::RtspDecodedInputOptions source_options;
source_options.url = "rtsp://camera.example/live";

simaai::neat::Graph graph("rtsp_detector");
graph.add(simaai::neat::nodes::groups::RtspDecodedInput(source_options));
graph.add(model);
graph.add(simaai::neat::nodes::Output(
"detections",
simaai::neat::OutputOptions::Latest()));

auto run = graph.build();

미디어 연결 방식이 표준일 때는 그룹으로 시작합니다. 사용자 지정 토폴로지나 그룹에서 지원하지 않는 소스 형식이 필요한 경우에만 개별 노드로 전환합니다.

일반적인 SiMa 노드​

일부 SiMa 노드는 매우 일반적이어서 별도의 참고 자료 또는 사용 방법 페이지가 있습니다.

  • Preproc: 크기 조정, 색상 변환, 정규화, 양자화, 테셀레이션 및 런타임 ROI 목록을 위한 통합 CVU 이미지 전처리.
  • CameraInput: 소스에서 소유한 MIPI/libcamera 프레임으로, 후속 CVU/MLA 단계를 위해 적응형 SiMaAI 메모리 핸드오프를 수행합니다.
  • SimaBoxDecode: 모델 헤드를 바운딩 박스로 디코딩하고 상위 전처리 메타데이터를 사용하여 좌표 매핑을 수행하는 감지 후처리.

경계 노드: Input 및 Output​

Input 및 Output 역시 노드입니다. 이들은 특별한데, 그 이유는 그래프 조각 내에서 데이터가 들어오거나 나가는 지점을 설명하기 때문입니다.

중요한 개념 모델:

Input("name") 및 Output("name")은 이름이 지정된 게이트입니다.

최종 애플리케이션 외부에서는 이러한 게이트가 공개 런타임 API가 됩니다.

  • Input("image")는 run.push("image", ...)가 됩니다.
  • Output("classes")는 run.pull("classes", ...)가 됩니다.

더 큰 그래프 내에서는 동일한 게이트가 단순히 연결 지점일 뿐입니다. Neat은 실행 가능한 런타임 경로를 구축하는 동안 내부 경계 노드를 제거하고 실제 작업을 직접 연결합니다.

simaai::neat::Graph route("route");
route.add(simaai::neat::nodes::Input("image"));
route.add(model);
route.add(simaai::neat::nodes::Output("classes"));

완전한 앱으로 사용:

auto run = route.build();
run.push("image", simaai::neat::TensorList{image_tensor});
auto classes = run.pull("classes");

더 큰 애플리케이션 내에서 사용:

simaai::neat::Graph app("app");
app.connect(camera, route);
app.connect(route, telemetry);

개념적으로 내부 경계 노드는 배선을 안내하기 위해 더 낮은 위치로 이동합니다.

camera -> model -> telemetry

이러한 이름은 여전히 진단, 엔드포인트 검사, 메트릭 및 시각화를 위해 유지됩니다. 이 이름들은 앱 중간에 추가 큐, 복사본 또는 가짜 런타임 싱크를 생성하지 않습니다.

레이블은 엔드포인트가 아닙니다.​

다음 이름을 분리하여 사용하십시오.

이름설명push(...) / pull(...)를 생성합니까?
Graph("detector")진단, 내보내기 및 로그를 위한 그래프 레이블입니다.아니요.
nodes::Input("image") / pyneat.nodes.input("image")최종 그래프 외부에서 유지될 때의 공개 입력 경계입니다.예: run.push("image", ...).
nodes::Output("detections") / pyneat.nodes.output("detections")최종 그래프 외부에서 유지될 때의 공개 출력 경계입니다.예: run.pull("detections", ...).
노드 또는 요소 이름진단 및 파이프라인 최적화에 사용되는 백엔드 이름입니다.아니요. 단, Input 또는 Output 경계를 통해 노출되는 경우는 예외입니다.

런타임 호출에서 엔드포인트 이름을 알 수 없다고 표시되면 추측하는 대신 run.input_names() 및 run.output_names()를 검사하십시오. 이름은 저렴하지만, 잘못된 이름은 비용이 많이 듭니다.

앱에서 푸시하는 입력​

애플리케이션에 이미 프레임 또는 텐서가 있고 이를 Neat로 푸시하려는 경우 nodes::Input를 사용하십시오.

경계에 명시적인 페이로드, 형식, 크기, 타이밍 또는 할당 계약이 필요한 경우 InputOptions를 사용하십시오.

필요 사항필드
페이로드 패밀리payload_type / PayloadType
형식format / FormatTag
고정된 차원width, height, depth
동적 입력 제한max_width, max_height, max_depth, max_bytes
타이밍 및 제한fps_n, fps_d, caps_override
라이브 소스 동작is_live, do_timestamp, block, stream_type
할당memory_policy, pool_min_buffers, pool_max_buffers
고급 메타데이터buffer_name, preprocess_meta

use_simaai_pool은 더 이상 사용되지 않습니다. 새 코드에서는 memory_policy를 사용하십시오.

  • 기존 코드에서 use_simaai_pool=false를 사용한 경우 memory_policy=SystemMemory를 사용하십시오.
  • 기본 SiMa 할당 동작의 경우 memory_policy=Auto를 사용하십시오.
  • 입력 경계에 특정 대상이 필요한 경우에만 Ev74 또는 Dms0를 사용하십시오.
  • 기존 코드 및 이전 버전의 그래프 JSON에서 use_simaai_pool을 사용하는 것은 호환성을 위해 허용됩니다.
  • 새 그래프 JSON을 저장할 때 use_simaai_pool 대신 memory_policy를 기록합니다.

그래프 경계에 계약이 필요한 경우에만 필드를 설정하지 않은 상태로 두십시오. 제한을 추측하는 것은 문제를 야기할 수 있습니다.

simaai::neat::Graph graph;

simaai::neat::InputOptions iopt;
iopt.payload_type = simaai::neat::PayloadType::Image;
iopt.format = simaai::neat::FormatTag::RGB;
iopt.width = 224;
iopt.height = 224;
graph.add(simaai::neat::nodes::Input("image", iopt));

입력 경계 레시피​

첫 번째 푸시 전에 경계 계약이 중요한 경우 다음 패턴을 사용합니다.

경계설정다음 경우 설정하지 않음
고정 크기 디코딩된 이미지payload_type, format, width, height푸시된 텐서 또는 샘플에 이미 완전한 이미지 메타데이터가 포함되어 있음
동적 디코딩된 이미지payload_type, format, max_width, max_height 및 선택 사항인 max_bytes그래프는 하나의 고정 크기만 허용함
인코딩된 H.264 입력payload_type = Encoded, format = H264 및 푸시된 Sample에 대한 H.264 캡그래프 소스가 RTSP 또는 파일 그룹을 통해 스트림을 소유함
인코딩된 H.265 입력payload_type = Encoded, format = H265 및 푸시된 Sample에 대한 H.265 캡그래프 소스가 RTSP 또는 파일 그룹을 통해 스트림을 소유하고 파싱함
감지 좌표 매핑preprocess_meta모델 경로가 전처리를 수행하고 메타데이터 자체를 출력함

동적 이미지 입력의 경우, 모든 프레임이 동일한 크기를 갖는다고 가정하지 않고 스트림을 제한합니다.

simaai::neat::InputOptions iopt;
iopt.payload_type = simaai::neat::PayloadType::Image;
iopt.format = simaai::neat::FormatTag::BGR;
iopt.max_width = 1920;
iopt.max_height = 1080;
iopt.max_bytes = 1920 * 1080 * 3;

graph.add(simaai::neat::nodes::Input("image", iopt));

앱에서 파싱된 H.265 액세스 유닛을 전송할 때, 경계선을 인코딩하고, FormatTag::H265를 선택하고, 해당 디코더 유형을 선택합니다. 미디어 유형은 태그에서 확인되므로, 캡스 문자열은 필요하지 않습니다. 디코더의 너비, 높이 및 FPS를 기본 스트림 값으로 설정합니다.

simaai::neat::Graph graph;

simaai::neat::InputOptions iopt;
iopt.payload_type = simaai::neat::PayloadType::Encoded;
iopt.format = simaai::neat::FormatTag::H265;

graph.add(simaai::neat::nodes::Input("video", iopt));

simaai::neat::SimaDecodeOptions decode;
decode.type = simaai::neat::SimaDecodeType::H265;
decode.dec_width = 1280;
decode.dec_height = 720;
decode.dec_fps = 30;
graph.add(simaai::neat::nodes::SimaDecode(decode));
graph.add(simaai::neat::nodes::Output("frames"));

auto run = graph.build();

auto push_h265_access_unit = [&run](std::vector<std::uint8_t> bytes) {
auto sample = simaai::neat::make_encoded_sample(
std::move(bytes),
"video/x-h265,parsed=true,stream-format=byte-stream,alignment=au");
sample.port_name = "video";
run.push("video", sample);
};

이미 RtspDecodedInput(...) 또는 VideoInputGroup(...)을 사용하고 있다면, 이 앱에서 추가하는 경계 조건을 그 앞에 추가하지 마십시오. 소스에서 관리하는 그룹은 자체 입력 경로를 소유합니다.

샘플 출력​

소비자가 전체 Sample (페이로드와 스트림/프레임/타임스탬프 메타데이터 포함)을 필요로 할 때 nodes::Output을 사용하십시오.

풀 동작이 중요할 때 OutputOptions을 사용하십시오.

목표사용
가장 최신 출력을 유지OutputOptions::Latest() / pyneat.OutputOptions.latest()
모든 프레임을 풀OutputOptions::EveryFrame(...) / pyneat.OutputOptions.every_frame(...)
그래프 클록에 맞춰 출력 속도 조절OutputOptions::Clocked(...) / pyneat.OutputOptions.clocked(...)
여러 프로듀서를 결합combine_policy = CombinePolicy::ByFrame 또는 ByPts
simaai::neat::Graph graph;
graph.add(simaai::neat::nodes::Input("image"));
graph.add(model);
graph.add(simaai::neat::nodes::Output(
"classes",
simaai::neat::OutputOptions::EveryFrame()));

const auto run = graph.build();

OutputOptions에는 네 가지 조정 가능한 옵션이 있지만, 대부분의 애플리케이션을 지원하는 기본 설정이 제공됩니다.

필드제어하는 항목권장 설정
max_buffers백프레셔 또는 삭제 전에 대기할 수 있는 최대 출력 샘플 수Latest(), EveryFrame(...) 또는 Clocked(...) 기본 설정
drop오버플로우 시 가장 오래된 대기 중인 샘플을 삭제할지, 아니면 차단할지 여부실시간 미리보기 스타일 출력의 경우 Latest()
sync출력이 그래프 클록과 동기화되는지 여부클록 기반 출력의 경우 Clocked(...)
combine_policy여러 상위 프로듀서의 출력을 단일 공개 Output으로 결합하는 방법유효한 frame_id가 있는 경우에만 CombinePolicy::ByFrame; 유효한 pts_ns가 있는 경우에만 ByPts

손실되지 않아야 하는 레코드의 경우 EveryFrame(...)을 사용하십시오. 최신 정보가 더 중요한 경우 Latest()을 사용하십시오. 실시간 미리보기가 법정 기록처럼 작동하지 않도록 하십시오.

고급: 이미지 또는 비디오 출력을 텐서에 맞게 조정​

일반적인 모델 또는 그래프 출력의 경우, 여기에서 중단하십시오. nodes::Output을 사용하십시오. 페이로드가 텐서만이고 전체 Sample 봉투가 필요하지 않은 경우 pull_tensors(...)를 사용하여 가져오십시오.

이미지 또는 비디오 출력을 변환, 크기 조정 또는 프레임 속도 조절하여 애플리케이션이 가져오기 전에 CPU 친화적인 UInt8 텐서로 만들어야 하는 경우에만 Graph::add_output_tensor(...)를 사용하십시오. 이 헬퍼는 어댑터 경로를 삽입하고 이름이 없는 출력을 만듭니다. 하나의 출력으로, run.pull_tensors(...)를 사용하여 가져옵니다.

OutputTensorOptions는 format, target_width, target_height 및 target_fps를 제어합니다. dtype을 UInt8로 유지하십시오. 현재 공개 경로는 다른 dtype을 거부합니다. 대부분의 모델 출력에는 이 헬퍼가 필요하지 않습니다.

빠른 결정 가이드​

  • 소스가 파일, 카메라 또는 RTSP인 경우: nodes::groups에서 미리 빌드된 입력 그룹을 사용하십시오.
  • 소스가 애플리케이션에서 생성된 텐서/프레임인 경우: nodes::Input을 사용하십시오.
  • 출력 소비자가 스트림/프레임/타임스탬프 메타데이터를 필요로 하는 경우: nodes::Output을 사용하고 Sample 객체를 가져옵니다.
  • 출력이 모델 또는 텐서 페이로드인 경우: nodes::Output을 사용하고 전체 Sample이 필요하지 않은 경우 pull_tensors(...)를 사용하여 텐서를 가져옵니다.
  • 출력이 크기 조정, 재구성 또는 프레임 속도 조절을 해야 하는 이미지 또는 비디오인 경우: 고급 add_output_tensor(...) 어댑터를 사용하십시오.
  • 재사용 가능한 번들이 필요한 경우: 노드에서 Graph 조각을 만들고 다른 빌딩 블록과 마찬가지로 추가/연결하십시오.

이것이 중요한 이유​

  • 하나의 개념이 원자적 단계, 경계 선언 및 미리 빌드된 그룹을 포괄합니다.
  • 재사용 가능한 그래프 조각은 함수처럼 작동합니다. 입력이 들어가고 출력이 나오며, 중간에 의도치 않은 런타임 소스/싱크가 없습니다.
  • 노드 이름과 경계 이름이 로우어링 과정에서 유지되므로 진단이 용이합니다.
  • 내부 경계가 불필요한 복사 또는 대기를 강제하지 않으므로 런타임 효율성이 유지됩니다.

추가 정보​

튜토리얼​

UdpOutputGroupG는 사용 중단 예정이며 소스 호환성을 위해 유지됩니다. 지원되는 노드로 명시적인 그래프를 구성하고 필요에 따라 비디오에는 VideoSender, 메타데이터에는 MetadataSender를 사용합니다. 레거시 그룹은 모든 런타임 패키지에 포함되지 않는 렌더링 및 샘플 역다중화 플러그인이 필요합니다.

하드웨어 인코딩​

SimaEncodeOptions.type은 H.264, H.265 또는 MJPEG를 선택합니다. 인코더는 네이티브 8비트 NV12를 받습니다. 입력 어댑터는 호환되는 SiMaAI NV12 버퍼를 유지하고 지원되는 CPU 원시 레이아웃을 한 번 준비합니다. 출력은 인코딩된 프레임이며 RTP로 전송할 때만 패킷화를 추가합니다.

simaai::neat::SimaEncodeOptions encode;
encode.type = simaai::neat::SimaEncodeType::H265;
encode.fps = 30;
encode.bitrate_kbps = 4000;
encode.gop_length = 30;
encode.idr_interval = 90;
graph.add(simaai::neat::nodes::SimaEncode(encode));
encode = pyneat.SimaEncodeOptions()
encode.type = pyneat.SimaEncodeType.MJPEG
encode.fps = 30
encode.quality = 80
graph.add(pyneat.nodes.sima_encode(encode))

인코딩을 시작할 때 입력 프레임에서 해상도를 가져오며 크기를 조정하지 않습니다. 다른 해상도를 인코딩하려면 새 실행을 시작합니다. 입력 크기는 양의 짝수여야 합니다. nodes::SimaEncode()와 pyneat.nodes.sima_encode()는 기본 H.264 설정을 사용합니다. 인코더 옵션에 입력 크기를 반복해서 지정하지 않습니다. fps는 스트림 주기와 속도 제어를 설정하며 입력 제출 속도를 조절하지 않습니다. H.264/H.265는 bitrate_kbps(기본 4000), rate_control(vbr 또는 cbr), profile, level(기본 4.0), gop_length, 별도의 idr_interval을 지원합니다. H.264 기본 프로파일은 baseline이며 H.265는 main을 지원합니다. 스트림에 필요하면 런타임이 요청한 레벨을 높이고 실제 적용 설정을 보고합니다. GOP가 0이거나 미설정이면 FPS를 사용하고 IDR이 0이거나 미설정이면 FPS의 3배를 사용합니다. GOP 1은 모두 인트라 프레임입니다. B 프레임 인코딩은 제공하지 않습니다.

코덱별 옵션은 처음에는 미설정입니다. MJPEG는 1100의 quality(기본 80)를 받으며 명시적으로 지정된 비디오 전용 설정을 거부합니다. 반대로 H.264/H.265는 quality를 거부합니다. num_buffers는 인코딩 출력 버퍼 120개를 선택하며 -1은 네이티브 기본값인 4개를 유지합니다. 생산자 입력 메모리 크기는 설정하지 않습니다. 이 API는 네이티브 4:2:2와 고비트 심도 인코딩을 지원하지 않습니다.

H264EncodeSima와 pyneat.nodes.h264_encode_sima는 사용 중단 예정인 호환 진입점입니다. 인수, getter, 네이티브 입력 동작은 계속 지원합니다. H264Decode와 마찬가지로 헤더를 포함하기 전에 SIMA_ENABLE_LEGACY_DEPRECATION을 정의하면 C++ 호출에서 경고가 발생합니다. Python 호출은 DeprecationWarning을 발생시킵니다. H264EncodeSW는 변경되지 않습니다. 이 릴리스는 C++ ABI를 버전 5로 바꾸므로 C++ 소비자를 다시 빌드하고 함께 다시 빌드된 Python 확장을 사용해야 합니다.

VideoSender 코덱 선택​

원시 입력은 동일한 인코더 옵션을 VideoSenderOptions::FromRaw에 전달합니다. 코덱은 인코딩과 RTP 패킷화를 모두 선택합니다.

auto options = simaai::neat::nodes::groups::VideoSenderOptions::FromRaw(encode);
options.host = "127.0.0.1";
options.video_port_base = 9000;
auto sender = simaai::neat::nodes::groups::VideoSender(options);
options = pyneat.VideoSenderOptions.from_raw(encode)
options.host = "127.0.0.1"
sender = pyneat.groups.video_sender(options)

인코딩된 프레임에는 VideoSenderOptions::Passthrough(RtspCodec::H265) 또는 pyneat.VideoSenderOptions.passthrough(pyneat.RtspCodec.H265)를 사용합니다. 이 경로는 인코딩 없이 선택한 코덱을 파싱하고 패킷화합니다. 두 팩토리 모두 H.264와 MJPEG도 지원합니다. 팩토리는 입력 모드를 기록하고 그래프 구성은 경로를 한 번 선택합니다. is_raw_input()과 is_encoded_input()으로 선택을 확인할 수 있습니다.

기본 RTP 페이로드는 H.264 96, H.265 98, MJPEG 26이며 rtp.payload_type으로 0..127 범위에서 재정의할 수 있습니다. rtp.config_interval은 H.264/H.265에만 적용됩니다. UDP 포트는 video_port_base + channel입니다. sync=true는 파이프라인 클록에서 패킷 타임스탬프를 기다리고 async=true는 시작 시 싱크가 첫 preroll 버퍼를 기다릴 수 있게 합니다. 둘 다 기본값은 false입니다. Python은 async_를 사용하며 async 별칭도 유지합니다. 이 제어 옵션은 인코더 스레드를 선택하거나 생산자 제출 속도를 조절하지 않습니다.

기존 H.264 원시/인코딩 팩토리는 호환 진입점으로 유지됩니다. 새 원시 전송에는 FromRaw를 사용합니다. 전송 옵션은 구성의 복사본을 소유하므로 원래 encode 객체를 바꿔도 영향을 주지 않습니다. 이후 레거시 options.encoder의 비트레이트/프로파일/레벨 필드를 바꾸면 원시 H.264/H.265에 계속 적용됩니다. Python에서는 해당 객체 전체를 교체할 수도 있습니다. MJPEG는 기본값이 아닌 비디오 전용 재정의를 거부합니다. 인코딩 패스스루는 인코더 설정을 무시합니다.

RTP/JPEG에는 호환 수신기, 표준 허프만 테이블을 사용하는 베이스라인 JPEG, 각 축 8~2040 범위의 8의 배수 크기가 필요합니다. 원시 전송과 인코딩 패스스루는 RTP 패킷화 전에 caps 협상에서 지원되지 않는 크기를 거부합니다. 독립 SimaEncode는 네이티브 크기 범위를 유지합니다. 이 기능은 Insight의 RTP/WebRTC 뷰어에 MJPEG 표시를 추가하지 않습니다.