What are the differences concerning programming between mvBlueFOX and mvBlueFOX3?

mvBlueFOX, mvBlueFOX-M, mvBlueFOX-MLC, mvBlueFOX-IGC, mvBlueFOX3

For all MATRIX VISION products there is an unified driver interface called mvIMPACT Acquire. The only difference between

is the Interface Layout.

For mvBlueFOX you have MATRIX VISION's specific Interface Layout "DeviceSpecific".
In contrast, mvBlueFOX3 bases on the image processing standards USB3 Vision and "GenICam".

USB3 Vision controls the communication via USB 3.0 between image acquisition device and the application. The GenICam standard unifies the access to the parameters of the devices. Additionally, the standard names the parameters and the values via the Standard Feature Naming Convention. You will find the current version of the SFNC on the website of the EMVA.

What does this mean for a programmer and the adoption of "old" code when changing the camera?

Basically, you can adopt the mvIMPACT Acquire based code to a large extend. I.e., the part where you

  • address and open the camera and
  • acquire the images

remains the same. These are all common classes and functions, which are available for all Interface Layouts.

The only thing that changes, is the way how to get and set the parameters of the camera.

This also includes the HRTC programs. In GenICam you can realize a HRTC program using Counters and Timers. The following sample shows, how you can set the exposure time to 10000 us via DeviceSpecific Interface Layout:

#include <iostream>
#include <mvIMPACT_CPP/mvIMPACT_acquire.h>
 
using namespace std;
using namespace mvIMPACT::acquire;

//-----------------------------------------------------------------------------
int main( int /*argc*/, char* /*argv*/[] )
//-----------------------------------------------------------------------------
{
  DeviceManager devMgr;
  Device* pDev = devMgr.getDeviceByFamily("mvBlueFOX");
  if (pDev == 0)
  {
	  cout << "There is currently no mvBlueFOX2 device connected," << endl;
	  cout << "or the mvBlueFOX2 drivers have not been" << endl;
	  cout << "correctly installed." << endl;
          cout << "Skipping mvBlueFOX2 single image capture..." << endl;
	  return 1;
  }
  cout << "Using Device: " << pDev->product.readS() << endl;
  cout << "Serial: " << pDev->serial.readS() << endl << endl ;
  pDev->interfaceLayout.write(dilDeviceSpecific);
  pDev->open();

  // -----------------DeviceSpecific part with property adjusting-----------
  CameraSettingsBlueFOX cs( pDev );
  cs.expose_us.write(10000);
  // --------------------------DeviceSpecific part END----------------------

  FunctionInterface fi( pDev );
  fi.imageRequestSingle();
  const int iMaxWaitTime_ms = -1;
  int requestNr = fi.imageRequestWaitFor( iMaxWaitTime_ms );
  const Request* pRequest = fi.getRequest( requestNr );
  cout << "Image captured( " << pRequest->imagePixelFormat.readS() 
       << " " << pRequest->imageWidth.read() 
       << "x" << pRequest->imageHeight.read() 
       << " )" << endl;
  fi.imageRequestUnlock( requestNr );
}

To use this code with mvBlueFOX3, you have to adopt the part of the parameterization using the GenICam Interface Layout. The red marked lines can be reused:

#include <iostream>
#include <mvIMPACT_CPP/mvIMPACT_acquire.h>
#include <mvIMPACT_CPP\mvIMPACT_acquire_GenICam.h>
 
using namespace std;
using namespace mvIMPACT::acquire;
using namespace mvIMPACT::acquire::GenICam;

//-----------------------------------------------------------------------------
int main( int /*argc*/, char* /*argv*/[] )
//-----------------------------------------------------------------------------
{
  DeviceManager devMgr;
  Device* pDev = devMgr.getDeviceByFamily("mvBlueFOX3");
  if (pDev == 0)
  {
	  cout << "There is currently no mvBlueFOX3 device connected," << endl;
	  cout << "or the mvBlueFOX3 drivers have not been" << endl;
	  cout << "correctly installed." << endl;
          cout << "Skipping mvBlueFOX3 single image capture..." << endl;
	  return 1;
  }
  cout << "Using Device: " << pDev->product.readS() << endl;
  cout << "Serial: " << pDev->serial.readS() << endl << endl ;
  // Note the different InterfaceLayout selection
  pDev->interfaceLayout.write(dilGenICam);
  pDev->open();

  // -----------------------GenICam part with property adjusting-------------
  // Note the different class name. This is a GenICam Class.
  AcquisitionControl ac(pDev);
  ac.exposureTime.write(10000);
  // ------------------------------GenICam part END--------------------------

  FunctionInterface fi( pDev );
  fi.imageRequestSingle();
  const int iMaxWaitTime_ms = -1;
  int requestNr = fi.imageRequestWaitFor( iMaxWaitTime_ms );
  const Request* pRequest = fi.getRequest( requestNr );
  cout << "Image captured( " << pRequest->imagePixelFormat.readS() 
       << " " << pRequest->imageWidth.read() 
       << "x" << pRequest->imageHeight.read() 
       << " )" << endl;
  fi.imageRequestUnlock( requestNr );
}

The code is simplified. For example, it is only allowed to connect one camera of the relevant family. Otherwise the program does not know which one it should use. More detailed programming samples can be found in the API manuals: for C, for C++, for .NET.

Using the GenICam Interface Layout offers more advantages:

You can use the same programming code with other USB3 Vision / GigE Vision / GenICam compliant devices! That's the reason, why there is a unified mvGenTL_Acquire driver for all these products.

These may not necessarily be MATRIX VISION cameras. If you change, for example, the following line in the code above, from

Device* pDev = devMgr.getDeviceByFamily("mvBlueFOX3");

to

Device* pDev = devMgr.getDeviceByFamily("GigEVision");

you can use a GigE Vision compliant camera like the mvBlueCOUGAR-X with the same code.

You can see that you can benefit from image processing standards. You have a free choice and you are not tied to any manufacturer anymore. Therefore, consider the support of standards when you buy image processing components.

Back