parallel-capture-sample.cpp
This advanced example illustrates multithreaded capturing.
The sample code allows you to capture and process 3D frames in a time-efficient manner by employing all available threads.
The files required for compiling this sample are packed in the archive. |
- Note
- The sample requires the Boost library to function. Before building the solution, make sure you have Boost version 1.51.0 installed in the root of your
C:
disk. If you have already installed a Boost of a different version, please edit the path to theBoostHome
variable in the..\samples\sdk-samples-user.props
file. Also, edit the<AdditionalLibraryDirectories>
path in..\samples\sdk-samples-common.props
.
/********************************************************************
*
* Project Artec 3D Scanning SDK Samples
*
* Purpose: Parallel capture sample
*
* Copyright: Artec Group
*
********************************************************************/
#include <string>
#include <iostream>
#include <iomanip>
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <boost/format.hpp>
#include <artec/sdk/base/Log.h>
#include <artec/sdk/base/IFrameMesh.h>
#include <artec/sdk/base/TArrayRef.h>
#include <artec/sdk/capturing/IScanner.h>
#include <artec/sdk/capturing/IFrame.h>
#include <artec/sdk/capturing/IFrameProcessor.h>
#include <artec/sdk/capturing/IArrayScannerId.h>
using namespace boost::chrono;
namespace asdk {
using namespace artec::sdk::base;
using namespace artec::sdk::capturing;
};
using asdk::TRef;
using asdk::TArrayRef;
// this constant determines the number of frames to collect.
const int NumberOfFramesToCapture = 100;
int main( int argc, char **argv )
{
// The log verbosity level is set here. It is set to the most
// verbose value - Trace. If you have any problems working with
// our examples, please do not hesitate to send us this extensive
// information along with your questions. However, if you feel
// comfortable with these Artec Scanning SDK code examples,
// we suggest you to set this level to asdk::VerboseLevel_Info.
TRef<asdk::IScanner> scanner;
{
TRef<asdk::IArrayScannerId> scannersList;
// Look for the scanners attached
std::wcout << L"Enumerating scanners... ";
{
std::wcout << L"failed" << std::endl;
return 1;
}
std::wcout << L"done" << std::endl;
// Check for any scanners found
if( scannersList->getSize() == 0 )
{
std::wcout << L"No scanners are found" << std::endl;
return 2;
}
// Connect to the first available scanner
TArrayRef<asdk::IArrayScannerId> scannersArray( scannersList );
for( int i = 0; i < scannersArray.size(); i++ )
{
std::wcout << L"Scanner " << scannersArray[i].serial << L" is found" << std::endl;
std::wcout << L"Connecting to the scanner... ";
{
std::wcout << L"failed" << std::endl;
continue;
}
std::wcout << L"done" << std::endl;
break;
}
if( !scanner )
{
std::wcout << L"No scanner can be connected to" << std::endl;
return 3;
}
}
// Start to work
int framesAlreadyCaptured = scanner->getFrameNumber();
// Storage for the frame meshes constructed
std::vector< TRef<asdk::IFrameMesh> > meshes;
meshes.resize( NumberOfFramesToCapture );
boost::mutex meshesProtection;
std::wcout << L"Capturing " << NumberOfFramesToCapture << " frames with " << boost::thread::hardware_concurrency() << L" threads" << std::endl;
high_resolution_clock::time_point startTime = high_resolution_clock::now();
// Start frame processing for every hard-supported thread available
boost::thread_group captureThreads;
for( unsigned i = 0; i < boost::thread::hardware_concurrency(); i++ )
{
captureThreads.create_thread( [&scanner, &meshes, &meshesProtection, framesAlreadyCaptured]
{
// Initialize a frame processor
TRef<asdk::IFrameProcessor> processor;
if( scanner->createFrameProcessor( &processor ) != asdk::ErrorCode_OK )
{
return;
}
while(true)
{
// Capture the next single frame image
TRef<asdk::IFrame> frame;
if( ec != asdk::ErrorCode_OK )
{
{
std::wcout << L"Capture error: frame capture timeout" << std::endl;
}
{
std::wcout << L"Capture error: frame corrupted" << std::endl;
}
{
std::wcout << L"Capture error: frame reconstruction failed" << std::endl;
}
{
std::wcout << L"Capture error: frame registration failed" << std::endl;
}
else
{
std::wcout << L"Capture error: unknown error" << std::endl;
}
continue;
}
int frameNumber = frame->getFrameNumber();
if( frameNumber >= NumberOfFramesToCapture + framesAlreadyCaptured )
{
return;
}
std::wcout << "frame " << std::setw( 4 ) << (frameNumber+1) << "\r";
// Reconstruct 3D mesh for the captured frame
TRef<asdk::IFrameMesh> mesh;
if( processor->reconstructAndTexturizeMesh( &mesh, frame ) != asdk::ErrorCode_OK )
{
std::wcout << L"Capture error: reconstruction failed for frame " << std::setw( 4 ) << (frameNumber+1) << std::endl;
continue;
}
// Calculate additional data
mesh->calculate( asdk::CM_Normals );
std::wcout << "mesh " << std::setw( 4 ) << (frameNumber+1) << "\r";
std::wcout.flush();
// Save the mesh for later use
boost::lock_guard<boost::mutex> guard( meshesProtection );
meshes[frameNumber - framesAlreadyCaptured] = mesh;
}
});
}
// Wait for the capture process to finish
captureThreads.join_all();
high_resolution_clock::time_point stopTime = high_resolution_clock::now();
float timeDelta = duration_cast<milliseconds>( stopTime - startTime ).count() / 1000.f;
float fps = NumberOfFramesToCapture / timeDelta;
std::wcout << "\nfps = " << std::fixed << std::setw( 4 ) << std::setprecision( 2 ) << fps << std::endl;
int successfullyCapturedMeshes = 0;
for( int i = 0; i < NumberOfFramesToCapture; i++ )
{
if( meshes[i] )
{
successfullyCapturedMeshes++;
}
}
std::wcout << NumberOfFramesToCapture << " shots captured with " << successfullyCapturedMeshes << " meshes constructed." << std::endl;
scanner = NULL;
std::wcout << L"Scanner released" << std::endl;
return 0;
}