Plumerai People Detection for Cortex-M API¶
This document describes the C API for Plumerai’s people detection software for videos on Arm Cortex-M microcontrollers.
Below are all the functions that make up the API. Following that is the full header as well as a simple example of how to use the API.
PeopleDetectionMicroInit¶
Initializes the people detection algorithm. This needs to be called only once at the start of the application.Arguments
- tensor_arena
unsigned char*
: A pointer to a user-allocated contiguous memory region to store input, output, and intermediate tensors. The size should be equal or larger than the value given byMIN_TENSOR_ARENA_SIZE
.
Returns
StatusCode
: A status-code indicating whether there was an error, it can be either of Success
or AllocationError
(see full header below for a description of these codes).
PeopleDetectionMicroCleanUp¶
Cleans-up the people detection algorithm. This needs to be called only once at the end of the application.Returns
StatusCode
: A status-code indicating whether there was an error. At the moment always returns Success
.
PeopleDetectionGetInputPointer¶
Retrieves the address of where the input data needs to be stored before making a call toPeopleDetectionMicroProcessFrame
. The camera output should be stored here in the image format described before. Any data residing at this location can be overwritten by a call to PeopleDetectionMicroProcessFrame
. The user should not write beyond PLUMERAI_IMAGE_SIZE
bytes from the start of this value. Returns
signed char*
: A pointer to the location the input data should be placed.
PeopleDetectionGetScratchPointer¶
Retrieves the address of where scratch data can optionally be placed. This is exposed to the user in case the tensor-arena does not leave much other contiguous memory regions available for the user to store data. Note that any data residing at this location can be overwritten by any call toPeopleDetectionMicroProcessFrame
. The user should not read or write beyond the actual tensor arena size minus PLUMERAI_TENSOR_ARENA_TAIL_RESERVED
from the start of this scratch pointer. Returns
signed char*
: A pointer to the location where scratch data can be placed.
PeopleDetectionMicroProcessFrame¶
StatusCode PeopleDetectionMicroProcessFrame(BoxPrediction* results,
int results_length,
int* num_results_returned);
PeopleDetectionGetInputPointer
. Arguments
- results
BoxPrediction*
: A pointer to an array to store the resulting boxes in. The user needs to allocate space for this structure. The recommended size is 20, but if the user allocates less, then fewer boxes are returned. If fewer boxes are detected, then also fewer are returned. This amount is given bynum_results_returned
, see below. - results_length
int
: The number ofBoxPrediction
elements allocated in the providedresults
parameter above by the user. See that parameter for more info. - num_results_returned
int*
: The minimum of the number of resulting bounding-boxes found in the image andresults_length
. The results structureresults
will be filled with zeros beyond this amount. If this value is equal toresults_length
, it might be an indication that more boxes are found than that can be output.
Returns
StatusCode
: A status-code indicating whether there was an error, it can be either of Success
, InvokeError
, OutputDimsError
(see full header below for a description of these codes).
BoxPrediction¶
typedef struct {
float y_min; // top coordinate between 0 and 1 in height dimension
float x_min; // left coordinate between 0 and 1 in width dimension
float y_max; // bottom coordinate between 0 and 1 in height dimension
float x_max; // right coordinate between 0 and 1 in width dimension
float confidence; // between 0 and 1, higher means more confident
} BoxPrediction;
Full header¶
#ifndef PLUMERAI_PEOPLE_DETECTION_MICRO_H
#define PLUMERAI_PEOPLE_DETECTION_MICRO_H
// The minimum amount of contiguous memory that needs to be allocated by the
// user. This can be allocated on a memory region of the user's choice. See
// `PeopleDetectionMicroInit` for more information.
#define MIN_TENSOR_ARENA_SIZE (327 * 1024)
// The Plumerai people detection algorithm requires a fixed input resolution.
// It uses 3-channel RGB data with 8-bits for each channel. See the description
// of `PeopleDetectionMicroProcessFrame` for more information.
#define PLUMERAI_IMAGE_HEIGHT 192 // The height of the input image in pixels.
#define PLUMERAI_IMAGE_WIDTH 256 // The width of the input image in pixels.
#define PLUMERAI_IMAGE_SIZE (PLUMERAI_IMAGE_HEIGHT * PLUMERAI_IMAGE_WIDTH * 3)
// See `PeopleDetectionGetScratchPointer` for documentation about this define.
#define PLUMERAI_TENSOR_ARENA_TAIL_RESERVED PLUMERAI_IMAGE_SIZE
// Most functions in this API return a status-code to indicate whether
// everything went well. If not, see below for more information about the error
// code.
typedef enum StatusCode_ {
Success = 0, // Everything went all right
AllocationError = -1, // Memory allocation failure, check arena size
InvokeError = -2, // Unexpected error, contact Plumerai
OutputDimsError = -3, // Unexpected error, contact Plumerai
} StatusCode;
// An output structure representing a single resulting bounding box.
// Coordinates are between 0 and 1, the origin is at the top-left.
typedef struct {
float y_min; // top coordinate between 0 and 1 in height dimension
float x_min; // left coordinate between 0 and 1 in width dimension
float y_max; // bottom coordinate between 0 and 1 in height dimension
float x_max; // right coordinate between 0 and 1 in width dimension
float confidence; // between 0 and 1, higher means more confident
} BoxPrediction;
// Initializes the people detection algorithm. This needs to be called only
// once at the start of the application.
//
// @param tensor_arena A pointer to a user-allocated contiguous memory region
// to store input, output, and intermediate tensors. The size should be equal
// or larger than the value given by `MIN_TENSOR_ARENA_SIZE`.
// @return a status-code indicating whether there was an error, it can be either
// of `Success` or `AllocationError` (see above for a description).
StatusCode PeopleDetectionMicroInit(unsigned char* tensor_arena);
// Cleans-up the people detection algorithm. This needs to be called only once
// at the end of the application.
//
// @return a status-code indicating whether there was an error. At the moment
// always returns `Success`.
StatusCode PeopleDetectionMicroCleanUp();
// Retrieves the address of where the input data needs to be stored before
// making a call to `PeopleDetectionMicroProcessFrame`. The camera output
// should be stored here in the image format described before. Any data residing
// at this location can be overwritten by a call to
// `PeopleDetectionMicroProcessFrame`. The user should not write beyond
// `PLUMERAI_IMAGE_SIZE` bytes from the start of this value.
//
// @return a pointer to the location the input data should be placed
signed char* PeopleDetectionGetInputPointer();
// Retrieves the address of where scratch data can optionally be placed. This is
// exposed to the user in case the tensor-arena does not leave much other
// contiguous memory regions available for the user to store data. Note that any
// data residing at this location can be overwritten by any call to
// `PeopleDetectionMicroProcessFrame`. The user should not read or write beyond
// the actual tensor arena size minus `PLUMERAI_TENSOR_ARENA_TAIL_RESERVED` from
// the start of this scratch pointer.
//
// @return a pointer to the location where scratch data can be placed
signed char* PeopleDetectionGetScratchPointer();
// Process a single frame from a video sequence with RGB input. This will
// process RGB image data (1st byte red, 3rd blue) of size PLUMERAI_IMAGE_HEIGHT
// * PLUMERAI_IMAGE_WIDTH * 3 in signed 8-bits format (range -128,+127) found at
// the location return by `PeopleDetectionGetInputPointer`.
//
// @param results A pointer to an array to store the resulting boxes in. The
// user needs to allocate space for this structure. The recommended size is 20,
// but if the user allocates less, then fewer boxes are returned. If fewer
// boxes are detected, then also fewer are returned. This amount is given by
// `num_results_returned`, see below.
// @param results_length The number of `BoxPrediction` elements allocated in
// the provided `results` parameter above by the user. See that parameter for
// more info.
// @param num_results_returned The minimum of the number of resulting
// bounding-boxes found in the image and `results_length`. The results
// structure `results` will be filled with zeros beyond this amount. If this
// value is equal to `results_length`, it might be an indication that more
// boxes are found than that can be output.
// @return a status-code indicating whether there was an error, it can be either
// of `Success`, `InvokeError`, `OutputDimsError` (see above for description).
StatusCode PeopleDetectionMicroProcessFrame(BoxPrediction* results,
int results_length,
int* num_results_returned);
#endif // PLUMERAI_PEOPLE_DETECTION_MICRO_H
Example usage¶
Below is an example of using the C API shown above.
#include "plumerai/people_detection_micro.h"
// Here stdio.h is used for `printf`, but this can be replaced with any specific
// method of printing results to screen, if needed.
#include <cstdio>
// Example tensor arena. Can be allocated on a specific memory region if
// desired. It needs to be at least of size MIN_TENSOR_ARENA_SIZE but can be
// larger if more contiguous scratch space is desired.
__attribute__((aligned(16))) unsigned char tensor_arena[MIN_TENSOR_ARENA_SIZE];
void mainloop() {
// This initializes the people detector
int error_code = PeopleDetectionMicroInit(tensor_arena);
if (error_code != 0) return;
signed char* input_ptr = PeopleDetectionGetInputPointer();
// We pre-allocate memory for the results, at most 10 boxes can be found
BoxPrediction predictions[10];
// Loop over frames in a video stream
while (true) {
// Some example input here, normally this is where image data is acquired.
// We can pass the `input_ptr` value directly to our camera API if it can
// provide us with the right resolution and format. If not, we might have to
// first resize our input image. Plumerai can provide optimized code for
// this if needed. A call to `PeopleDetectionGetScratchPointer` can be made
// to get a scratch buffer to store the initial high-resolution input in.
//
// In this example here we simply assign some values for fake input data.
const int image_size = PLUMERAI_IMAGE_WIDTH * PLUMERAI_IMAGE_HEIGHT * 3;
for (int i = 0; i < image_size; ++i) {
// Input data is in RGB signed 8-bits format (range -128,+127)
input_ptr[i] = static_cast<signed char>((i % 255) - 128);
}
// Process a single input image frame from e.g. a camera video stream. The
// result will be stored in `predictions`, and `num_results` will tell us
// how many results there are.
int num_results = 0;
error_code =
PeopleDetectionMicroProcessFrame(predictions, 10, &num_results);
if (error_code != 0) return;
// Write the results to a terminal. Replace this with your own printing
// function if needed.
printf("Detected %d person(s)\n", num_results);
for (int i = 0; i < num_results; ++i) {
BoxPrediction p = predictions[i];
printf(
"Detected person with confidence %.2f @ (x,y) -> (%.2f,%.2f) till (%.2f,%.2f)\n",
p.confidence, p.x_min, p.y_min, p.x_max, p.y_max);
}
}
// Clean-up
error_code = PeopleDetectionMicroCleanUp();
if (error_code != 0) return;
}