This article is a review of the C++ OpenCV samples that ship with the DUO SDK. This will be updated as new features are added or specifications updated to the DUO API. In the Developers/Samples folder within the SDK download you can find the latest version of these samples with a cmake project to generate specific IDE projects (Visual Studio/Qt Creator).
Before reading this guide it is recommended to review our API and SDK Docs to get an understanding of the design, common practices and usage. With DUO devices you will always receive a "frame" which contains all relevant sensor data. The following examples showcase the usage of the DUOFrame structure while using different device functions. Also make sure you have the latest SDK download and OpenCV.
Here are some of the common methods used through-out the examples:
And variables/structures:
The including the DUOLib and OpenCV libraries (which may vary dependant on compiler).
#include "DUOLib.h" #include "opencv2/opencv.hpp" using namespace cv;
Demonstrates polling mechanism for capturing and display of frames using the OpenCV library (opencv.org).
Utilizing all highlighted methods/structures from Samples 1-4 and the polling technique from Sample 5.
We use these specific OpenCV functions/structures:
#ifndef SAMPLE_H
#define SAMPLE_H
// Platform Specific
...
// Include DUO API header file
#include "DUOLib.h"
#include "opencv2/opencv.hpp"
using namespace cv;
// Some global variables
static DUOInstance _duo = NULL;
static PDUOFrame _pFrameData = NULL;
// Platform Specific
...
// One and only duo callback function
// It sets the current frame data and signals that the new frame data is ready
static void CALLBACK DUOCallback(const PDUOFrame pFrameData, void *pUserData)
{
_pFrameData = pFrameData;
SetEvent(_evFrame);
}
// Opens, sets current image format and fps and starts capturing
static bool OpenDUOCamera(int width, int height, float fps)
{
if(_duo != NULL)
{
StopDUO(_duo);
CloseDUO(_duo);
_duo = NULL;
}
// Find optimal binning parameters for given (width, height)
// This maximizes sensor imaging area for given resolution
int binning = DUO_BIN_NONE;
if(width <= 752/2)
binning += DUO_BIN_HORIZONTAL2;
if(height <= 480/4)
binning += DUO_BIN_VERTICAL4;
else if(height <= 480/2)
binning += DUO_BIN_VERTICAL2;
// Check if we support given resolution (width, height, binning, fps)
DUOResolutionInfo ri;
if(!EnumerateDUOResolutions(&ri, 1, width, height, binning, fps))
return 0;
if(!OpenDUO(&_duo))
return 0;
char tmp[260];
// Get and print some DUO parameter values
GetDUODeviceName(_duo,tmp);
printf("DUO Device Name: '%s'\n", tmp);
GetDUOSerialNumber(_duo, tmp);
printf("DUO Serial Number: %s\n", tmp);
GetDUOFirmwareVersion(_duo, tmp);
printf("DUO Firmware Version: v%s\n", tmp);
GetDUOFirmwareBuild(_duo, tmp);
printf("DUO Firmware Build: %s\n", tmp);
// Set selected resolution
SetDUOResolutionInfo(_duo, ri);
// Start capture
if(!StartDUO(_duo, DUOCallback, NULL))
return 0;
return true;
}
// Waits until the new DUO frame is ready and returns it
static PDUOFrame GetDUOFrame()
{
if(_duo == NULL)
return 0;
if(WaitForSingleObject(_evFrame, 1000) == WAIT_OBJECT_0)
return _pFrameData;
else
return NULL;
}
// Stops capture and closes the camera
static void CloseDUOCamera()
{
if(_duo == NULL)
return;
// Stop capture
StopDUO(_duo);
// Close DUO
CloseDUO(_duo);
_duo = NULL;
}
static void SetExposure(float value)
{
if(_duo == NULL)
return;
SetDUOExposure(_duo, value);
}
static void SetGain(float value)
{
if(_duo == NULL)
return;
SetDUOGain(_duo, value);
}
static void SetLed(float value)
{
if(_duo == NULL)
return;
SetDUOLedPWM(_duo, value);
}
#endif // SAMPLE_H
As for the implementation we go through the following steps:
#include "Sample.h"
#define WIDTH 640
#define HEIGHT 480
#define FPS 30
int main(int argc, char* argv[])
{
printf("DUOLib Version: v%s\n", GetDUOLibVersion());
// Open DUO camera and start capturing
if(!OpenDUOCamera(WIDTH, HEIGHT, FPS))
{
printf("Could not open DUO camera\n");
return 0;
}
printf("\nHit to exit.\n");
// Create OpenCV windows
cvNamedWindow("Left");
cvNamedWindow("Right");
// Create image headers for left & right frames
IplImage *left, *right;
// Set exposure and LED brightness
SetGain(0);
SetExposure(50);
SetLed(25);
bool first = true;
// Run capture loop until key is pressed
while((cvWaitKey(1) & 0xff) != 27)
{
// Capture DUO frame
PDUOFrame pFrameData = GetDUOFrame();
if(pFrameData == NULL) continue;
// Set the image data
if(first)
{
first = false;
left = cvCreateImageHeader(cvSize(WIDTH, HEIGHT), IPL_DEPTH_8U, 1);
right = cvCreateImageHeader(cvSize(WIDTH, HEIGHT), IPL_DEPTH_8U, 1);
}
left->imageData = (char*)pFrameData->leftData;
right->imageData = (char*)pFrameData->rightData;
// Process images here (optional)
// Display images
cvShowImage("Left", left);
cvShowImage("Right", right);
}
cvDestroyAllWindows();
// Release image headers
cvReleaseImageHeader(&left);
cvReleaseImageHeader(&right);
// Close DUO camera
CloseDUOCamera();
return 0;
}
Demonstrates implementation of hardware background subtraction using programmable illumination on the DUO MLX using the OpenCV library (opencv.org).
Utilizing all highlighted methods/structures from Samples 1-4 and the polling technique from Sample 5.
We use these specific OpenCV functions/structures:
#ifndef SAMPLE_H
#define SAMPLE_H
// Platform Specific
...
// Include DUO API header file
#include "DUOLib.h"
#include "opencv2/opencv.hpp"
using namespace cv;
// Some global variables
static DUOInstance _duo = NULL;
static PDUOFrame _pFrameData = NULL;
// Platform Specific
...
// One and only duo callback function
// It sets the current frame data and signals that the new frame data is ready
static void CALLBACK DUOCallback(const PDUOFrame pFrameData, void *pUserData)
{
_pFrameData = pFrameData;
SetEvent(_evFrame);
}
// Opens, sets current image format and fps and starts capturing
static bool OpenDUOCamera(int width, int height, float fps)
{
if(_duo != NULL)
{
StopDUO(_duo);
CloseDUO(_duo);
_duo = NULL;
}
// Find optimal binning parameters for given (width, height)
// This maximizes sensor imaging area for given resolution
int binning = DUO_BIN_NONE;
if(width <= 752/2)
binning += DUO_BIN_HORIZONTAL2;
if(height <= 480/4)
binning += DUO_BIN_VERTICAL4;
else if(height <= 480/2)
binning += DUO_BIN_VERTICAL2;
// Check if we support given resolution (width, height, binning, fps)
DUOResolutionInfo ri;
if(!EnumerateDUOResolutions(&ri, 1, width, height, binning, fps))
return 0;
if(!OpenDUO(&_duo))
return 0;
char tmp[260];
// Get and print some DUO parameter values
GetDUODeviceName(_duo,tmp);
printf("DUO Device Name: '%s'\n", tmp);
GetDUOSerialNumber(_duo, tmp);
printf("DUO Serial Number: %s\n", tmp);
GetDUOFirmwareVersion(_duo, tmp);
printf("DUO Firmware Version: v%s\n", tmp);
GetDUOFirmwareBuild(_duo, tmp);
printf("DUO Firmware Build: %s\n", tmp);
// Set selected resolution
SetDUOResolutionInfo(_duo, ri);
// Start capture
if(!StartDUO(_duo, DUOCallback, NULL))
return 0;
return true;
}
// Waits until the new DUO frame is ready and returns it
static PDUOFrame GetDUOFrame()
{
if(_duo == NULL)
return 0;
if(WaitForSingleObject(_evFrame, 1000) == WAIT_OBJECT_0)
return _pFrameData;
else
return NULL;
}
// Stops capture and closes the camera
static void CloseDUOCamera()
{
if(_duo == NULL)
return;
// Stop capture
StopDUO(_duo);
// Close DUO
CloseDUO(_duo);
_duo = NULL;
}
static void SetExposure(float value)
{
if(_duo == NULL)
return;
SetDUOExposure(_duo, value);
}
static void SetGain(float value)
{
if(_duo == NULL)
return;
SetDUOGain(_duo, value);
}
static void SetLed(float value)
{
if(_duo == NULL)
return;
SetDUOLedPWM(_duo, value);
}
#endif // SAMPLE_H
As for the implementation we go through the following steps:
#include "Sample.h"
#define WIDTH 320
#define HEIGHT 240
#define FPS 60
// Setup LED sequence where LEDs are on (100%) in first frame and off (0%) in the second.
// This sequence is constantly repeated.
// The returned DUOFrame will contain the sequence index in ledSeqTag value.
DUOLEDSeq ledSequence[] =
{
{ 100, 100, 100, },
{ 0, 0, 0, },
};
int main(int argc, char* argv[])
{
printf("DUOLib Version: v%s\n", GetDUOLibVersion());
// Open DUO camera and start capturing
if(!OpenDUOCamera(WIDTH, HEIGHT, FPS))
{
printf("Could not open DUO camera\n");
return 0;
}
printf("\nHit to exit.\n");
// Set exposure and LED brightness
SetGain(0);
SetExposure(50);
// Set the LED sequence
SetDUOLedPWMSeq(_duo, ledSequence, sizeof(ledSequence)/sizeof(DUOLEDSeq));
// Create image headers for left, right and background frames
Mat left, right;
Mat leftBg, rightBg;
// Run capture loop until key is pressed
while((cvWaitKey(1) & 0xff) != 27)
{
// Capture DUO frame
PDUOFrame pFrameData = GetDUOFrame();
if(pFrameData == NULL) continue;
if(pFrameData->ledSeqTag == 0)
{
// LEDs are on
left = Mat(Size(WIDTH, HEIGHT), CV_8UC1, pFrameData->leftData);
right = Mat(Size(WIDTH, HEIGHT), CV_8UC1, pFrameData->rightData);
}
else
{
// LEDs are off
leftBg = Mat(Size(WIDTH, HEIGHT), CV_8UC1, pFrameData->leftData);
rightBg = Mat(Size(WIDTH, HEIGHT), CV_8UC1, pFrameData->rightData);
}
// Display background subtracted images
if(!left.empty() && !leftBg.empty() &&
!right.empty() && !rightBg.empty())
{
imshow("Left", left - leftBg);
imshow("Right", right - rightBg);
}
}
destroyAllWindows();
// Close DUO camera
CloseDUOCamera();
return 0;
}