Skip to content

Common.h

Go to the source code of this file.

Describes the general process of an inspection program.

The following is part of the Classification example code.

Getting Started

First, set the path to the image data and model file to be used. In this example, we used the example data and model files installed in the SAIGE_HOME path.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// ExampleClsRuntime.cpp:21

std::string dataDir =
    get_env_var("SAIGE_HOME") + "/" + get_runtime_base() + "/engine/Examples/data/sfaw2023/images/test/";

std::string trainedModelPath = dataDir + "../../models/cls_example.saigecls";

// 실행 인자: 기본값으로 실행하거나 항목별로 입력받는다 (verbosity 4: 결과 이미지 표시)
std::string imageExt = ".png";
int verbosity = 2;
bool optimize = false;
ExampleArgs()
    .Add("data_dir", dataDir)
    .Add("model_path", trainedModelPath)
    .Add("image_ext", imageExt)
    .Add("verbosity", verbosity, "0~4, 4: show result images")
    .Add("optimize", optimize)
    .Prompt();

// image paths to classify
// used filesystem library of c++17 standard.
// u8string means 8byte character string so, it doesn't support unicode system of filesystem.
std::vector<std::string> imagePaths;

for (const auto& file : std::filesystem::recursive_directory_iterator(dataDir)) {
    if (file.is_regular_file() && file.path().extension() == imageExt) {
        imagePaths.push_back(std::string(file.path().u8string()));
    }
}

Create Handle

Next, create handles for the inspection handle and inspection result. Set the options that can be set when creating a handle using the SaigeHandleConfig structure. Also, to apply the set option values, you must set the relevant flags appropriately. Add the SAIGE_OPTIMIZE_HANDLE flag if you want to use the optimization option.

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// ExampleClsRuntime.cpp:60

SaigeInferenceHandle handle = nullptr;
SaigeHandleConfig config;
config.batchSize = 1;
unsigned int handleFlags = SAIGE_SET_BATCH_SIZE;
if (optimize) {
    handleFlags |= SAIGE_OPTIMIZE_HANDLE;
}
retval = SaigeCreateInferenceHandle(&handle, kProjectTypeCLS, trainedModelPath.c_str(),
                                    deviceIndex, &config, handleFlags);
if (retval < 0) {
    std::cerr << "SaigeCreateInferenceHandle() failed - " << SaigeStrError(retval) << std::endl;
    return retval;
}

SaigeInferenceResult result = nullptr;
retval = SaigeCreateInferenceResult(&result);
if (retval < 0) {
    std::cerr << "SaigeCreateInferenceResult() failed - " << SaigeStrError(retval) << std::endl;
    SaigeDestroyInferenceHandle(handle);
    return retval;
}

Using Result Handle

The inference results obtained from the Result Handle are automatically released when the Result Handle is destroyed or used for the next inspection. In SAIGE VISION, the memory management of the array-form inference result data is automatically performed by the Result Handle. The memory allocated when the Result Handle is used for the next inspection or when the SaigeDestroyInferenceResult function is called is released.

Get Model Information

Use the SaigeModelInfo structure to retrieve model information.

 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// ExampleClsRuntime.cpp:87

std::cout << SaigeGetModuleVersion() << std::endl;
SaigeModelInfo* modelInfo = new SaigeModelInfo;
retval = SaigeGetModelInfo(handle, modelInfo);
if (retval < 0) {
    std::cerr << "SaigeGetModelInfo() failed - " << SaigeStrError(retval) << std::endl;
} else if (verbosity >= 1) {
    std::cout << "[Classification Model Info]" << std::endl;
    std::cout << "Network Type: " << modelInfo->networkType << std::endl;
    std::cout << "Number of Classes: " << modelInfo->numOfClasses << std::endl;

    for (auto i = 0; i < modelInfo->numOfClasses; ++i) {
        uint8_t red, green, blue;
        SaigeColorCodeToRGB(modelInfo->classColors[i], &red, &green, &blue);
        std::cout << modelInfo->classNames[i] << ": color RGB(" << (int)red << ", " << (int)green
                  << ", " << (int)blue << ") - " << (modelInfo->classIsNg[i] ? "NG" : "OK")
                  << std::endl;
    }
    std::cout << "Trained Developer Version: " << modelInfo->developerVersion << std::endl;
    std::cout << "Server Version: " << modelInfo->serverVersion << std::endl;
    std::cout << "Module Version: " << modelInfo->moduleVersion << std::endl;
    std::cout << "TrainingTimeStarted: " << modelInfo->trainingTimeStarted << std::endl;
    std::cout << "TrainingTimeCompleted: " << modelInfo->trainingTimeCompleted << std::endl;
    std::cout << "TrainingTimeElapsed: " << modelInfo->trainingTimeElapsed << std::endl;
    std::cout << "UsedGpuName: " << modelInfo->usedGpuName << std::endl;
    std::cout << "Number of Train Images: " << modelInfo->numOfTrainImages << std::endl;
    std::cout << "Number of Validation Images: " << modelInfo->numOfValidationImages
              << std::endl;
    std::cout << "Number of Iterations: " << modelInfo->numOfIterations << std::endl;
    std::cout << "ROI Info" << std::endl
              << "- ROI Mode: " << modelInfo->roiInfo.roiMode << std::endl
              << "- ROI LTRB Ratio: " << modelInfo->roiInfo.left << ", " << modelInfo->roiInfo.top
              << ", " << modelInfo->roiInfo.right << ", " << modelInfo->roiInfo.bottom
              << std::endl;
    std::cout << "Image Resize Width, Height: " << modelInfo->imageResizeWidth << ", "
              << modelInfo->imageResizeHeight << std::endl;
    if (modelInfo->roiInfo.blindMask != nullptr) {
        // show blind mask
        SaigeShowImage(modelInfo->roiInfo.blindMask, modelInfo->roiInfo.blindMaskWidth,
                       modelInfo->roiInfo.blindMaskHeight, 1, SaigeImageType::SV_U8, false, true,
                       255.0, 0);
    }
}

Set Inference Options

You can set the options to be used during inference using the SaigeInferenceOption structure and Get, Set functions.

Note

Before changing the option value, you must initialize the structure with the currently set option values using the SaigeGetInferenceOption function.

136
137
138
139
140
141
142
143
144
145
// ExampleClsRuntime.cpp:138

SaigeInferenceOption* options = new SaigeInferenceOption;
retval = SaigeGetInferenceOption(handle, options);
if (retval < 0) {
    std::cerr << "SaigeGetInferenceOption() failed - " << SaigeStrError(retval) << std::endl;
    SaigeDestroyInferenceHandle(handle);
    SaigeDestroyInferenceResult(result);
    return retval;
}

Additional options can be set depending on the program settings. Here, the bool detailedTime value is used to set the SaigeInferenceOption::calcTime value. In this case, you must pass the flag that specifies which option value to set as the third argument to the SaigeSetInferenceOption function.

147
148
149
150
151
152
153
154
155
156
157
158
159
// ExampleClsRuntime.cpp:149

if (detailedTime) {
    options->calcTime = true;
    retval = SaigeSetInferenceOption(handle, options, SAIGE_SET_CALC_TIME);
    if (retval < 0) {
        std::cerr << "SaigeSetInferenceOption() failed - " << SaigeStrError(retval)
                  << std::endl;
        SaigeDestroyInferenceHandle(handle);
        SaigeDestroyInferenceResult(result);
        return retval;
    }
}

Inspect

Here, the image file is loaded into an array and inspected. To load image data, use the SaigeGetImageData function. In this case, you receive the width, height, channels, and type of the image data loaded.

226
227
228
229
230
231
232
233
// ExampleClsRuntime.cpp:228

// 이미지 데이터를 로드합니다.
ucImageData = (unsigned char*)SaigeGetImageData(img.c_str(), &w, &h, &c, &type);
if (ucImageData == nullptr) {
    std::cerr << "SaigeGetImageData() failed - " << img << std::endl;
    continue;
}

The imageFlag value sets whether the image data is 8-bit or 16-bit, the order of the channels, etc. For the image loaded using the SaigeGetImageData function, you can set the imageFlag value using the SaigeConvertImageType function. Then, perform inference using the SaigeInferFromByteArray function.

242
243
244
245
246
247
248
249
250
// ExampleClsRuntime.cpp:244

unsigned int imageFlag = SaigeConvertImageType(c, type);
retval = SaigeInferFromByteArray(handle, ucImageData, w, h, imageFlag, result);
if (retval < 0) {
    std::cerr << "SaigeInferFromByteArray() failed - " << SaigeStrError(retval)
              << std::endl;
    continue;
}

To get the inference result, use the Get Result function appropriate for the project type.

254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
// ExampleClsRuntime.cpp:256

std::vector<float> score;
int classId;
score.resize(modelInfo->numOfClasses);
retval = SaigeGetInferenceResultScore(result, score.data(), true);
if (retval < 0) {
    std::cerr << "SaigeGetInferenceResultScore() failed - " << SaigeStrError(retval)
              << std::endl;
    SaigeDestroyInferenceHandle(handle);
    SaigeDestroyInferenceResult(result);
    return retval;
}

retval = SaigeGetInferenceResultClass(result, &classId);
if (retval < 0) {
    std::cerr << "SaigeGetInferenceResultClass() failed - " << SaigeStrError(retval)
              << std::endl;
    SaigeDestroyInferenceHandle(handle);
    SaigeDestroyInferenceResult(result);
    return retval;
}

retval = SaigeGetInferenceResultInspectionTime(result, &imreadTime, &inferenceTime,
                                               &postProcessingTime);
if (retval < 0) {
    std::cerr << "SaigeGetInferenceResultClass() failed - " << SaigeStrError(retval)
              << std::endl;
    SaigeDestroyInferenceHandle(handle);
    SaigeDestroyInferenceResult(result);
    return retval;
}

See also: SaigeGetInferenceResultClass, SaigeGetInferenceResultScore, SaigeGetInferenceResultInspectionTime

Clean Up

Note

The image data loaded using the SaigeGetImageData function must be released using the SaigeFreeImageData function.

If you have allocated memory for structures such as model information and inference options, you must release the memory.

343
344
345
346
347
348
349
350
351
352
353
// ExampleClsRuntime.cpp:345

if (ucImageData != nullptr) {
    retval = SaigeFreeImageData(ucImageData);
    if (retval < 0) {
        std::cerr << "SaigeFreeImageData() Failed - " << SaigeStrError(retval) << std::endl;
    }
    ucImageData = nullptr;
}
delete modelInfo;
delete options;

Finally, destroy the inspection handle and result handle.

358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
// ExampleClsRuntime.cpp:360

retval = SaigeDestroyInferenceResult(result);
if (retval < 0) {
    std::cerr << "SaigeDestroyInferenceResult() failed - " << SaigeStrError(retval)
              << std::endl;
    return retval;
}

retval = SaigeDestroyInferenceHandle(handle);
if (retval < 0) {
    std::cerr << "SaigeDestroyInferenceHandle() failed - " << SaigeStrError(retval)
              << std::endl;
    return retval;
}