Spinnaker SDK C++
4.3.0.189
 
 

 
Loading...
Searching...
No Matches
StereoAcquisition_QuickSpin.cpp

StereoAcquisition_QuickSpin.cpp shows how to acquire image sets from a stereo camera using the QuickSpin API.

StereoAcquisition_QuickSpin.cpp shows how to acquire image sets from a stereo camera using the QuickSpin API. QuickSpin is a subset of the Spinnaker library that allows for simpler node access and control. The image sets are then saved to file and/or used to compute 3D point cloud and saved as a PLY (Polygon File Format) file.

This example touches on the preparation and cleanup of a camera just before and just after the acquisition of images. Image retrieval and conversion, grabbing image data, and saving images are all covered as well. Retrieving node information is the only portion of the example that differs from Acquisition.

A much wider range of topics is covered in the full Spinnaker examples than in the QuickSpin ones. There are only enough QuickSpin examples to demonstrate node access and to get started with the API; please see full Spinnaker examples for further or specific knowledge on a topic.

Please leave us feedback at: https://www.surveymonkey.com/r/TDYMVAPI More source code examples at: https://github.com/Teledyne-MV/Spinnaker-Examples Need help? Check out our forum at: https://teledynevisionsolutions.zendesk.com/hc/en-us/community/topics

//=============================================================================
// Copyright (c) 2025 FLIR Integrated Imaging Solutions, Inc. All Rights
// Reserved
//
// This software is the confidential and proprietary information of FLIR
// Integrated Imaging Solutions, Inc. ("Confidential Information"). You
// shall not disclose such Confidential Information and shall use it only in
// accordance with the terms of the non-disclosure or license agreement you
// entered into with FLIR Integrated Imaging Solutions, Inc. (FLIR).
//
// FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
// SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES
// SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
// THIS SOFTWARE OR ITS DERIVATIVES.
//=============================================================================
//=============================================================================
// System Includes
//=============================================================================
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <sstream>
#include <filesystem>
//=============================================================================
// Examples Includes
//=============================================================================
#include "PointCloud.h"
#include "Spinnaker.h"
#include "SpinStereoHelper.h"
#include "StereoParameters.h"
#include "Getopt.h"
using namespace Spinnaker;
using namespace Spinnaker::GenApi;
using namespace Spinnaker::GenICam;
using namespace SpinStereo;
using namespace std;
bool ProcessArgs(int argc, char* argv[], StereoAcquisitionParams& params)
{
string executionPath = string(argv[0]);
size_t found = executionPath.find_last_of("/\\");
string programName = executionPath.substr(found + 1);
int iOpt;
const char* currentParamPosition;
bool bBadArgs = false;
// If no arguments run with default parameters.
if (argc == 1)
{
params.doEnablePointCloudOutput = true;
params.doEnableSpeckleFilter = true;
return true;
}
const char* paramMatchPattern = "n:ABCDEFGh?";
while ((iOpt = GetOption(argc, argv, paramMatchPattern, &currentParamPosition)) != 0)
{
switch (iOpt)
{
//
// Options
//
case 'n':
#ifdef _MSC_VER
if (sscanf_s(currentParamPosition, "%d", &params.numImageSets) != 1)
#else
if (sscanf(currentParamPosition, "%d", &params.numImageSets) != 1)
#endif
{
bBadArgs = true;
}
else
{
if (params.numImageSets <= 0)
{
cout << "The numImageSets argument must be a number greater than 0." << endl;
bBadArgs = true;
}
}
break;
case 'A':
break;
case 'B':
break;
case 'C':
break;
case 'D':
break;
case 'E':
break;
case 'F':
params.doEnablePointCloudOutput = true;
break;
case 'G':
params.doEnableSpeckleFilter = true;
break;
case '?':
case 'h':
default:
cerr << "Invalid option provided: " << currentParamPosition << endl;
DisplayHelp(programName, params);
return false;
}
}
if (bBadArgs)
{
cout << "Invalid arguments" << endl;
DisplayHelp(programName, params);
return false;
}
{
{
cout << "Need to have disparity Image (-E) for point cloud generation" << endl << endl;
DisplayHelp(programName, params);
return false;
}
{
cout << "Need to have Rectified Sensor1 Image (-C) for point cloud generation" << endl << endl;
DisplayHelp(programName, params);
return false;
}
}
{
cout << "Need to enable at least one image (-A/-B/-C/-D/-E)" << endl << endl;
DisplayHelp(programName, params);
return false;
}
return true;
}
void DisplayHelp(const string& pszProgramName, const StereoAcquisitionParams& params)
{
cout << "Usage: ";
cout << pszProgramName << " [OPTIONS]" << endl << endl;
cout << "OPTIONS" << endl
<< endl
<< " -n NUM_FRAMES Number frames" << endl
<< " Default is " << params.numImageSets << endl
<< " -A DO_ENABLE_RAW_SENSOR1_TRANSMIT doEnableRawSensor1Transmit" << endl
<< " Default is " << params.doEnableRawSensor1Transmit << endl
<< " -B DO_ENABLE_RAW_SENSOR2_TRANSMIT doEnableRawSensor2Transmit" << endl
<< " Default is " << params.doEnableRawSensor2Transmit << endl
<< " -C DO_ENABLE_RECT_SENSOR1_TRANSMIT doEnableRectSensor1Transmit" << endl
<< " Default is " << params.doEnableRectSensor1Transmit << endl
<< " -D DO_ENABLE_RECT_SENSOR2_TRANSMIT doEnableRectSensor2Transmit" << endl
<< " Default is " << params.doEnableRectSensor2Transmit << endl
<< " -E DO_ENABLE_DISPARITY_TRANSMIT doEnableDisparityTransmit" << endl
<< " Default is " << params.doEnableDisparityTransmit << endl
<< " -F DO_ENABLE_POINTCLOUD_OUTPUT doEnablePointCloudOutput" << endl
<< " Default is " << params.doEnablePointCloudOutput << endl
<< " -G DO_ENABLE_SPECKLE_FILTER doEnableSpeckleFilter" << endl
<< " Default is " << params.doEnableSpeckleFilter << endl
<< "EXAMPLE" << endl
<< endl
<< " " << pszProgramName << " -n " << params.numImageSets << " -A "
<< " -B "
<< " -C "
<< " -D "
<< " -E "
<< " -F " << endl
<< endl;
}
// This function configures the camera to add chunk data to each image. It does
// this by enabling each type of chunk data after enabling chunk data mode.
// When chunk data mode is turned on, the data is made available in both the nodemap
// and each image.
{
bool result = true;
cout << endl << endl << "*** CONFIGURING CHUNK DATA ***" << endl << endl;
try
{
//
// Activate chunk mode
//
// *** NOTES ***
// Once enabled, chunk data will be available at the end of the payload
// of every image captured until it is disabled. Chunk data can also be
// retrieved from the nodemap.
//
if (!IsWritable(pCam->ChunkModeActive))
{
cout << "Unable to activate chunk mode. Aborting..." << endl << endl;
return false;
}
pCam->ChunkModeActive.SetValue(true);
cout << "Chunk mode activated..." << endl;
//
// Enable all types of chunk data
//
// *** NOTES ***
// Enabling chunk data requires working with nodes: "ChunkSelector"
// is an enumeration selector node and "ChunkEnable" is a boolean. It
// requires retrieving the selector node (which is of enumeration node
// type), selecting the entry of the chunk data to be enabled, retrieving
// the corresponding boolean, and setting it to true.
//
// In this example, all chunk data is enabled, so these steps are
// performed in a loop. Once this is complete, chunk mode still needs to
// be activated.
//
NodeList_t entries;
if (!IsReadable(pCam->ChunkSelector))
{
cout << "Unable to retrieve chunk selector. Aborting..." << endl << endl;
return false;
}
// Retrieve entries
pCam->ChunkSelector.GetEntries(entries);
cout << "Enabling entries..." << endl;
for (size_t i = 0; i < entries.size(); i++)
{
// Select entry to be enabled
CEnumEntryPtr ptrChunkSelectorEntry = entries.at(i);
// Go to next node if problem occurs
if (!IsReadable(ptrChunkSelectorEntry))
{
continue;
}
pCam->ChunkSelector.SetIntValue(ptrChunkSelectorEntry->GetValue());
cout << "\t" << ptrChunkSelectorEntry->GetSymbolic() << ": ";
// Enable the boolean, thus enabling the corresponding chunk data
if (!IsAvailable(pCam->ChunkEnable))
{
cout << "not available" << endl;
result = false;
}
else if (pCam->ChunkEnable.GetValue())
{
cout << "enabled" << endl;
}
else if (IsWritable(pCam->ChunkEnable))
{
pCam->ChunkEnable.SetValue(true);
cout << "enabled" << endl;
}
else
{
cout << "not writable" << endl;
result = false;
}
}
}
{
cout << "Error: " << e.what() << endl;
result = false;
}
return result;
}
// This function disables each type of chunk data before disabling chunk data mode.
{
bool result = true;
try
{
NodeList_t entries;
if (!IsReadable(pCam->ChunkSelector))
{
cout << "Unable to retrieve chunk selector. Aborting..." << endl << endl;
return false;
}
// Retrieve entries
pCam->ChunkSelector.GetEntries(entries);
cout << "Disabling entries..." << endl;
for (size_t i = 0; i < entries.size(); i++)
{
// Select entry to be disabled
CEnumEntryPtr ptrChunkSelectorEntry = entries.at(i);
// Go to next node if problem occurs
if (!IsReadable(ptrChunkSelectorEntry))
{
continue;
}
pCam->ChunkSelector.SetIntValue(ptrChunkSelectorEntry->GetValue());
cout << "\t" << ptrChunkSelectorEntry->GetSymbolic() << ": ";
// Disable the boolean, thus disabling the corresponding chunk data
if (!IsAvailable(pCam->ChunkEnable))
{
cout << "not available" << endl;
result = false;
}
else if (!pCam->ChunkEnable.GetValue())
{
cout << "disabled" << endl;
}
else if (IsWritable(pCam->ChunkEnable))
{
pCam->ChunkEnable.SetValue(false);
cout << "disabled" << endl;
}
else
{
cout << "not writable" << endl;
}
}
cout << endl;
if (!IsWritable(pCam->ChunkModeActive))
{
cout << "Unable to deactivate chunk mode. Aborting..." << endl << endl;
return false;
}
pCam->ChunkModeActive.SetValue(false);
cout << "Chunk mode deactivated..." << endl;
}
{
cout << "Error: " << e.what() << endl;
result = false;
}
return result;
}
// This function displays a select amount of chunk data from the image. Unlike
// accessing chunk data via the nodemap, there is no way to loop through all
// available data.
{
bool result = true;
cout << "Printing chunk data from image..." << endl;
try
{
//
// Retrieve chunk data from image
//
// *** NOTES ***
// When retrieving chunk data from an image, the data is stored in a
// a ChunkData object and accessed with getter functions.
//
ChunkData chunkData = pImage->GetChunkData();
//
// Retrieve exposure time; exposure time recorded in microseconds
//
// *** NOTES ***
// Floating point numbers are returned as a float64_t. This can safely
// and easily be statically cast to a double.
//
double exposureTime = static_cast<double>(chunkData.GetExposureTime());
std::cout << "\tExposure time: " << exposureTime << endl;
//
// Retrieve frame ID
//
// *** NOTES ***
// Integers are returned as an int64_t. As this is the typical integer
// data type used in the Spinnaker SDK, there is no need to cast it.
//
int64_t frameID = chunkData.GetFrameID();
cout << "\tFrame ID: " << frameID << endl;
// The following are stereo-specific chunk data attributes
// Retrieve stereo height; stereo height recorded in pixels
int64_t stereoHeight = chunkData.GetStereoHeight();
cout << "\tStereoHeight: " << stereoHeight << endl;
// Retrieve stereo width; stereo width recorded in pixels
int64_t stereoWidth = chunkData.GetStereoWidth();
cout << "\tStereoWidth: " << stereoWidth << endl;
// Retrieve Scan3dCordinateOffset; Scan3dCordinateOffset recorded in pixels
float64_t scan3dCoordinateOffset = chunkData.GetScan3dCoordinateOffset();
cout << "\tScan3dCoordinateOffset: " << scan3dCoordinateOffset << endl;
// Retrieve Scan3dBaseline; Scan3dBaseline recorded in meters
float64_t scan3dBaseline = chunkData.GetScan3dBaseline();
cout << "\tScan3dBaseline: " << scan3dBaseline << endl;
// Retrieve Scan3dFocalLength; Scan3dFocalLength recorded in pixels
float64_t scan3dFocalLength = chunkData.GetScan3dFocalLength();
cout << "\tScan3dFocalLength: " << scan3dFocalLength << endl;
// Retrieve MinZ; MinZ recorded in meters
float64_t minZ = chunkData.GetMinZ();
cout << "\tMinZ: " << minZ << endl;
// Retrieve MaxZ; MaxZ recorded in meters
float64_t maxZ = chunkData.GetMaxZ();
cout << "\tMaxZ: " << maxZ << endl;
// Retrieve Scan3dPrincipalPointU; Scan3dPrincipalPointU recorded in pixels
float64_t scan3dPrincipalPointU = chunkData.GetScan3dPrincipalPointU();
cout << "\tScan3dPrincipalPointU: " << scan3dPrincipalPointU << endl;
// Retrieve Scan3dPrincipalPointV; Scan3dPrincipalPointV recorded in pixels
float64_t scan3dPrincipalPointV = chunkData.GetScan3dPrincipalPointV();
cout << "\tScan3dPrincipalPointV: " << scan3dPrincipalPointV << endl;
// Retrieve SmallPenalty; SmallPenalty recorded in pixels
int64_t smallPenalty = chunkData.GetSmallPenalty();
cout << "\tSmallPenalty: " << smallPenalty << endl;
// Retrieve LargePenalty; LargePenalty recorded in pixels
int64_t largePenalty = chunkData.GetLargePenalty();
cout << "\tLargePenalty: " << largePenalty << endl;
// Retrieve UniquenessRatio; UniquenessRatio recorded in percentage
int64_t uniquenessRatio = chunkData.GetUniquenessRatio();
cout << "\tUniquenessRatio: " << uniquenessRatio << endl;
}
{
cout << "Error: " << e.what() << endl;
result = false;
}
return result;
}
const StereoParameters& stereoParameters,
ImageList& imageList,
int counter,
string prefix = "")
{
PointCloudParameters pointCloudParameters = PointCloudParameters();
pointCloudParameters.decimationFactor = 1;
pointCloudParameters.ROIImageLeft = 0;
pointCloudParameters.ROIImageTop = 0;
pointCloudParameters.ROIImageRight = static_cast<unsigned int>(
imageList.GetByPayloadType(SPINNAKER_IMAGE_PAYLOAD_TYPE_DISPARITY_SENSOR1)->GetWidth());
pointCloudParameters.ROIImageBottom = static_cast<unsigned int>(
imageList.GetByPayloadType(SPINNAKER_IMAGE_PAYLOAD_TYPE_DISPARITY_SENSOR1)->GetHeight());
StereoCameraParameters stereoCameraParameters = StereoCameraParameters();
stereoCameraParameters.coordinateOffset = stereoParameters.scan3dCoordinateOffset;
stereoCameraParameters.baseline = stereoParameters.scan3dBaseline;
stereoCameraParameters.focalLength = stereoParameters.scan3dFocalLength;
stereoCameraParameters.principalPointU = stereoParameters.scan3dPrincipalPointU;
stereoCameraParameters.principalPointV = stereoParameters.scan3dPrincipalPointV;
stereoCameraParameters.disparityScaleFactor = stereoParameters.scan3dCoordinateScale;
stereoCameraParameters.invalidDataFlag = stereoParameters.scan3dInvalidDataFlag;
stereoCameraParameters.invalidDataValue = stereoParameters.scan3dInvalidDataValue;
imageList.GetByPayloadType(SPINNAKER_IMAGE_PAYLOAD_TYPE_DISPARITY_SENSOR1),
imageList.GetByPayloadType(SPINNAKER_IMAGE_PAYLOAD_TYPE_RECTIFIED_SENSOR1),
pointCloudParameters,
stereoCameraParameters);
stringstream strstr("");
strstr << prefix;
strstr << "PointCloud_" << counter << ".ply";
cout << "Save point cloud to file: " << strstr.str() << endl;
pointCloud.SavePointCloudAsPly(strstr.str().c_str());
return true;
}
const StreamTransmitFlags& streamTransmitFlags,
ImageList& imageList,
int counter,
const string prefix = "")
{
cout << "Save images to files." << endl;
stringstream strstr;
if (streamTransmitFlags.rawSensor1TransmitEnabled)
{
strstr.str("");
strstr << prefix;
strstr << "RawSensor1_" << counter << ".png";
string rawSensor1Filename = strstr.str();
cout << "Save raw Sensor1 image to file: " << rawSensor1Filename << endl;
imageList.GetByPayloadType(SPINNAKER_IMAGE_PAYLOAD_TYPE_RAW_SENSOR1)->Save(rawSensor1Filename.c_str());
}
if (streamTransmitFlags.rawSensor2TransmitEnabled)
{
strstr.str("");
strstr << prefix;
strstr << "RawSensor2_" << counter << ".png";
string rawSensor2Filename = strstr.str();
cout << "Save raw Sensor2 image to file: " << rawSensor2Filename << endl;
imageList.GetByPayloadType(SPINNAKER_IMAGE_PAYLOAD_TYPE_RAW_SENSOR2)->Save(rawSensor2Filename.c_str());
}
if (streamTransmitFlags.rectSensor1TransmitEnabled)
{
strstr.str("");
strstr << prefix;
strstr << "RectSensor1_" << counter << ".png";
string rectSensor1Filename = strstr.str();
cout << "Save rectified sensor1 image to file: " << rectSensor1Filename << endl;
imageList.GetByPayloadType(SPINNAKER_IMAGE_PAYLOAD_TYPE_RECTIFIED_SENSOR1)->Save(rectSensor1Filename.c_str());
}
if (streamTransmitFlags.rectSensor2TransmitEnabled)
{
strstr.str("");
strstr << prefix;
strstr << "RectSensor2_" << counter << ".png";
string rectSensor2Filename = strstr.str();
cout << "Save rectified sensor2 image to file: " << rectSensor2Filename << endl;
imageList.GetByPayloadType(SPINNAKER_IMAGE_PAYLOAD_TYPE_RECTIFIED_SENSOR2)->Save(rectSensor2Filename.c_str());
}
if (streamTransmitFlags.disparityTransmitEnabled)
{
strstr.str("");
strstr << prefix;
strstr << "Disparity_" << counter << ".pgm";
string disparityFilename = strstr.str();
cout << "Save disparity image to file: " << disparityFilename << endl;
imageList.GetByPayloadType(SPINNAKER_IMAGE_PAYLOAD_TYPE_DISPARITY_SENSOR1)->Save(disparityFilename.c_str());
}
return true;
}
{
// NOTE:
//
// Camera firmware will report the current bandwidth required by the camera in the 'DeviceLinkCurrentThroughput'
// node. When 'DeviceLinkThroughputLimit' node is set by the user, firmware will automatically increase packet
// delay to fulfill the requested throughput. Therefore, once camera is configured for the desired
// framerate/image size/etc, set 'DeviceLinkCurrentThroughput' node value into 'DeviceLinkThroughputLimit' node,
// and packet size will be automatically set by the camera.
INodeMap& nodeMap = pCam->GetNodeMap();
// Set Stream Channel Packet Size to the max possible on its interface
CIntegerPtr ptrPacketSize = nodeMap.GetNode("GevSCPSPacketSize");
if (!IsReadable(pCam->GevSCPSPacketSize) || !IsWritable(pCam->GevSCPSPacketSize))
{
std::cerr << "Failed to get or set the GevSCPSPacketSize parameter from or to the camera." << std::endl;
return false;
}
const unsigned int maxGevSCPSPacketSize = static_cast<unsigned int>(pCam->GevSCPSPacketSize.GetMax());
const unsigned int maxPacketSize =
pCam->DiscoverMaxPacketSize() > maxGevSCPSPacketSize ? maxGevSCPSPacketSize : pCam->DiscoverMaxPacketSize();
pCam->GevSCPSPacketSize.SetValue(maxPacketSize);
cout << "PacketSize set to: " << pCam->GevSCPSPacketSize.GetValue() << endl;
if (!IsReadable(pCam->DeviceLinkCurrentThroughput))
{
std::cerr << "Failed to get the DeviceLinkCurrentThroughput parameter from the camera." << std::endl;
return false;
}
if (!IsReadable(pCam->DeviceLinkThroughputLimit) || !IsWritable(pCam->DeviceLinkThroughputLimit))
{
std::cerr << "Failed to get or set the DeviceLinkThroughputLimit parameter from or to the camera." << std::endl;
return false;
}
cout << "Current camera throughput: " << pCam->DeviceLinkCurrentThroughput.GetValue() << endl;
// If the 'DeviceLinkCurrentThroughput' value is lower than the minimum, set the lowest possible value allowed
// by the 'DeviceLinkCurrentThroughput' node
if (pCam->DeviceLinkThroughputLimit.GetMin() > pCam->DeviceLinkCurrentThroughput.GetValue())
{
cout << "DeviceLinkCurrentThroughput node minimum of: " << pCam->DeviceLinkThroughputLimit.GetMin()
<< " is higher than current throughput we desire to set (" << pCam->DeviceLinkCurrentThroughput.GetValue()
<< ")" << endl;
pCam->DeviceLinkThroughputLimit.SetValue(pCam->DeviceLinkThroughputLimit.GetMin());
}
else
{
// Set 'DeviceLinkCurrentThroughput' value into 'DeviceLinkThroughputLimit' node so that the
// camera will adjust inter-packet delay automatically
pCam->DeviceLinkThroughputLimit.SetValue(pCam->DeviceLinkCurrentThroughput.GetValue());
}
cout << "DeviceLinkThroughputLimit set to: " << pCam->DeviceLinkThroughputLimit.GetValue() << endl << endl;
return true;
}
bool AcquireImages(CameraPtr pCam, StereoParameters& stereoParameters, unsigned int numImageSets)
{
bool result = true;
cout << endl << endl << "*** IMAGE ACQUISITION ***" << endl << endl;
try
{
// Begin acquiring images
pCam->BeginAcquisition();
cout << endl << "Acquiring " << numImageSets << " image sets." << endl;
gcstring serialNumber = pCam->TLDevice.DeviceSerialNumber.GetValue();
uint64_t timeoutInMilliSecs = 2000;
for (unsigned int counter = 0; counter < numImageSets; counter++)
{
try
{
cout << endl << "Acquiring stereo image set: " << counter << endl;
//
// Retrieve next received set of stereo images
//
// *** NOTES ***
// GetNextImageSync() captures an image from each stream and returns a synchronized
// image set in an ImageList object based on the frame ID. The ImageList object is
// simply a generic container for one or more ImagePtr objects.
//
// For a set of stereo images, the ImageList object could contain up to five different
// image payload type images (Raw Sensor1, Raw Sensor2, Rectified Sensor1, Rectified Sensor2 and
// Disparity Sensor1). The five images that are returned in the ImageList are guaranteed
// to be synchronized in timestamp and Frame ID.
//
// This function cannot be invoked if GetNextImage is being invoked already.
// Results will be indeterministic and could lead to missing or lost of images.
//
// *** LATER ***
// Once the image list is saved and/or no longer needed, the image list must be
// released in order to keep the image buffer from filling up.
ImageList imageList;
imageList = pCam->GetNextImageSync(timeoutInMilliSecs);
if (!SpinStereo::ValidateImageList(stereoParameters.streamTransmitFlags, imageList))
{
cout << "Failed to get next image set." << endl;
continue;
}
// Chunk Data is only available from the last Image in the ImageList for multi-stream cameras
ImagePtr img = imageList.GetByIndex(imageList.GetSize() - 1);
if (stereoParameters.postProcessDisparity)
{
{
// Applying SpeckleFilter directly on disparity image
cout << "Applying SpeckleFilter on disparity image..." << endl;
ImagePtr pDisparity =
imageList.GetByPayloadType(SPINNAKER_IMAGE_PAYLOAD_TYPE_DISPARITY_SENSOR1);
ImageUtilityStereo::FilterSpecklesFromImage(
pDisparity,
stereoParameters.maxSpeckleSize,
stereoParameters.speckleThreshold,
stereoParameters.scan3dCoordinateScale,
stereoParameters.scan3dInvalidDataValue);
}
else
{
cout << "Skipping disparity post processing as disparity components are disabled" << endl;
}
}
stringstream ss("");
ss << "StereoAcquisition_QuickSpin_" << serialNumber << "_";
if (!SaveImagesToFile(stereoParameters.streamTransmitFlags, imageList, counter, ss.str()))
{
cerr << "Failed to save images." << endl;
result = false;
break;
}
if (stereoParameters.doComputePointCloud)
{
{
// only do if both streams are enabled
if (!Compute3DPointCloudAndSave(stereoParameters, imageList, counter, ss.str()))
{
cerr << "Failed to compute the 3D point cloud." << endl;
result = false;
break;
}
}
else
{
cout << "Skipping compute 3D point cloud as rectified sensor1 or disparity sensor1 components "
"are disabled"
<< endl;
}
}
}
{
cout << "Error: " << e.what() << endl;
result = false;
}
}
//
// End acquisition
//
// *** NOTES ***
// Ending acquisition appropriately helps ensure that devices clean up
// properly and do not need to be power-cycled to maintain integrity.
//
pCam->EndAcquisition();
}
{
cout << "Error: " << e.what() << endl;
result = false;
}
return result;
}
// This function acts as the body of the example; please see NodeMapInfo_QuickSpin example
// for more in-depth comments on setting up cameras.
bool RunSingleCamera(CameraPtr pCam, StereoParameters& stereoParameters, int numImageSets)
{
bool result = true;
try
{
// Print device info
result = PrintDeviceInfo(pCam);
// Initialize camera
pCam->Init();
// Check to make sure camera supports stereo vision
cout << endl << "Checking camera stereo support..." << endl;
if (!ImageUtilityStereo::IsStereoCamera(pCam))
{
cout << "Device serial number " << pCam->TLDevice.DeviceSerialNumber.GetValue()
<< " is not a valid BX camera. Skipping..." << endl;
// Deinitialize camera
pCam->DeInit();
return true;
}
// Configure heartbeat for GEV camera
#ifdef _DEBUG
result = result && DisableGVCPHeartbeat(pCam);
#else
result = result && ResetGVCPHeartbeat(pCam);
#endif
if (!result)
{
cerr << "Failed to set the heartbeat." << endl;
// Deinitialize camera
pCam->DeInit();
return false;
}
// Camera Stereo Parameters can be configured while camera is acquiring images, but
// enabling/disabling stream components is only possible before camera begins image acquisition
cout << endl << "Configuring camera..." << endl;
{
cerr << "Failed to configure the acquisition." << endl;
// Deinitialize camera
pCam->DeInit();
return false;
}
cout << endl << "Configuring chunk data..." << endl;
if (!ConfigureChunkData(pCam))
{
cerr << "Failed to configure chunk data." << endl;
// Deinitialize camera
pCam->DeInit();
return false;
}
cout << endl << "Configuring device link throughput..." << endl;
{
cerr << "Failed to set the device link throughput." << endl;
// Deinitialize camera
pCam->DeInit();
return false;
}
cout << endl << "Configuring stereo processing..." << endl;
if (!SpinStereo::ConfigureStereoProcessing(pCam, stereoParameters))
{
cerr << "Failed to configure stereo processing." << endl;
// Deinitialize camera
pCam->DeInit();
return false;
}
cout << endl << "*** STEREO PARAMETERS *** " << endl << stereoParameters.ToString() << endl;
#if _DEBUG
cout << endl << "*** CAMERA CALIBRATION PARAMETERS ***" << endl;
{
cerr << "Failed to get camera calibration parameters." << endl;
return false;
}
#endif
// Acquire images
cout << endl << "Acquiring images..." << endl;
result &= AcquireImages(pCam, stereoParameters, numImageSets);
#ifdef _DEBUG
// Reset heartbeat for GEV camera
result = result && ResetGVCPHeartbeat(pCam);
#endif
// Deinitialize camera
pCam->DeInit();
}
{
cout << "Error: " << e.what() << endl;
result = false;
}
return result;
}
// Example entry point; please see Enumeration_QuickSpin example for more
// in-depth comments on preparing and cleaning up the system.
int main(int argc, char** argv)
{
// Since this application saves images in the current folder
// we must ensure that we have permission to write to this folder.
// If we do not have permission, fail right away.
FILE* tempFile = fopen("test.txt", "w+");
if (tempFile == nullptr)
{
cout << "Failed to create file in current folder. Please check "
"permissions."
<< endl;
cout << "Press Enter to exit..." << endl;
getchar();
return -1;
}
fclose(tempFile);
remove("test.txt");
// determine cmd line arguments
StereoAcquisitionParams stereoAcquisitionParams;
if (!ProcessArgs(argc, argv, stereoAcquisitionParams))
{
return -1;
}
StereoParameters stereoParameters;
StreamTransmitFlags& streamTransmitFlags = stereoParameters.streamTransmitFlags;
streamTransmitFlags.rawSensor1TransmitEnabled = stereoAcquisitionParams.doEnableRawSensor1Transmit;
streamTransmitFlags.rawSensor2TransmitEnabled = stereoAcquisitionParams.doEnableRawSensor2Transmit;
streamTransmitFlags.rectSensor1TransmitEnabled = stereoAcquisitionParams.doEnableRectSensor1Transmit;
streamTransmitFlags.rectSensor2TransmitEnabled = stereoAcquisitionParams.doEnableRectSensor2Transmit;
streamTransmitFlags.disparityTransmitEnabled = stereoAcquisitionParams.doEnableDisparityTransmit;
stereoParameters.doComputePointCloud = stereoAcquisitionParams.doEnablePointCloudOutput;
stereoParameters.postProcessDisparity = stereoAcquisitionParams.doEnableSpeckleFilter;
// Print application build information
cout << "Application build date: " << __DATE__ << " " << __TIME__ << endl << endl;
// Retrieve singleton reference to system object
SystemPtr system = System::GetInstance();
// Print out current library version
const LibraryVersion spinnakerLibraryVersion = system->GetLibraryVersion();
cout << "Spinnaker library version: " << spinnakerLibraryVersion.major << "." << spinnakerLibraryVersion.minor
<< "." << spinnakerLibraryVersion.type << "." << spinnakerLibraryVersion.build << endl
<< endl;
// Retrieve list of cameras from the system
CameraList camList = system->GetCameras();
const unsigned int numCameras = camList.GetSize();
cout << "Number of cameras detected: " << numCameras << endl << endl;
// Finish if there are no cameras
if (numCameras == 0)
{
// Clear camera list before releasing system
camList.Clear();
// Release system
system->ReleaseInstance();
cout << "Not enough cameras!" << endl;
cout << "Done! Press Enter to exit..." << endl;
getchar();
return -1;
}
//
// Create shared pointer to camera
//
// *** NOTES ***
// The CameraPtr object is a shared pointer, and will generally clean itself
// up upon exiting its scope. However, if a shared pointer is created in the
// same scope that a system object is explicitly released (i.e. this scope),
// the reference to the shared point must be broken manually.
//
// *** LATER ***
// Shared pointers can be terminated manually by assigning them to nullptr.
// This keeps releasing the system from throwing an exception.
//
CameraPtr pCam = nullptr;
bool result = true;
// Run example on each camera
for (unsigned int i = 0; i < numCameras; i++)
{
// Select camera
pCam = camList.GetByIndex(i);
cout << endl << "Running example for camera " << i << "..." << endl;
// Run example
result &= RunSingleCamera(pCam, stereoParameters, stereoAcquisitionParams.numImageSets);
cout << "Camera " << i << " example complete..." << endl << endl;
}
//
// Release reference to the camera
//
// *** NOTES ***
// Had the CameraPtr object been created within the for-loop, it would not
// be necessary to manually break the reference because the shared pointer
// would have automatically cleaned itself up upon exiting the loop.
//
pCam = nullptr;
// Clear camera list before releasing system
camList.Clear();
// Release system
system->ReleaseInstance();
cout << endl << "Done! Press Enter to exit..." << endl;
getchar();
return (result == true) ? 0 : -1;
}
int AcquireImages(CameraPtr pCam, INodeMap &nodeMap, INodeMap &nodeMapTLDevice)
Definition Acquisition.cpp:200
int main(int, char **)
Definition Acquisition.cpp:536
int ResetGVCPHeartbeat(CameraPtr pCam)
Definition Acquisition.cpp:139
int RunSingleCamera(CameraPtr pCam)
Definition Acquisition.cpp:488
int PrintDeviceInfo(INodeMap &nodeMap)
Definition Acquisition.cpp:442
int DisableGVCPHeartbeat(CameraPtr pCam)
Definition Acquisition.cpp:144
int DisplayChunkData(ImagePtr pImage)
Definition ChunkData.cpp:195
int ConfigureChunkData(INodeMap &nodeMap)
Definition ChunkData.cpp:71
int DisableChunkData(INodeMap &nodeMap)
Definition ChunkData.cpp:550
int GetOption(int argc, char **argv, const char *pszValidOpts, const char **ppszParam)
Definition Getopt.c:96
bool SetDeviceLinkThroughput(CameraPtr pCam)
Definition StereoAcquisition.cpp:647
bool ProcessArgs(int argc, char *argv[], StereoAcquisitionParams &params)
ProcessArgs.
Definition StereoAcquisition.cpp:75
bool Compute3DPointCloudAndSave(const StereoParameters &stereoParameters, ImageList &imageList, int counter, string prefix="")
Compute3DPointCloudAndSave.
Definition StereoAcquisition.cpp:542
void DisplayHelp(const string &pszProgramName, const StereoAcquisitionParams &params)
DisplayHelp.
Definition StereoAcquisition.cpp:200
bool SaveImagesToFile(const StreamTransmitFlags &streamTransmitFlags, ImageList &imageList, int counter, const string prefix="")
Definition StereoAcquisition.cpp:584
Class for handling parameters of the S3D camera.
Definition StereoParameters.h:66
std::string ToString() const
Converts the parameters to a string representation.
Definition StereoParameters.cpp:48
bool doComputePointCloud
flag to enable computation of the 3D point cloud.
Definition StereoParameters.h:86
StreamTransmitFlags streamTransmitFlags
Flags to enable streams image transmission.
Definition StereoParameters.h:84
float scan3dBaseline
Definition StereoParameters.h:100
float scan3dCoordinateOffset
Minimum number of disparities.
Definition StereoParameters.h:79
float scan3dPrincipalPointV
Definition StereoParameters.h:101
float scan3dInvalidDataValue
Definition StereoParameters.h:82
float speckleThreshold
Speckle threshold value.
Definition StereoParameters.h:95
float scan3dPrincipalPointU
Definition StereoParameters.h:102
float scan3dFocalLength
Definition StereoParameters.h:99
float scan3dCoordinateScale
Definition StereoParameters.h:105
bool scan3dInvalidDataFlag
Definition StereoParameters.h:81
bool postProcessDisparity
Flag to enable disparity post-processing.
Definition StereoParameters.h:92
int maxSpeckleSize
Speckle range value.
Definition StereoParameters.h:94
Used to hold a list of camera objects.
Definition CameraList.h:42
void Clear()
Clears the list of cameras and destroys their corresponding reference counted objects.
CameraPtr GetByIndex(unsigned int index) const
Returns a pointer to a camera object at the "index".
unsigned int GetSize() const
Returns the size of the camera list.
A reference tracked pointer to a camera object.
Definition CameraPtr.h:44
The chunk data which contains additional information about an image.
Definition ChunkData.h:42
float64_t GetScan3dBaseline() const
Description: Returns the baseline as the physical distance of two cameras in a stereo camera setup.
float64_t GetScan3dCoordinateOffset() const
Description: Returns the Offset for the selected coordinate axis of the image included in the payload...
int64_t GetStereoWidth() const
Description: Returns the width of the image after stereo processing by the device (in pixels).
int64_t GetSmallPenalty() const
Description: Returns the penalty when the change of Disparity Change is plus or minus 1.
int64_t GetLargePenalty() const
Description: Returns the penalty when the change of Disparity Change is plus or minus 1.
float64_t GetMinZ() const
Description: Returns the minimum depth in meters for the point cloud range.
int64_t GetStereoHeight() const
Description: Returns the height of the image after stereo processing by the device (in pixels).
float64_t GetScan3dPrincipalPointV() const
Description: Returns the value of this feature gives the vertical position of the principal point,...
float64_t GetScan3dPrincipalPointU() const
Description: Returns the value of this feature gives the horizontal position of the principal point,...
int64_t GetUniquenessRatio() const
Description: Returns the difference between the best matching disparity and the second-best matching ...
float64_t GetMaxZ() const
Description: Returns the maximum depth in meters for the point cloud range.
float64_t GetExposureTime() const
Description: Returns the exposure time used to capture the image.
float64_t GetScan3dFocalLength() const
Description: Returns the focal length of the camera in pixel.
int64_t GetFrameID() const
Description: Returns the image frame ID.
The Exception object represents an error that is returned from the library.
Definition Exception.h:51
virtual const char * what() const
virtual override for what().
Encapsulates a GenApi pointer dealing with the dynamic_cast automatically.
Definition Pointer.h:75
Definition GCString.h:43
Used to hold a list of image objects.
Definition ImageList.h:42
ImagePtr GetByIndex(unsigned int index) const
Returns a pointer to an image object at the "index".
ImagePtr GetByPayloadType(const ImagePayloadType payloadType) const
Returns a pointer to an image object with the specified image payload type.
unsigned int GetSize() const
Returns the size of the image list.
A reference tracked pointer to an image object.
Definition ImagePtr.h:46
static PointCloud ComputePointCloud(const ImagePtr &disparityImage, const ImagePtr &rectifiedImage, const PointCloudParameters &pointCloudParameters, const StereoCameraParameters &stereoCameraParameters)
Computes 3D point cloud from a stereo pair consisting of a disparity/rectified image using a stereo m...
The PointCloud object class.
Definition PointCloud.h:46
A reference tracked pointer to a system object.
Definition SystemPtr.h:44
double float64_t
64 bit floating point
Definition GCTypes.h:261
bool IsWritable(EAccessMode AccessMode)
Tests if writable.
Definition INode.h:277
bool IsAvailable(EAccessMode AccessMode)
Tests if available.
Definition INode.h:325
bool IsReadable(EAccessMode AccessMode)
Tests if readable.
Definition INode.h:253
interface SPINNAKER_API_ABSTRACT INodeMap
Interface to access the node map.
Definition INodeMap.h:54
void SavePointCloudAsPly(const std::string &) const
The function writes the point cloud data to the specified file in PLY format.
node_vector NodeList_t
a list of node references
Definition INode.h:54
bool PrintCameraCalibrationParams(INodeMap &nodeMap)
Prints the camera calibration parameters.
Definition SpinStereoHelper.cpp:956
Definition SpinStereoHelper.cpp:34
bool ValidateImageList(const StreamTransmitFlags &streamTransmitFlags, ImageList &imageList)
Definition SpinStereoHelper.cpp:765
bool ConfigureAcquisition(CameraPtr pCam, StreamTransmitFlags &streamTransmitFlags)
Definition SpinStereoHelper.cpp:249
bool ConfigureStereoProcessing(INodeMap &nodeMap, StereoParameters &stereoParameters)
Definition SpinStereoHelper.cpp:226
Definition AutoPollController.h:33
Definition GCString.h:31
Definition BasePtr.h:24
Definition StereoParameters.h:40
bool rawSensor1TransmitEnabled
Flag to enable raw sensor1 image transmission.
Definition StereoParameters.h:41
bool rawSensor2TransmitEnabled
Flag to enable raw sensor2 image transmission.
Definition StereoParameters.h:42
bool rectSensor1TransmitEnabled
Flag to enable rectified sensor1 image transmission.
Definition StereoParameters.h:43
bool disparityTransmitEnabled
Flag to enable disparity image transmission.
Definition StereoParameters.h:45
bool rectSensor2TransmitEnabled
Flag to enable rectified sensor2 image transmission.
Definition StereoParameters.h:44
Provides easier access to the current version of Spinnaker.
Definition SpinnakerDefs.h:706
unsigned int minor
Minor version of the library.
Definition SpinnakerDefs.h:711
unsigned int major
Major version of the library.
Definition SpinnakerDefs.h:708
unsigned int type
Version type of the library.
Definition SpinnakerDefs.h:714
unsigned int build
Build number of the library.
Definition SpinnakerDefs.h:717
Definition SpinnakerDefs.h:790
unsigned int ROIImageTop
Definition SpinnakerDefs.h:800
unsigned int ROIImageLeft
Definition SpinnakerDefs.h:796
unsigned int decimationFactor
Definition SpinnakerDefs.h:793
unsigned int ROIImageBottom
Definition SpinnakerDefs.h:806
unsigned int ROIImageRight
Definition SpinnakerDefs.h:803
Definition SpinnakerDefs.h:848
float invalidDataValue
Definition SpinnakerDefs.h:855
float disparityScaleFactor
Definition SpinnakerDefs.h:854
float principalPointV
Definition SpinnakerDefs.h:853
float focalLength
Definition SpinnakerDefs.h:851
float principalPointU
Definition SpinnakerDefs.h:852
bool invalidDataFlag
Definition SpinnakerDefs.h:856
float baseline
Definition SpinnakerDefs.h:850
float coordinateOffset
Definition SpinnakerDefs.h:849
Definition StereoAcquisition.h:32
bool doEnableRectSensor2Transmit
Definition StereoAcquisition.h:37
bool doEnableRawSensor1Transmit
Definition StereoAcquisition.h:34
bool doEnableSpeckleFilter
Definition StereoAcquisition_QuickSpin.h:40
unsigned int numImageSets
Definition StereoAcquisition.h:33
bool doEnableRawSensor2Transmit
Definition StereoAcquisition.h:35
bool doEnablePointCloudOutput
Definition StereoAcquisition.h:39
bool doEnableDisparityTransmit
Definition StereoAcquisition.h:38
bool doEnableRectSensor1Transmit
Definition StereoAcquisition.h:36