CommandLineMatrixScanCameraSample.c

MatrixScan Sample Without User Interface

This example uses the Scandit SDK to run MatrixScan (Tracking) using frames from a camera.

This demo is currently limited to GNU/Linux systems with a Video4Linux 2 camera.

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
// Please insert your app key here:
#define SCANDIT_SDK_LICENSE_KEY "-- INSERT YOUR LICENSE KEY HERE --"
// Please insert the desired default camera resolution here:
#define DEFAULT_RESOLUTION_WIDTH 1280
#define DEFAULT_RESOLUTION_HEIGHT 720
static volatile ScBool process_frames;
static void catch_exit(int signo) {
printf("SIGINT received.\n");
process_frames = SC_FALSE;
}
static void print_all_discrete_resolutions(const ScCamera *cam) {
printf("This camera uses discrete resolutions:\n");
ScSize resolution_array[20];
ScFramerate framerate_array[10];
const int32_t resolution_count = sc_camera_query_supported_resolutions(cam, &resolution_array[0], 20);
for (int32_t i = 0; i < resolution_count; i++) {
const int32_t framerate_count = sc_camera_query_supported_framerates(cam, resolution_array[i], framerate_array, 10);
for (int32_t j = 0; j < framerate_count; j++) {
const float fps = sc_framerate_get_fps(&framerate_array[j]);
printf("\t%u:%u @ %.2f FPS\n", resolution_array[i].width, resolution_array[i].height, fps);
}
}
}
void on_appeared(const ScTrackedObject* obj, void *user_data) {
// This callback gets emitted when a new object appears in the camera feed.
// Use this callback to start to draw a location.
const uint32_t id = sc_tracked_object_get_id(obj);
const ScBarcode* barcode = (const ScBarcode*) obj;
if (sc_barcode_is_recognized(barcode)) {
printf("Barcode #%u: %s '%s' appeared.\n", id, sc_symbology_to_string(sc_barcode_get_symbology(barcode)), data.str);
} else {
printf("Object #%u appeared.\n", id);
}
}
void on_updated(const ScTrackedObject* obj, void *user_data) {
// This callback gets emitted when an existing object has been found
// in a new location.
const uint32_t id = sc_tracked_object_get_id(obj);
const ScBarcode* barcode = (const ScBarcode*) obj;
if (sc_barcode_is_recognized(barcode)) {
printf("Barcode #%u: %s '%s' was updated.\n", id, sc_symbology_to_string(sc_barcode_get_symbology(barcode)), data.str);
} else {
printf("Object #%u was updated.\n", id);
}
}
void on_lost(ScTrackedObjectType type, uint32_t tracking_id, void *user_data) {
// This callback gets emitted when an object was no longer found.
// Use this callback to disable your drawing task.
// Be aware that it also gets triggered on objects that have not been recognized.
printf("Object #%u was lost.\n", tracking_id);
}
void on_predicted(uint32_t tracking_id, ScQuadrilateral quadrilateral,
float dt, void *user_data) {
// Use this callback to update the drawing location of an object. Predictions
// are made even if the object was not found for a certain time.
}
int main(int argc, const char *argv[]) {
// Handle ctrl+c events.
if (signal(SIGINT, catch_exit) == SIG_ERR) {
printf("Could not set up signal handler.\n");
return -1;
}
// Create the camera object.
ScCamera *camera = NULL;
if (argc > 1) {
// Setup the camera from a device path. E.g. /dev/video1
// We use 4 image buffers.
camera = sc_camera_new_from_path(argv[1], 4);
} else {
// When no parameters are given, the camera is automatically detected.
camera = sc_camera_new();
}
if (camera == NULL) {
printf("No camera available.\n");
return -1;
}
uint32_t resolution_width = DEFAULT_RESOLUTION_WIDTH;
uint32_t resolution_height = DEFAULT_RESOLUTION_HEIGHT;
// Read the desired resolution form the command line.
if (argc == 4) {
resolution_width = atoi(argv[2]);
resolution_height = atoi(argv[3]);
}
// Get the supported resolutions and check
// if the desired resolution is supported
ScBool supported = SC_FALSE;
const uint32_t resolutions_size = 30;
ScSize resolutions[resolutions_size];
int32_t resolutions_found;
switch (resm) {
print_all_discrete_resolutions(camera);
// The camera supports a small set of predefined resolutions
resolutions_found = sc_camera_query_supported_resolutions(camera, &resolutions[0], resolutions_size);
if (!resolutions_found) {
printf("There was an error getting the discrete resolution capabilities of the camera.\n");
return -1;
}
for (int i = 0; i < resolutions_found; i++) {
if (resolutions[i].width == resolution_width &&
resolutions[i].height == resolution_height) {
supported = SC_TRUE;
break;
}
}
break;
// The camera supports a wide range of resolutions that are
// generated step-wise. Refer to documentation for further
// explanation.
printf("There was an error getting the stepwise resolution capabilities of the camera.\n");
return -1;
}
printf("This camera uses step-wise resolutions:\n");
printf("\tx: %u:%u:%u\n", swres.min_width, swres.step_width, swres.max_width);
printf("\ty: %u:%u:%u\n", swres.min_height, swres.step_height, swres.max_height);
if (swres.min_width <= resolution_width &&
resolution_width <= swres.max_width &&
swres.min_height <= resolution_height &&
resolution_height <= swres.max_height &&
resolution_width % swres.step_width == 0 &&
resolution_height % swres.step_height == 0) {
supported = SC_TRUE;
}
break;
default:
printf("Could not get camera resolution mode.\n");
return -1;
}
// Set the resolution
if (!supported) {
printf("%dx%d is not supported by this camera.\nPlease specify a supported resolution on the command line or in the source code.\n", resolution_width, resolution_height);
return -1;
}
ScSize desired_resolution;
desired_resolution.width = resolution_width;
desired_resolution.height = resolution_height;
if (!sc_camera_request_resolution(camera, desired_resolution)) {
printf("Setting resolution failed.\n");
return -1;
}
// Start streaming.
if (!sc_camera_start_stream(camera)) {
printf("Start the camera failed.\n");
return -1;
}
// Create a recognition context. Files created by the recognition context and the
// attached scanners will be written to this directory. In production environment,
// it should be replaced with writable path which does not get removed between reboots
sc_recognition_context_new(SCANDIT_SDK_LICENSE_KEY, "/tmp", NULL);
if (context == NULL) {
printf("Could not initialize context.\n");
return -1;
}
// Create barcode scanner with EAN13/UPCA and QR code scanning enabled.
// The default preset is optimized for real-time frame processing using a
// camera.
if (settings == NULL) {
return -1;
}
// We want to track at most one so that the command line output remains readable.
// In a more realistic MatrixScan scenario this number should be set to the number of
// expected codes that have to be tracked at the same time.
// We disable looking at a default scan area to get a smother MatrixScan experience
// Our camera has no auto-focus.
// Codes are most likely oriented from left to right.
// Only keep codes for one frame and do not accumulate anything.
// Accumulating many codes over a long scan session can slow down the scanning speed significantly.
// Create a barcode scanner for our context and settings.
if (scanner == NULL) {
return -1;
}
// The scanner is setup asynchronous.
// We could wait here using sc_barcode_scanner_wait_for_setup_completed if needed.
// Setup the object tracker and it's callbacks used for MatrixScan.
on_appeared,
on_updated,
on_lost,
on_predicted
};
// We don't pass custom data to the callbacks in this simple example.
// The tracker is enabled by default.
ScObjectTracker *tracker = sc_object_tracker_new(context, &callbacks, NULL);
// ... but it can be disabled on demand.
//sc_object_tracker_set_enabled(tracker, SC_FALSE);
// Signal a new frame sequence to the context.
// Create an image description that is reused for every frame.
process_frames = SC_TRUE;
while (process_frames) {
// Get the latest camera frame data and description
const uint8_t *image_data = sc_camera_get_frame(camera, image_descr);
if (image_data == NULL) {
printf("Frame access failed. Exiting.\n");
break;
}
// Process the frame.
ScProcessFrameResult result = sc_recognition_context_process_frame(context, image_descr, image_data);
printf("Processing frame failed with error %d: '%s'\n", result.status,
}
// Signal the camera that we are done reading the image buffer.
sc_camera_enqueue_frame_data(camera, image_data);
}
// Signal to the context that the frame sequence is finished.
// Cleanup all objects.
}
API for tracking objects across frames.
ScBool sc_camera_request_resolution(ScCamera *camera, ScSize resolution)
Tries to set the camera resolution.
A unsigned step-wise description of a size.
Definition: ScCamera.h:47
void sc_recognition_context_release(ScRecognitionContext *context)
Decrease reference count of recognition context by one.
int32_t sc_camera_query_supported_framerates(const ScCamera *camera, ScSize resolution, ScFramerate *framerate_array, uint32_t framerate_array_length)
Query supported discrete framerates of the camera at a given resolution.
uint32_t step_height
y dimension step size
Definition: ScCamera.h:53
ScByteArray sc_barcode_get_data(const ScBarcode *barcode)
Get the data encoded in the barcode.
void sc_barcode_scanner_settings_set_max_number_of_codes_per_frame(ScBarcodeScannerSettings *settings, uint32_t max_codes)
Set the maximum number of barcode to be decoded every frame.
Opaque pointer type for an object tracker.
Result status and frame id.
Definition: ScRecognitionContext.h:244
uint32_t min_height
minimum y dimension
Definition: ScCamera.h:51
void sc_barcode_scanner_release(ScBarcodeScanner *scanner)
Decrease reference count of barcode scanner by one.
ScBarcodeScanner * sc_barcode_scanner_new_with_settings(ScRecognitionContext *context, const ScBarcodeScannerSettings *settings)
Create a new barcode scanner instance with the given settings.
@ SC_SYMBOLOGY_UPCA
Definition: ScBarcode.h:45
ScBool sc_barcode_is_recognized(const ScBarcode *barcode)
Check whether the barcode was fully decoded (recognized).
An opaque data structure holding configuration options for the barcode scanner.
ScCameraMode
Describes the resolution mode of the camera.
Definition: ScCamera.h:129
void sc_barcode_scanner_settings_set_code_location_constraint_2d(ScBarcodeScannerSettings *settings, ScCodeLocationConstraint constraint)
Set the 2d code location constraint.
ScBarcodeScannerSettings * sc_barcode_scanner_settings_new_with_preset(ScBarcodeScannerSettingsPresetFlags preset)
Create a new barcode scanner settings object.
ScContextStatusFlag status
Execution status flag.
Definition: ScRecognitionContext.h:245
const char * sc_context_status_flag_get_message(ScContextStatusFlag status)
Get a human readable error message for a result status.
@ SC_SYMBOLOGY_QR
Definition: ScBarcode.h:69
Barcode Scanner interface.
void sc_recognition_context_start_new_frame_sequence(ScRecognitionContext *context)
Start processing a new batch of continuous frames.
void sc_barcode_scanner_settings_set_code_direction_hint(ScBarcodeScannerSettings *settings, ScCodeDirection direction)
Set the code direction hint.
ScTrackedObjectType
Type of the tracked object.
Definition: ScTrackedObject.h:25
void sc_barcode_scanner_settings_set_code_duplicate_filter(ScBarcodeScannerSettings *settings, int32_t filter)
Specifies the duplicate filter to use for the session.
ScBool sc_camera_enqueue_frame_data(ScCamera *camera, const uint8_t *frame_data)
Requeues the buffer after the data has been used.
A 2-dimensional polygon with 4 corners.
Definition: ScCommon.h:65
Opaque handle to a camera object.
#define SC_FALSE
False value.
Definition: ScConfig.h:139
void sc_barcode_scanner_settings_set_focus_mode(ScBarcodeScannerSettings *settings, ScCameraFocusMode focus_mode)
Set the camera's focus type.
Recognition context interface.
#define SC_TRUE
True value.
Definition: ScConfig.h:133
Camera creation and control interface.
uint32_t width
x dimension
Definition: ScCommon.h:140
void sc_barcode_scanner_settings_set_code_location_constraint_1d(ScBarcodeScannerSettings *settings, ScCodeLocationConstraint constraint)
Set the 1d code location constraint.
void sc_barcode_scanner_settings_release(ScBarcodeScannerSettings *settings)
Decrease reference count of barcode scanner settings object by one.
ScImageDescription * sc_image_description_new(void)
Create a new image description.
Callback storage structure. Set a callback to NULL to ignore it.
Definition: ScObjectTracker.h:38
@ SC_CAMERA_MODE_STEPWISE
the camera captures at a wide range of step-wise generated resolutions
Definition: ScCamera.h:132
void sc_image_description_release(ScImageDescription *description)
Decrease reference count of image description by one.
ScCamera * sc_camera_new(void)
Create a camera object using default values.
ScObjectTracker * sc_object_tracker_new(ScRecognitionContext *context, ScObjectTrackerCallbacks *callbacks, void *callback_user_data)
Create a new object tracker.
@ SC_SYMBOLOGY_EAN13
Definition: ScBarcode.h:37
ScBool sc_camera_start_stream(ScCamera *camera)
Tells the camera to start capturing images.
ScCameraMode sc_camera_get_resolution_mode(const ScCamera *camera)
Query the resolution mode of the camera.
uint32_t step_width
x dimension step size
Definition: ScCamera.h:50
Describes dimensions as well as internal memory layout of an image buffer.
@ SC_CODE_DIRECTION_LEFT_TO_RIGHT
Definition: ScBarcodeScannerSettings.h:82
uint32_t max_height
maximum y dimension
Definition: ScCamera.h:52
int32_t ScBool
Boolean value, can be SC_TRUE or SC_FALSE.
Definition: ScConfig.h:127
Scans barcodes in images.
Describes a framerate.
Definition: ScCamera.h:63
uint32_t min_width
minimum x dimension
Definition: ScCamera.h:48
A 2-dimensional unsigned size.
Definition: ScCommon.h:139
const char * sc_symbology_to_string(ScSymbology symbology)
Helper function to convert the symbology enum to a string.
ScProcessFrameResult sc_recognition_context_process_frame(ScRecognitionContext *context, const ScImageDescription *image_description, const uint8_t *image_data)
Process image frame with this recognition context.
@ SC_CAMERA_MODE_DISCRETE
the camera captures at a finite set of discrete resolutions
Definition: ScCamera.h:131
Opaque pointer type for an object tracker.
void sc_recognition_context_end_frame_sequence(ScRecognitionContext *context)
Signal that a batch of continuous frames ended.
@ SC_RECOGNITION_CONTEXT_STATUS_SUCCESS
The context status is okay. No error occured.
Definition: ScRecognitionContext.h:57
uint32_t sc_tracked_object_get_id(const ScTrackedObject *object)
Retrieve unique id for the tracked object.
Opaque recognition context data structure.
ScCamera * sc_camera_new_from_path(const char *device_path, uint32_t buffer_count)
Create a camera object from a device path.
void sc_camera_release(ScCamera *camera)
Decrease reference count of camera by one.
const uint8_t * sc_camera_get_frame(ScCamera *camera, ScImageDescription *image_description)
float sc_framerate_get_fps(const ScFramerate *frame_rate)
Returns the number of frames per second.
int32_t sc_camera_query_supported_resolutions(const ScCamera *camera, ScSize *resolution_array, uint32_t resolution_array_length)
Query supported discrete resolutions of the camera.
A located or recognized barcode/ 2d code in an image.
void sc_object_tracker_release(ScObjectTracker *tracker)
Decrease reference count of tracker object.
uint32_t height
y dimension
Definition: ScCommon.h:141
ScRecognitionContext * sc_recognition_context_new(const char *license_key, const char *writable_data_path, JNIEnv *env, jobject activity, const char *device_name)
Create a new recognition context (Android only).
A null terminated array of bytes.
@ SC_PRESET_NONE
Preset with all symbologies disabled.
Definition: ScBarcodeScannerSettings.h:32
void sc_barcode_scanner_settings_set_symbology_enabled(ScBarcodeScannerSettings *settings, ScSymbology symbology, ScBool enabled)
Enable/disable decoding of a certain symbology.
@ SC_CAMERA_FOCUS_MODE_FIXED
the camera cannot change its focus
Definition: ScCommon.h:208
ScBool sc_camera_query_supported_resolutions_stepwise(const ScCamera *camera, ScStepwiseResolution *resolutions)
Query supported step-wise resolutions of the camera.
ScSymbology sc_barcode_get_symbology(const ScBarcode *barcode)
Get the symbology of the barcode.
void sc_barcode_scanner_settings_set_code_caching_duration(ScBarcodeScannerSettings *settings, int32_t duration)
Determines how long codes are kept in the session.
uint32_t max_width
maximum x dimension
Definition: ScCamera.h:49
@ SC_CODE_LOCATION_IGNORE
The area can be defined but will not be used by the barcode scanner.
Definition: ScBarcodeScannerSettings.h:132