Basic Classification
This example loads a complete classification pipeline file (.denkflow) exported from the Hub.
- Python
- C
import denkflow
# A personal access token (PAT) is used for authentication.
pat = "YOUR-PAT"
# These are the files that will be used in this example.
denkflow_path = "path/to/model/file.denkflow"
image_path = "path/to/an/image.jpg"
# To make data available to the pipeline, it needs to be put into the
# input topic via publishing. After running the pipeline, the results
# can be received from the output topic. While the name of the inut
# topic is typically the same for every pipeline, the pipelines for
# different model types might deviate in the names of their output
# topics.
input_topic = "camera/image"
output_topic = "classification_node/output"
# Load the .denkflow file and create the pipeline from it.
pipeline = denkflow.Pipeline.from_denkflow(
denkflow_path,
pat=pat,
)
# This function initializes the pipeline. After this step, the pipeline
# can no longer be modified. Subscribing and publishing only work after
# initialization.
pipeline.initialize()
# The subscribe-function produces a receiver that can be used to gather
# output data from the pipeline.
receiver = pipeline.subscribe(output_topic)
# The image file needs to be converted to an ImageTensor before it can be
# fed into the pipeline.
image_tensor = denkflow.ImageTensor.from_file(image_path)
# The publishing step puts the data into the input topic, where it can be
# accessed by the pipeline.
pipeline.publish_image_tensor(input_topic, image_tensor)
# Upon calling the run-function, the pipeline takes the published image
# and processes it. The results are written into the output topic, where
# they can be received using the previously created receiver.
pipeline.run()
# This step will take the data from the output topic. The output data type
# for classification models is the scalar tensor.
tensor = receiver.receive_scalar_tensor()
# Every output tensor will have a to_objects-function which will produce
# objects that can be easily printed or used for further data processing.
results_per_batch = tensor.to_objects()
# For this example, the results of the classification are simply printed
# to the console.
print("Classification Results:")
for results_per_class_label in results_per_batch:
for result_for_class_label in results_per_class_label:
print(f"{result_for_class_label.class_label}: {result_for_class_label.value:.2f}")
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "denkflow.h"
void handle_error(enum DenkflowResult error_code, const char* function_name) {
printf("%s: %d", function_name, (int32_t)error_code);
if (error_code != DenkflowResult_Ok) {
char error_buffer[ERROR_BUFFER_SIZE];
memset(error_buffer, 0, ERROR_BUFFER_SIZE);
get_last_error(error_buffer);
printf(" (%s)\n", error_buffer);
exit(EXIT_FAILURE);
}
printf("\n");
}
int main() {
Pipeline* pipeline = NULL;
InitializedPipeline* initialized_pipeline = NULL;
ImageTensor* image_tensor = NULL;
Receiver_Tensor* receiver = NULL;
ScalarTensor* tensor = NULL;
ScalarResults* results = NULL;
HubLicenseSource* hub_license_source = NULL;
enum DenkflowResult r;
const uint64_t timeout_ms = 8000;
// A personal access token (PAT) is used for authentication.
const char* pat = "YOUR-PAT";
// These are the files that will be used in this example.
const char* denkflow_path = "path/to/model/file.denkflow";
const char* image_path = "path/to/an/image.jpg";
// To make data available to the pipeline, it needs to be put into the
// input topic via publishing. After running the pipeline, the results
// can be received from the output topic. While the name of the inut
// topic is typically the same for every pipeline, the pipelines for
// different model types might deviate in the names of their output
// topics.
const char* input_topic = "camera/image";
const char* output_topic = "classification_node/output";
// Creat a license source for authentication.
r = hub_license_source_from_pat(&hub_license_source, pat, NULL_BYTE, NULL_BYTE);
handle_error(r, "hub_license_source_from_pat");
// Load the .denkflow file and create the pipeline from it.
r = pipeline_from_denkflow(&pipeline, denkflow_path, (void*)hub_license_source);
handle_error(r, "pipeline_from_denkflow");
// This function initializes the pipeline. After this step, the pipeline
// can no longer be modified. Subscribing and publishing only work after
// initialization.
r = initialize_pipeline(&initialized_pipeline, &pipeline);
handle_error(r, "initialize_pipeline");
// The subscribe-function produces a receiver that can be used to gather
// output data from the pipeline.
r = initialized_pipeline_subscribe(&receiver, initialized_pipeline, output_topic);
handle_error(r, "initialized_pipeline_subscribe");
// The image file needs to be converted to an ImageTensor before it can be
// fed into the pipeline.
r = image_tensor_from_file(&image_tensor, image_path);
handle_error(r, "image_tensor_from_file");
// The publishing step puts the data into the input topic, where it can be
// accessed by the pipeline. This function deallocated the image_tensor.
r = initialized_pipeline_publish_image_tensor(initialized_pipeline, input_topic, &image_tensor);
handle_error(r, "initialized_pipeline_publish_image_tensor");
// Upon calling the run-function, the pipeline takes the published image
// and processes it. The results are written into the output topic, where
// they can be received using the previously created receiver.
r = initialized_pipeline_run(initialized_pipeline, timeout_ms);
handle_error(r, "initialized_pipeline_run");
// This step will take the data from the output topic. The output data type
// for classification models is the scalar tensor.
r = receiver_receive_scalar_tensor(&tensor, receiver);
handle_error(r, "receiver_receive_scalar_tensor");
// Every output tensor will have a to_objects-function which will produce
// objects that can be easily printed or used for further data processing.
r = scalar_tensor_to_objects(&results, tensor);
handle_error(r, "scalar_tensor_to_objects");
// For this example, the results of the classification are simply printed
// to the console.
if (r == DenkflowResult_Ok) {
for (int b = 0; b < results->scalar_batch_elements_length; b++) {
printf("Image %d\n", b);
for (int c = 0; c < results->scalar_batch_elements[b].scalars_length; c++) {
printf(" %s: %f\n",
results->scalar_batch_elements[b].scalars[c].class_label.name,
results->scalar_batch_elements[b].scalars[c].value
);
}
}
}
// Free all objects to avoid memory leaks
r = free_object((void**)&hub_license_source);
handle_error(r, "free_object");
r = free_object((void**)&initialized_pipeline);
handle_error(r, "free_object");
r = free_object((void**)&receiver);
handle_error(r, "free_object");
r = free_object((void**)&tensor);
handle_error(r, "free_object");
r = free_object((void**)&results);
handle_error(r, "free_object");
return 0;
}