Impact Acquire SDK C++
ContinuousCapture_BVS-3D-RV0.cpp

The ContinuousCapture_BVS-3D-RV0 program is based on the ContinuousCapture.cpp example concerning the acquisition implementation. The sample is intended for BVS 3D-RV0 devices only as it makes use of device specific settings which won't be supported by the majority of other devices. The sample will set up a device in a way that Multi-Part Format data will be delivered and will display intensitiy image buffer and confidence image buffer parts in two different display windows.

Since
2.50.0
Program location
The source file ContinuousCapture_BVS-3D-RV0.cpp is only part of this document so far, so in order to play around with it must be copied from here!
Note
The following device families are currently supported by this sample:
  • BVS 3D-RV0 (rc_visard)
ContinuousCapture_BVS-3D-RV0 example:
  1. Opens a BVS 3D-RV0 device.
  2. Configures the device in a way it will deliver multi-part data OR will terminate with an error message if the configuration fails.
  3. Captures buffers continuously and will display (Windows) or output information (on other platforms) for the both parts of the delivered buffer.
How it works
After getting the device from user input the sample opens the device (pDev->open()). Then the sample will try to set up the device accordingly by calling the configureDevice() function. The image acquisition will make use of the mvIMPACT::acquire::helper::RequestProvider class discussed in the ContinuousCapture.cpp example application. If necessary, the device will disable the pattern projector once the acquisition is stopped.
Used device settings:
//-----------------------------------------------------------------------------
bool configureDevice( Device* pDev )
//-----------------------------------------------------------------------------
{
ImageFormatControl ifc( pDev );
if( ifc.componentSelector.isValid() && ifc.componentSelector.isWriteable() )
{
if( !supportsEnumStringValue( ifc.componentSelector, "Confidence" ) )
{
return false;
}
ifc.componentSelector.writeS( "Confidence" );
ifc.componentEnable.write( TBoolean::bTrue );
if( !supportsEnumStringValue( ifc.componentSelector, "Disparity" ) )
{
return false;
}
ifc.componentSelector.writeS( "Disparity" );
ifc.componentEnable.write( TBoolean::bFalse );
}
else
{
return false;
}
AcquisitionControl acq( pDev );
if( !acq.exposureAuto.isValid() ||
!acq.exposureAuto.isWriteable() ||
!acq.acquisitionMultiPartMode.isValid() ||
!acq.acquisitionMultiPartMode.isWriteable() )
{
return false;
}
if( !supportsEnumStringValue( acq.exposureAuto, "Continuous" ) ||
!supportsEnumStringValue( acq.acquisitionMultiPartMode, "SynchronizedComponents" ) )
{
return false;
}
acq.exposureAuto.writeS( "Continuous" );
acq.acquisitionMultiPartMode.writeS( "SynchronizedComponents" );
ChunkDataControl cdc( pDev );
if( !cdc.chunkModeActive.isValid() || !cdc.chunkModeActive.isWriteable() )
{
return false;
}
cdc.chunkModeActive.write( TBoolean::bTrue );
DepthControl dctl( pDev );
if( !dctl.depthAcquisitionMode.isValid() ||
!dctl.depthAcquisitionMode.isWriteable() ||
!dctl.depthExposureAdaptTimeout.isValid() ||
!dctl.depthExposureAdaptTimeout.isWriteable() ||
!dctl.depthQuality.isValid() ||
!dctl.depthQuality.isWriteable() )
{
return false;
}
if( !supportsEnumStringValue( dctl.depthAcquisitionMode, "Continuous" ) ||
!supportsEnumStringValue( dctl.depthQuality, "High" ) ||
!supportsValue( dctl.depthExposureAdaptTimeout, 0.0 ) )
{
return false;
}
dctl.depthAcquisitionMode.writeS( "Continuous" );
dctl.depthExposureAdaptTimeout.write( 0.0 );
dctl.depthQuality.writeS( "High" );
return true;
}
Handling multi part data
Once the request object is ready the number of included multi part buffers can be obtained by calling mvIMPACT::acquire::Request::getBufferPartCount(). A specific buffer part can be used by calling mvIMPACT::acquire::Request::getBufferPart( ) and passing the number of the desired part to create a BufferPart object which can be used like a usual mvIMPACT::acquire::Request object afterwards.
//-----------------------------------------------------------------------------
void myThreadCallback( shared_ptr<Request> pRequest, ThreadParameter& threadParameter )
//-----------------------------------------------------------------------------
{
// display some statistical information every 100th image
if( threadParameter.requestsCaptured_ % 100 == 0 )
{
const Statistics& s = threadParameter.statistics_;
cout << "Info from " << threadParameter.pDev_->serial.read()
<< ": " << s.framesPerSecond.name() << ": " << s.framesPerSecond.readS()
<< ", " << s.errorCount.name() << ": " << s.errorCount.readS()
<< ", " << s.captureTime_s.name() << ": " << s.captureTime_s.readS() << endl;
}
if( pRequest->isOK() )
{
const unsigned int bufferPartCount = pRequest->getBufferPartCount();
if( bufferPartCount > 0 )
{
// data has been delivered in multi-part format
for( unsigned int i = 0; i < bufferPartCount; i++ )
{
const BufferPart& bufferPart( pRequest->getBufferPart( i ) );
const string pixelFormat = bufferPart.pixelFormat.readS();
#ifdef USE_DISPLAY
const TBufferPartDataType bufferDataType = bufferPart.dataType.read();
const int linePitch = static_cast<int>( bufferPart.linePitch.read() );
const int width = static_cast<int>( bufferPart.width.read() );
const int height = static_cast<int>( bufferPart.height.read() );
const int channelbBitDepth = static_cast<int>( bufferPart.channelBitDepth.read() );
cout << "Image captured: " << pRequest->imageWidth.read() << "x" << pRequest->imageHeight.read() << "buffer contains: " << bufferDataType << " data" << endl;
if( bufferDataType == bpdt2DImage )
{
threadParameter.displayWindowPrimary_.GetImageDisplay().SetImage( bufferPart.address.read(), width, height, channelbBitDepth, linePitch );
threadParameter.displayWindowPrimary_.GetImageDisplay().Update();
}
else if( bufferDataType == bpdtConfidenceMap )
{
threadParameter.displayWindowSecondary_.GetImageDisplay().SetImage( bufferPart.address.read(), width, height, channelbBitDepth, linePitch );
threadParameter.displayWindowSecondary_.GetImageDisplay().Update();
}
else
{
cout << "The data type of buffer part " << i << " of the current request is reported as " << bufferPart.dataType.readS() << ", which will NOT be handled by this example application" << endl;
}
#else
cout << "Image captured: " << pRequest->imageWidth.read() << "x" << pRequest->imageHeight.read() << "buffer contains: " << bufferPart.dataType.readS() << " data" << endl;
#endif // #ifdef USE_DISPLAY
}
}
}
else
{
cout << "Error: " << pRequest->requestResult.readS() << endl;
}
}
Source code
#include <apps/Common/exampleHelper.h>
#include <common/crt/mvstdio.h>
#include <iostream>
#include <mvIMPACT_CPP/mvIMPACT_acquire_helper.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire_GenICam.h>
#ifdef _WIN32
# include <mvDisplay/Include/mvIMPACT_acquire_display.h>
# define USE_DISPLAY
#endif // #ifdef _WIN32
using namespace mvIMPACT::acquire;
using namespace std;
//-----------------------------------------------------------------------------
struct ThreadParameter
//-----------------------------------------------------------------------------
{
Device* pDev_;
unsigned int requestsCaptured_;
Statistics statistics_;
#ifdef USE_DISPLAY
ImageDisplayWindow displayWindowPrimary_;
ImageDisplayWindow displayWindowSecondary_;
#endif // #ifdef USE_DISPLAY
explicit ThreadParameter( Device* pDev ) : pDev_( pDev ), requestsCaptured_( 0 ), statistics_( pDev )
#ifdef USE_DISPLAY
// initialise display window
// IMPORTANT: It's NOT safe to create multiple display windows in multiple threads!!!
, displayWindowPrimary_( "mvIMPACT_acquire sample, Device " + pDev_->serial.read() + " 2D Image" )
, displayWindowSecondary_( "mvIMPACT_acquire sample, Device " + pDev_->serial.read() + " 3D Data" )
#endif // #ifdef USE_DISPLAY
{}
ThreadParameter( const ThreadParameter& src ) = delete;
ThreadParameter& operator=( const ThreadParameter& rhs ) = delete;
};
//-----------------------------------------------------------------------------
void myThreadCallback( shared_ptr<Request> pRequest, ThreadParameter& threadParameter )
//-----------------------------------------------------------------------------
{
// display some statistical information every 100th image
if( threadParameter.requestsCaptured_ % 100 == 0 )
{
const Statistics& s = threadParameter.statistics_;
cout << "Info from " << threadParameter.pDev_->serial.read()
<< ": " << s.framesPerSecond.name() << ": " << s.framesPerSecond.readS()
<< ", " << s.errorCount.name() << ": " << s.errorCount.readS()
<< ", " << s.captureTime_s.name() << ": " << s.captureTime_s.readS() << endl;
}
if( pRequest->isOK() )
{
const unsigned int bufferPartCount = pRequest->getBufferPartCount();
if( bufferPartCount > 0 )
{
// data has been delivered in multi-part format
for( unsigned int i = 0; i < bufferPartCount; i++ )
{
const BufferPart& bufferPart( pRequest->getBufferPart( i ) );
const string pixelFormat = bufferPart.pixelFormat.readS();
#ifdef USE_DISPLAY
const TBufferPartDataType bufferDataType = bufferPart.dataType.read();
const int linePitch = static_cast<int>( bufferPart.linePitch.read() );
const int width = static_cast<int>( bufferPart.width.read() );
const int height = static_cast<int>( bufferPart.height.read() );
const int channelbBitDepth = static_cast<int>( bufferPart.channelBitDepth.read() );
cout << "Image captured: " << pRequest->imageWidth.read() << "x" << pRequest->imageHeight.read() << "buffer contains: " << bufferDataType << " data" << endl;
if( bufferDataType == bpdt2DImage )
{
threadParameter.displayWindowPrimary_.GetImageDisplay().SetImage( bufferPart.address.read(), width, height, channelbBitDepth, linePitch );
threadParameter.displayWindowPrimary_.GetImageDisplay().Update();
}
else if( bufferDataType == bpdtConfidenceMap )
{
threadParameter.displayWindowSecondary_.GetImageDisplay().SetImage( bufferPart.address.read(), width, height, channelbBitDepth, linePitch );
threadParameter.displayWindowSecondary_.GetImageDisplay().Update();
}
else
{
cout << "The data type of buffer part " << i << " of the current request is reported as " << bufferPart.dataType.readS() << ", which will NOT be handled by this example application" << endl;
}
#else
cout << "Image captured: " << pRequest->imageWidth.read() << "x" << pRequest->imageHeight.read() << "buffer contains: " << bufferPart.dataType.readS() << " data" << endl;
#endif // #ifdef USE_DISPLAY
}
}
}
else
{
cout << "Error: " << pRequest->requestResult.readS() << endl;
}
}
//-----------------------------------------------------------------------------
// This function will allow to select devices that support the GenICam interface
// layout(these are devices, that claim to be compliant with the GenICam standard)
// and that are bound to drivers that support the user controlled start and stop
// of the internal acquisition engine. Other devices will not be listed for
// selection as the code of the example relies on these features in the code.
bool isDeviceSupportedBySample( const Device* const pDev )
//-----------------------------------------------------------------------------
{
const string product = pDev->product.readS();
return ( product.find( "rc_visard" ) != std::string::npos );
}
//-----------------------------------------------------------------------------
bool configureDevice( Device* pDev )
//-----------------------------------------------------------------------------
{
ImageFormatControl ifc( pDev );
if( ifc.componentSelector.isValid() && ifc.componentSelector.isWriteable() )
{
if( !supportsEnumStringValue( ifc.componentSelector, "Confidence" ) )
{
return false;
}
ifc.componentSelector.writeS( "Confidence" );
ifc.componentEnable.write( TBoolean::bTrue );
if( !supportsEnumStringValue( ifc.componentSelector, "Disparity" ) )
{
return false;
}
ifc.componentSelector.writeS( "Disparity" );
ifc.componentEnable.write( TBoolean::bFalse );
}
else
{
return false;
}
AcquisitionControl acq( pDev );
if( !acq.exposureAuto.isValid() ||
!acq.exposureAuto.isWriteable() ||
!acq.acquisitionMultiPartMode.isValid() ||
!acq.acquisitionMultiPartMode.isWriteable() )
{
return false;
}
if( !supportsEnumStringValue( acq.exposureAuto, "Continuous" ) ||
!supportsEnumStringValue( acq.acquisitionMultiPartMode, "SynchronizedComponents" ) )
{
return false;
}
acq.exposureAuto.writeS( "Continuous" );
acq.acquisitionMultiPartMode.writeS( "SynchronizedComponents" );
ChunkDataControl cdc( pDev );
if( !cdc.chunkModeActive.isValid() || !cdc.chunkModeActive.isWriteable() )
{
return false;
}
cdc.chunkModeActive.write( TBoolean::bTrue );
DepthControl dctl( pDev );
if( !dctl.depthAcquisitionMode.isValid() ||
!dctl.depthAcquisitionMode.isWriteable() ||
!dctl.depthExposureAdaptTimeout.isValid() ||
!dctl.depthExposureAdaptTimeout.isWriteable() ||
!dctl.depthQuality.isValid() ||
!dctl.depthQuality.isWriteable() )
{
return false;
}
if( !supportsEnumStringValue( dctl.depthAcquisitionMode, "Continuous" ) ||
!supportsEnumStringValue( dctl.depthQuality, "High" ) ||
!supportsValue( dctl.depthExposureAdaptTimeout, 0.0 ) )
{
return false;
}
dctl.depthAcquisitionMode.writeS( "Continuous" );
dctl.depthExposureAdaptTimeout.write( 0.0 );
dctl.depthQuality.writeS( "High" );
return true;
}
//-----------------------------------------------------------------------------
int main( void )
//-----------------------------------------------------------------------------
{
DeviceManager devMgr;
Device* pDev = getDeviceFromUserInput( devMgr, isDeviceSupportedBySample );
if( pDev == nullptr )
{
cout << "Unable to continue! Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
// if this device offers the 'GenICam' interface switch it on, as this will
// allow are better control over GenICam compliant devices
conditionalSetProperty( pDev->interfaceLayout, dilGenICam, true );
// if this device offers a user defined acquisition start/stop behavior
// enable it as this allows finer control about the streaming behavior
conditionalSetProperty( pDev->acquisitionStartStopBehaviour, assbUser, true );
if( !pDev->isOpen() )
{
pDev->open();
}
else
{
cout << "Unable to continue! The selected device could not be opnened. Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
cout << "Initialising the device. This might take some time..." << endl;
if( !configureDevice( pDev ) )
{
cout << "Unable to continue! The selected device does not support some of the required features. Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
ThreadParameter threadParam( pDev );
helper::RequestProvider requestProvider( pDev );
cout << "Press [ENTER] to stop the acquisition thread" << endl;
requestProvider.acquisitionStart( myThreadCallback, std::ref( threadParam ) );
cin.get();
requestProvider.acquisitionStop();
return 0;
}
Contains information about a specific part of a captured buffer.
Definition mvIMPACT_acquire.h:8410
std::string name(void) const
Returns the name of the component referenced by this object.
Definition mvIMPACT_acquire.h:1206
Grants access to devices that can be operated by this software interface.
Definition mvIMPACT_acquire.h:7171
This class and its functions represent an actual device detected by this interface in the current sys...
Definition mvIMPACT_acquire.h:6118
PropertyS product
A string property (read-only) containing the product name of this device.
Definition mvIMPACT_acquire.h:6537
PropertyS serial
A string property (read-only) containing the serial number of this device.
Definition mvIMPACT_acquire.h:6551
void open(void)
Opens a device.
Definition mvIMPACT_acquire.h:6420
PropertyIDeviceInterfaceLayout interfaceLayout
An enumerated integer property which can be used to define which interface layout shall be used when ...
Definition mvIMPACT_acquire.h:6644
bool isOpen(void) const
Returns the current initialisation status in this process.
Definition mvIMPACT_acquire.h:6363
PropertyIAcquisitionStartStopBehaviour acquisitionStartStopBehaviour
An enumerated integer property defining the start/stop behaviour during acquisition of this driver in...
Definition mvIMPACT_acquire.h:6800
Category for the acquisition and trigger control features.
Definition mvIMPACT_acquire_GenICam.h:2115
Category that contains the Chunk Data control features.
Definition mvIMPACT_acquire_GenICam.h:11823
Adjustment and triggering of the depth image for 3D control.
Definition mvIMPACT_acquire_GenICam.h:11048
Category for Image Format Control features.
Definition mvIMPACT_acquire_GenICam.h:1132
std::string read(int index=0) const
Reads a value from a property.
Definition mvIMPACT_acquire.h:5323
std::string readS(int index=0, const std::string &format="") const
Reads data from this property as a string.
Definition mvIMPACT_acquire.h:3340
Contains basic statistical information.
Definition mvIMPACT_acquire.h:14509
PropertyF framesPerSecond
A float property (read-only) containing the current number of frames captured per second.
Definition mvIMPACT_acquire.h:14586
PropertyF captureTime_s
A float property (read-only) containing the overall time an image request spent in the device drivers...
Definition mvIMPACT_acquire.h:14560
PropertyI errorCount
An integer property (read-only) containing the overall count of image requests which returned with an...
Definition mvIMPACT_acquire.h:14568
A class that can be used to display images in a window.
Definition mvIMPACT_acquire_display.h:606
A helper class that can be used to implement a simple continuous acquisition from a device.
Definition mvIMPACT_acquire_helper.h:432
TBufferPartDataType
Defines buffer part data types.
Definition TBufferPartDataType.h:41
This namespace contains classes and functions belonging to the GenICam specific part of the image acq...
Definition mvIMPACT_acquire.h:23830
This namespace contains classes and functions that can be used to display images.
This namespace contains classes and functions belonging to the image acquisition module of this SDK.
Definition mvCommonDataTypes.h:34