Skip to main content

Preproc Chapter

FieldValue
DifficultyIntermediate
Estimated Read Time15-20 minutes
Labelspreprocessing, normalization, image

Concept

Preprocessing is where raw input data is transformed into the exact tensor contract your model expects.

This chapter focuses on the preproc controls you use most in real deployments:

  • format: declares input image layout/color order (RGB/BGR/GRAY) expected at ingress.
  • input_max_width, input_max_height, input_max_depth: runtime bounds for accepted dynamic inputs.
  • preproc.input_width, preproc.input_height: expected source dimensions entering preproc.
  • preproc.output_width, preproc.output_height: tensor dimensions produced for inference.
  • preproc.normalize: enables value normalization before inference.
  • preproc.channel_mean, preproc.channel_stddev: per-channel normalization constants that should match model training assumptions.

Use-case guidance:

  • Model output is unstable or low-confidence after deployment: verify format and channel_mean/stddev first.
  • Multiple cameras/sources with different resolutions: set input_max_* and explicit preproc in/out dimensions for predictable behavior.
  • Porting a model from another framework: mirror the training-time normalization recipe with preproc.normalize + channel stats.
  • Isolating preprocessing issues: run/inspect model.preprocess() path and confirm shape/dtype before debugging inference/postproc.

Reference:

Learning Process

  1. Configure Model::Options / ModelOptions with explicit preproc dimensions, format, and normalization policy.
  2. Build the model and inspect preprocessing-stage behavior (group composition and tensor contract cues).
  3. Execute a deterministic run path and verify resulting output/type signals.
  4. Confirm expected behavior through CHECK, SIGNATURE, and [OK] markers.

Run

NEAT_EXTRAS_ROOT=<sima-neat-*-Linux-extras>
cd $NEAT_EXTRAS_ROOT/lib/sima-neat/tutorials
./tutorial_v2_005_preproc_chapter --mpk /path/to/model.tar.gz

Code

tutorials/005_preproc_chapter/preproc_chapter.cpp
// Run preprocessing standalone via stages::Preproc and inspect the resulting tensor.
//
// Usage:
// tutorial_v2_005_preproc_chapter --mpk /path/to/resnet_50.tar.gz [--size 224]

#include "neat.h"

#include "pipeline/StageRun.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;
}

int parse_int_arg(int argc, char** argv, const std::string& key, int def) {
std::string value;
if (!get_arg(argc, argv, key, value))
return def;
return std::stoi(value);
}

} // namespace

int main(int argc, char** argv) {
try {
std::string mpk;
if (!get_arg(argc, argv, "--mpk", mpk)) {
std::cerr << "Usage: tutorial_v2_005_preproc_chapter --mpk <path> [--size <n>]\n";
return 1;
}
const int size = parse_int_arg(argc, argv, "--size", 224);

simaai::neat::Model::Options opt;
opt.format = "BGR";
opt.input_max_width = size;
opt.input_max_height = size;
opt.input_max_depth = 3;
opt.preproc.input_width = size;
opt.preproc.input_height = size;
opt.preproc.output_width = size;
opt.preproc.output_height = size;
opt.preproc.normalize = true;
opt.preproc.channel_mean = std::array<float, 3>{0.5f, 0.5f, 0.5f};
opt.preproc.channel_stddev = std::array<float, 3>{0.5f, 0.5f, 0.5f};

simaai::neat::Model model(mpk, opt);

cv::Mat bgr(size, size, CV_8UC3, cv::Scalar(40, 80, 120));
if (!bgr.isContinuous())
bgr = bgr.clone();

// CORE LOGIC
// stages::Preproc runs just the preprocessing step from the model's Options
// and returns the preprocessed Tensor.
simaai::neat::Tensor pre = simaai::neat::stages::Preproc(bgr, model);

std::cout << "preproc_rank=" << pre.shape.size() << "\n";
std::cout << "preproc_dtype=" << static_cast<int>(pre.dtype) << "\n";
std::cout << "[OK] 005_preproc_chapter\n";
return 0;
} catch (const std::exception& e) {
std::cerr << "[FAIL] " << e.what() << "\n";
return 1;
}
}

Source