Skip to main content

Configure Model Options

FieldValue
DifficultyBeginner
Estimated Read Time5 minutes
Labelsmodel-options, configuration, contracts

Concept​

ModelOptions declares the runtime contract between your input data, the model pipeline stages, and output decoding. It is the first struct you reach for when moving past default behavior — one place to tune preprocessing, input bounds, and postprocessing together.

This chapter focuses on the options most teams use first:

  • format, media_type: declare incoming data type (for example raw RGB/BGR image input).
  • input_max_width, input_max_height, input_max_depth: set dynamic input bounds for validation and runtime sizing.
  • preproc.*: control preprocessing behavior (normalization, channel stats, image-type and resize policy overrides).
  • decode_type, score_threshold, nms_iou_threshold, top_k: control detection-style postprocessing and filtering.
  • original_width, original_height: provide original image geometry when postprocessing requires source-frame coordinates.
  • name_suffix, upstream_name: stabilize/clarify generated stage naming when composing bigger pipelines.

Use-case guidance

  • Prototype classification quickly: set format + input max dimensions, keep postproc defaults minimal.
  • Detection model bring-up (YOLO-style): set decode_type plus threshold/NMS/top-k options to shape final boxes.
  • Mixed input sizes in one app: set input_max_* high enough for expected ranges to avoid runtime contract failures.
  • Accuracy tuning after deployment: adjust preproc.normalize, channel_mean, channel_stddev to match model training assumptions.
  • Multi-model or hybrid pipelines: use name_suffix / upstream_name to keep pipeline graph naming explicit and debuggable.

APIs introduced

  • pyneat.ModelOptions() with the fields listed above.
  • model.input_spec(), model.output_spec(), model.metadata() — inspect the resolved contract after loading.

Prerequisites Chapter 001.

References

Learning Process​

  1. Build a Model::Options / ModelOptions config covering input, preproc, and postproc settings.
  2. Instantiate a model with those options and inspect input_spec(), output_spec(), and metadata.
  3. Run one deterministic inference path and observe how options influence runtime behavior.

Run​

Python:

python3 share/sima-neat/tutorials/004_configure_model_options/configure_model_options.py \
--mpk /tmp/yolo_v8s_mpk.tar.gz

C++ (prebuilt):

./lib/sima-neat/tutorials/tutorial_004_configure_model_options \
--mpk /tmp/yolo_v8s_mpk.tar.gz

C++ (build from source):

./build.sh --target tutorial_004_configure_model_options
./build/tutorials-standalone/tutorial_004_configure_model_options \
--mpk /tmp/yolo_v8s_mpk.tar.gz

To integrate this chapter's C++ source into your own project with a custom CMakeLists.txt (no extras folder required), see How to Run Tutorials on the landing page.

Code​

tutorials/004_configure_model_options/configure_model_options.cpp
// Model::Options chapter: configure input/preproc/boxdecode via Options, inspect specs.
//
// Usage:
// tutorial_004_configure_model_options --mpk /path/to/yolo_v8s.tar.gz

#include "neat.h"

#include <opencv2/core.hpp>

#include <array>
#include <iostream>
#include <stdexcept>
#include <string>

namespace {

bool get_arg(int argc, char** argv, const std::string& key, std::string& out) {
for (int i = 1; i + 1 < argc; ++i) {
if (key == argv[i]) {
out = argv[i + 1];
return true;
}
}
return false;
}

void print_spec(const char* label, const simaai::neat::TensorConstraint& spec) {
std::cout << label << ": rank=" << spec.rank << " dtypes=" << spec.dtypes.size()
<< " shape_dims=" << spec.shape.size() << "\n";
}

} // namespace

int main(int argc, char** argv) {
try {
std::string mpk;
if (!get_arg(argc, argv, "--mpk", mpk)) {
std::cerr << "Usage: tutorial_004_configure_model_options --mpk <path>\n";
return 1;
}

// Model::Options groups input caps, preproc, and box-decode into one struct.
simaai::neat::Model::Options opt;
opt.preprocess.kind = simaai::neat::InputKind::Image;
opt.preprocess.color_convert.input_format = simaai::neat::PreprocessColorFormat::BGR;
opt.preprocess.input_max_width = 640;
opt.preprocess.input_max_height = 640;
opt.preprocess.input_max_depth = 3;
opt.preprocess.normalize.enable = simaai::neat::AutoFlag::On;
opt.preprocess.normalize.mean = std::array<float, 3>{0.485f, 0.456f, 0.406f};
opt.preprocess.normalize.stddev = std::array<float, 3>{0.229f, 0.224f, 0.225f};
opt.decode_type = simaai::neat::BoxDecodeType::YoloV8;
opt.score_threshold = 0.55f;
opt.nms_iou_threshold = 0.45f;
opt.top_k = 100;
opt.boxdecode_original_width = 640;
opt.boxdecode_original_height = 640;
opt.name_suffix = "_chapter";

// CORE LOGIC
simaai::neat::Model model(mpk, opt);
print_spec("input_spec", model.input_spec());
print_spec("output_spec", model.output_spec());
std::cout << "metadata_keys=" << model.metadata().size() << "\n";

cv::Mat bgr(640, 640, CV_8UC3, cv::Scalar(10, 20, 30));
if (!bgr.isContinuous())
bgr = bgr.clone();
auto out = model.run(std::vector<cv::Mat>{bgr}, /*timeout_ms=*/2000);
std::cout << "outputs=" << out.size() << "\n";
std::cout << "[OK] 004_configure_model_options\n";
return 0;
} catch (const std::exception& e) {
std::cerr << "[FAIL] " << e.what() << "\n";
return 1;
}
}

Source​