mvIMPACT Acquire SDK C++
CameraDescriptions.cpp

The CameraDescriptions program is a simple example, which shows, how to work with camera descriptions e.g. how to access, select and display. With each selected description the sample tries to acquire images with the capture parameters as defined by the camera description within a live thread. The sample is based on the ContinuousCapture.cpp example. After the user has selected a device it also will acquire a live image and displays it. Therefore this part of the sample will not be discussed here. Information about this part of the sample can be found in the other sample.

Program location
The source file CameraDescriptions.cpp can be found under:
%INSTALLDIR%\apps\CameraDescriptions\
Note
If you have installed the package without example applications, the source code as well as the executable will not be available. On Windows the sample application can be installed or removed from the target system at any time by simply restarting the installation package.
CameraDescriptions example:
  1. Opens a MATRIX VISION device.
  2. Snaps images using the capture parameters defined by the camera description (without display using Linux).
Console Output
This sample is meant for devices that support camera descriptions only. Other de
vices might be installed
but won't be recognized by the application.

[2]: DE039924901 (mvDELTA, Family: mvSIGMA, interface layout: DeviceSpecific)
[3]: MG347729864 (mvGAMMA-G, Family: mvTITAN, interface layout: DeviceSpecific)

Please enter the number in front of the listed device followed by [ENTER] to ope
n it: 3
Using device number 3.
Initialising device MG347729864. This might take some time...
download C:\Windows\system32\titan.bin...
   size=1370484 al=64 sdram=$fd000000..+8M mmio=$fe800000 load=$05B20000 cpu_clk
=166666750 MHz
   relocate...
   get memory image...
   download ok

Available camera descriptions: 4
----------------------------------
  [0]: Standard_Generic
  [1]: NonStandard_Generic
  [2]: Standard_Jai_CV-M30
  [3]: Standard_mvCam1

Please select a camera description to use for this sample (numerical value):
...
How it works
After starting the sample the user can select the device. After it the sample will initialize the device. Then the sample will check, if the device is a frame grabber, because currently only frame grabbers support camera descriptions. For cameras (e.g. like the mvBlueFOX) this feature wouldn't make any sense anyway as here the capture device is the same as the image source thus nothing needs to be adapted to one another:
CameraSettingsFrameGrabber cs(pDev);
if( !cs.type.isValid() )
{
cout << "Device " << pDev->serial.read() << " doesn't seem to support camera descriptions." << endl
<< "Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}

Now in a loop the user can select the camera description (function "selectCameraDescriptionFromUserInput()"). This function displays all available camera descriptions for this device an allows the user to select one of them:

//-----------------------------------------------------------------------------
void selectCameraDescriptionFromUserInput( CameraSettingsFrameGrabber& cs )
//-----------------------------------------------------------------------------
{
// display the name of every camera description available for this device.
// this might be less than the number of camera descriptions available on the system as e.g.
// an analog frame grabber can't use descriptions for digital cameras
vector<pair<string, int> > vAvailableDescriptions;
cs.type.getTranslationDict( vAvailableDescriptions );
cout << endl << "Available camera descriptions: " << vAvailableDescriptions.size() << endl
<< "----------------------------------" << endl;
for_each( vAvailableDescriptions.begin(), vAvailableDescriptions.end(), DisplayDictEntry<int>() );
cout << endl << "Please select a camera description to use for this sample (numerical value): ";
int cameraDescriptionToUse;
cin >> cameraDescriptionToUse;
// remove the '\n' from the stream
cin.get();
// wrong input will raise an exception
// The camera description contains all the parameters needed to capture the associated video
// signal. Camera descriptions for a certain camera can be obtained from MATRIX VISION. Experienced
// users can also create their own camera descriptions using wxPropView. The documentation will
// explain how to create and configure camera description files
cs.type.write( cameraDescriptionToUse );
}

More camera descriptions can either be obtained from MATRIX VISION or can be created using PropView. This manual describes how to do that as well. Once a camera description has been created it should not be modified from within an application as it is meant to represent the actual camera, which can be modified either. The only exception is when a camera is programmed to operate in a different mode. However even in this case it might make sense to consider creating a second camera definition for this camera. On Windows all camera descriptions must be stored under

%ALLUSERS%\Documents\MATRIX VISION\mvIMPACT acquire\CameraFiles

or

%MVIMPACT_ACQUIRE_DATA_DIR%\CameraFiles

which will point to the same folder, on Linux this directory will be

/etc/matrix-vision/mvimpact-acquire/camerafiles

while under other platforms these files should end up in the current working directory if no custom directory has been defined. An application can define a custom path by modifying the property mvIMPACT::acquire::Device::customDataDirectory.

Note
Camera descriptions stored under a different location will NOT be recognized by the driver!

Thereafter the user can display and modify the connector representation of the capture device:

cout << endl << "Current connector settings:" << endl
<< " Camera output: " << connector.cameraOutputUsed.readS() << endl
<< " Grabber input: " << connector.videoChannel.read() << "(" << connector.pinDescription.read() << ")" << endl;

By pressing "o" the user can select one of the camera outputs defined by the camera description:

if( cmd == "o" )
{
cout << "Available camera outputs as defined by the camera description:" << endl;
vector<pair<string, TCameraOutput> > v;
// query the properties translation dictionary, which will contain every camera description
// recognized by this device
connector.cameraOutputUsed.getTranslationDict( v );
for_each( v.begin(), v.end(), DisplayDictEntry<int>() );
cout << "Enter the new (numerical) value: ";
int newOutput;
cin >> newOutput;
try
{
connector.cameraOutputUsed.write( static_cast<TCameraOutput>(newOutput) );
}
catch( const ImpactAcquireException& e )
{
cout << e.getErrorString() << endl;
}
}
TCameraOutput
Defines valid ways a camera can offer image data to a capture device.
Definition: mvDriverBaseEnums.h:914

By pressing "i" the input of the frame grabber can be selected:

if( cmd == "i" )
{
// The allowed range depends on the currently selected camera output as e.g. for
// a RGB camera signal 3 video input are required on the device side, while a
// composite signal just requires 1.
cout << "Allowed grabber video inputs in the current camera output mode: "
<< connector.videoChannel.read( plMinValue ) << " - "
<< connector.videoChannel.read( plMaxValue ) << endl;
cout << "Enter the new (numerical) value: ";
int newVideoInput;
cin >> newVideoInput;
try
{
connector.videoChannel.write( newVideoInput );
}
catch( const ImpactAcquireException& e )
{
cout << e.getErrorString() << endl;
}
}
@ plMinValue
Set/Get the minimum value for this mvIMPACT::acquire::Property.
Definition: mvIMPACT_acquire.h:2885
@ plMaxValue
Set/Get the maximum value for this mvIMPACT::acquire::Property.
Definition: mvIMPACT_acquire.h:2878

Now the user can press on any key to acquire and start a live acquisition and any key again to stop the live acquisition and return back to the camera description selection menu again. This can be left by pressing "q". Afterwards the application will terminate.

Source code
#include <algorithm>
#include <iostream>
#include <set>
#include <thread>
#include <apps/Common/exampleHelper.h>
#ifdef _WIN32
# define USE_DISPLAY
#endif // #ifdef _WIN32
using namespace std;
using namespace mvIMPACT::acquire;
//-----------------------------------------------------------------------------
struct ThreadParameter
//-----------------------------------------------------------------------------
{
Device* pDev_;
unsigned int requestsCaptured_;
Statistics statistics_;
#ifdef USE_DISPLAY
ImageDisplayWindow displayWindow_;
#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!!!
, displayWindow_( "mvIMPACT_acquire sample, Device " + pDev_->serial.read() )
#endif // #ifdef USE_DISPLAY
{}
ThreadParameter( const ThreadParameter& src ) = delete;
ThreadParameter& operator=( const ThreadParameter& rhs ) = delete;
};
//-----------------------------------------------------------------------------
void myThreadCallback( shared_ptr<Request> pRequest, ThreadParameter& threadParameter )
//-----------------------------------------------------------------------------
{
++threadParameter.requestsCaptured_;
// 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() )
{
#ifdef USE_DISPLAY
threadParameter.displayWindow_.GetImageDisplay().SetImage( pRequest );
threadParameter.displayWindow_.GetImageDisplay().Update();
#else
cout << "Image captured: " << pRequest->imageOffsetX.read() << "x" << pRequest->imageOffsetY.read() << "@" << pRequest->imageWidth.read() << "x" << pRequest->imageHeight.read() << endl;
#endif // #ifdef USE_DISPLAY
}
else
{
cout << "Error: " << pRequest->requestResult.readS() << endl;
}
}
//-----------------------------------------------------------------------------
void modifyConnectorFromUserInput( Connector& connector )
//-----------------------------------------------------------------------------
{
bool boRun = true;
while( boRun )
{
cout << endl << "Current connector settings:" << endl
<< " Camera output: " << connector.cameraOutputUsed.readS() << endl
<< " Grabber input: " << connector.videoChannel.read() << "(" << connector.pinDescription.read() << ")" << endl;
cout << "Press" << endl
<< " 'o' to select a different camera output" << endl
<< " 'i' to select a different grabber input" << endl
<< " any other key when done" << endl;
string cmd;
cin >> cmd;
// remove the '\n' from the stream
cin.get();
if( cmd == "o" )
{
cout << "Available camera outputs as defined by the camera description:" << endl;
vector<pair<string, TCameraOutput> > v;
// query the properties translation dictionary, which will contain every camera description
// recognized by this device
connector.cameraOutputUsed.getTranslationDict( v );
for_each( v.begin(), v.end(), DisplayDictEntry<int>() );
cout << "Enter the new (numerical) value: ";
int newOutput;
cin >> newOutput;
try
{
connector.cameraOutputUsed.write( static_cast<TCameraOutput>( newOutput ) );
}
catch( const ImpactAcquireException& e )
{
cout << e.getErrorString() << endl;
}
}
else if( cmd == "i" )
{
// The allowed range depends on the currently selected camera output as e.g. for
// a RGB camera signal 3 video input are required on the device side, while a
// composite signal just requires 1.
cout << "Allowed grabber video inputs in the current camera output mode: " <<
connector.videoChannel.read( plMinValue ) << " - " <<
connector.videoChannel.read( plMaxValue ) << endl;
cout << "Enter the new (numerical) value: ";
int newVideoInput;
cin >> newVideoInput;
try
{
connector.videoChannel.write( newVideoInput );
}
catch( const ImpactAcquireException& e )
{
cout << e.getErrorString() << endl;
}
}
else
{
boRun = false;
continue;
}
}
}
//-----------------------------------------------------------------------------
void selectCameraDescriptionFromUserInput( CameraSettingsFrameGrabber& cs )
//-----------------------------------------------------------------------------
{
// display the name of every camera description available for this device.
// this might be less than the number of camera descriptions available on the system as e.g.
// an analog frame grabber can't use descriptions for digital cameras
vector<pair<string, int> > vAvailableDescriptions;
cs.type.getTranslationDict( vAvailableDescriptions );
cout << endl << "Available camera descriptions: " << vAvailableDescriptions.size() << endl
<< "----------------------------------" << endl;
for_each( vAvailableDescriptions.begin(), vAvailableDescriptions.end(), DisplayDictEntry<int>() );
cout << endl << "Please select a camera description to use for this sample (numerical value): ";
int cameraDescriptionToUse;
cin >> cameraDescriptionToUse;
// remove the '\n' from the stream
cin.get();
// wrong input will raise an exception
// The camera description contains all the parameters needed to capture the associated video
// signal. Camera descriptions for a certain camera can be obtained from MATRIX VISION. Experienced
// users can also create their own camera descriptions using wxPropView. The documentation will
// explain how to create and configure camera description files
cs.type.write( cameraDescriptionToUse );
}
//-----------------------------------------------------------------------------
bool isDeviceSupportedBySample( const Device* const pDev )
//-----------------------------------------------------------------------------
{
return pDev->hasCapability( dcCameraDescriptionSupport );
}
//-----------------------------------------------------------------------------
int main( void )
//-----------------------------------------------------------------------------
{
DeviceManager devMgr;
cout << "This sample is meant for devices that support camera descriptions only. Other devices might be installed" << endl
<< "but won't be recognized by the application." << endl
<< endl;
Device* pDev = getDeviceFromUserInput( devMgr, isDeviceSupportedBySample );
if( pDev == nullptr )
{
cout << "Unable to continue! Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
cout << "Initialising device " << pDev->serial.read() << ". This might take some time..." << endl;
try
{
pDev->open();
}
catch( const ImpactAcquireException& e )
{
// this e.g. might happen if the same device is already opened in another process...
cout << "An error occurred while opening the device(error code: " << e.getErrorCode() << ")." << endl
<< "Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
// Assume that this is a frame grabber as currently only these devices support camera descriptions
CameraSettingsFrameGrabber cs( pDev );
if( !cs.type.isValid() )
{
cout << "Device " << pDev->serial.read() << " doesn't seem to support camera descriptions." << endl
<< "Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
Connector connector( pDev );
CameraDescriptionManager cdm( pDev );
bool boRun = true;
while( boRun )
{
try
{
selectCameraDescriptionFromUserInput( cs );
cdm.getStandardCameraDescriptionCount();
modifyConnectorFromUserInput( connector );
// start the execution of the 'live' thread.
cout << endl << "Press [ENTER] to end the acquisition" << endl << endl;
ThreadParameter threadParam( pDev );
helper::RequestProvider requestProvider( pDev );
requestProvider.acquisitionStart( myThreadCallback, std::ref( threadParam ) );
cin.get();
requestProvider.acquisitionStop();
cout << endl << "Press 'q' followed by [ENTER] to end to application or any other key followed by [ENTER] to select a different camera description: ";
string cmd;
cin >> cmd;
if( cmd == "q" )
{
boRun = false;
continue;
}
}
catch( const ImpactAcquireException& e )
{
cout << "Invalid selection (Error message: " << e.getErrorString() << ")" << endl
<< "Please make a valid selection" << endl;
}
}
return 0;
}
@ dcCameraDescriptionSupport
This device supports camera descriptions.
Definition: mvDriverBaseEnums.h:1815
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.