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
// ExampleClsRuntime.cpp:21

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

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

// 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() == ".png") {
        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.

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// ExampleClsRuntime.cpp:50

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.

 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 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
// ExampleClsRuntime.cpp:77

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.

126
127
128
129
130
131
132
133
134
135
// ExampleClsRuntime.cpp:128

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.

137
138
139
140
141
142
143
144
145
146
147
148
149
// ExampleClsRuntime.cpp:139

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.

216
217
218
219
220
221
222
223
// ExampleClsRuntime.cpp:218

// 이미지 데이터를 로드합니다.
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.

232
233
234
235
236
237
238
239
240
// ExampleClsRuntime.cpp:234

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.

244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
// ExampleClsRuntime.cpp:246

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.

333
334
335
336
337
338
339
340
341
342
343
// ExampleClsRuntime.cpp:335

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.

348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
// ExampleClsRuntime.cpp:350

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;
}