Spinnaker SDK C++
4.2.0.21
 
 

 
Loading...
Searching...
No Matches
Acquisition.cpp

Acquisition.cpp shows how to acquire images.

Acquisition.cpp shows how to acquire images. It relies on information provided in the Enumeration example. Also, check out the ExceptionHandling and NodeMapInfo examples if you haven't already. ExceptionHandling shows the handling of standard and Spinnaker exceptions while NodeMapInfo explores retrieving information from various node types.

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.

Once comfortable with Acquisition, we suggest checking out AcquisitionMultipleCamera, NodeMapCallback, or SaveToVideo. AcquisitionMultipleCamera demonstrates simultaneously acquiring images from a number of cameras, NodeMapCallback serves as a good introduction to programming with callbacks and events, and SaveToVideo exhibits video creation.

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) 2024 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 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.
//=============================================================================
#include "Spinnaker.h"
#include <iostream>
#include <sstream>
using namespace Spinnaker;
using namespace Spinnaker::GenApi;
using namespace Spinnaker::GenICam;
using namespace std;
// Use the following enum to select the stream mode
{
STREAM_MODE_TELEDYNE_GIGE_VISION, // Teledyne Gige Vision is the default stream mode for spinview which is supported on Windows
STREAM_MODE_PGRLWF, // Light Weight Filter driver is our legacy driver which is supported on Windows
STREAM_MODE_SOCKET, // Socket is supported for MacOS and Linux, and uses native OS network sockets instead of a
// filter driver
};
#if defined(WIN32) || defined(WIN64)
#else
#endif
// Disables or enables heartbeat on GEV cameras so debugging does not incur timeout errors
int ConfigureGVCPHeartbeat(CameraPtr pCam, bool enableHeartbeat)
{
//
// Write to boolean node controlling the camera's heartbeat
//
// *** NOTES ***
// This applies only to GEV cameras.
//
// GEV cameras have a heartbeat built in, but when debugging applications the
// camera may time out due to its heartbeat. Disabling the heartbeat prevents
// this timeout from occurring, enabling us to continue with any necessary
// debugging.
//
// *** LATER ***
// Make sure that the heartbeat is reset upon completion of the debugging.
// If the application is terminated unexpectedly, the camera may not locked
// to Spinnaker indefinitely due to the the timeout being disabled. When that
// happens, a camera power cycle will reset the heartbeat to its default setting.
// Retrieve TL device nodemap
INodeMap& nodeMapTLDevice = pCam->GetTLDeviceNodeMap();
// Retrieve GenICam nodemap
INodeMap& nodeMap = pCam->GetNodeMap();
CEnumerationPtr ptrDeviceType = nodeMapTLDevice.GetNode("DeviceType");
if (!IsReadable(ptrDeviceType))
{
return -1;
}
if (ptrDeviceType->GetIntValue() != DeviceType_GigEVision)
{
return 0;
}
if (enableHeartbeat)
{
cout << endl << "Resetting heartbeat..." << endl << endl;
}
else
{
cout << endl << "Disabling heartbeat..." << endl << endl;
}
CBooleanPtr ptrDeviceHeartbeat = nodeMap.GetNode("GevGVCPHeartbeatDisable");
if (!IsWritable(ptrDeviceHeartbeat))
{
cout << "Unable to configure heartbeat. Continuing with execution as this may be non-fatal..." << endl << endl;
}
else
{
ptrDeviceHeartbeat->SetValue(!enableHeartbeat);
if (!enableHeartbeat)
{
cout << "WARNING: Heartbeat has been disabled for the rest of this example run." << endl;
cout << " Heartbeat will be reset upon the completion of this run. If the " << endl;
cout << " example is aborted unexpectedly before the heartbeat is reset, the" << endl;
cout << " camera may need to be power cycled to reset the heartbeat." << endl << endl;
}
else
{
cout << "Heartbeat has been reset." << endl;
}
}
return 0;
}
{
return ConfigureGVCPHeartbeat(pCam, true);
}
{
return ConfigureGVCPHeartbeat(pCam, false);
}
// This function demonstrates how we can change stream modes.
{
int result = 0;
// Retrieve Stream nodemap
const INodeMap& sNodeMap = pCam->GetTLStreamNodeMap();
// The node "StreamMode" is only available for GEV cameras.
// Skip setting stream mode if the node is inaccessible.
const CEnumerationPtr ptrStreamMode = sNodeMap.GetNode("StreamMode");
if (!IsReadable(ptrStreamMode) || !IsWritable(ptrStreamMode))
{
return 0;
}
gcstring streamMode;
{
streamMode = "LWF";
break;
streamMode = "Socket";
break;
default:
streamMode = "TeledyneGigeVision";
}
// Retrieve the desired entry node from the enumeration node
const CEnumEntryPtr ptrStreamModeCustom = ptrStreamMode->GetEntryByName(streamMode);
if (!IsReadable(ptrStreamModeCustom))
{
// Failed to get custom node
cout << "Stream mode " + streamMode + " not available. Aborting..." << endl;
return -1;
}
// Retrieve the integer value from the entry node
const int64_t streamModeCustom = ptrStreamModeCustom->GetValue();
// Set integer as new value for enumeration node
ptrStreamMode->SetIntValue(streamModeCustom);
// Print out the current stream mode
cout << endl << "Stream Mode set to " + ptrStreamMode->GetCurrentEntry()->GetSymbolic() << "..." << endl;
return 0;
}
// This function acquires and saves 10 images from a device.
int AcquireImages(CameraPtr pCam, INodeMap& nodeMap, INodeMap& nodeMapTLDevice)
{
int result = 0;
cout << endl << endl << "*** IMAGE ACQUISITION ***" << endl << endl;
try
{
//
// Set acquisition mode to continuous
//
// *** NOTES ***
// Because the example acquires and saves 10 images, setting acquisition
// mode to continuous lets the example finish. If set to single frame
// or multiframe (at a lower number of images), the example would just
// hang. This would happen because the example has been written to
// acquire 10 images while the camera would have been programmed to
// retrieve less than that.
//
// Setting the value of an enumeration node is slightly more complicated
// than other node types. Two nodes must be retrieved: first, the
// enumeration node is retrieved from the nodemap; and second, the entry
// node is retrieved from the enumeration node. The integer value of the
// entry node is then set as the new value of the enumeration node.
//
// Notice that both the enumeration and the entry nodes are checked for
// availability and readability/writability. Enumeration nodes are
// generally readable and writable whereas their entry nodes are only
// ever readable.
//
// Retrieve enumeration node from nodemap
CEnumerationPtr ptrAcquisitionMode = nodeMap.GetNode("AcquisitionMode");
if (!IsReadable(ptrAcquisitionMode) || !IsWritable(ptrAcquisitionMode))
{
cout << "Unable to set acquisition mode to continuous (enum retrieval). Aborting..." << endl << endl;
return -1;
}
// Retrieve entry node from enumeration node
CEnumEntryPtr ptrAcquisitionModeContinuous = ptrAcquisitionMode->GetEntryByName("Continuous");
if (!IsReadable(ptrAcquisitionModeContinuous))
{
cout << "Unable to get or set acquisition mode to continuous (entry retrieval). Aborting..." << endl
<< endl;
return -1;
}
// Retrieve integer value from entry node
const int64_t acquisitionModeContinuous = ptrAcquisitionModeContinuous->GetValue();
// Set integer value from entry node as new value of enumeration node
ptrAcquisitionMode->SetIntValue(acquisitionModeContinuous);
cout << "Acquisition mode set to continuous..." << endl;
//
// Begin acquiring images
//
// *** NOTES ***
// What happens when the camera begins acquiring images depends on the
// acquisition mode. Single frame captures only a single image, multi
// frame captures a set number of images, and continuous captures a
// continuous stream of images. Because the example calls for the
// retrieval of 10 images, continuous mode has been set.
//
// *** LATER ***
// Image acquisition must be ended when no more images are needed.
//
pCam->BeginAcquisition();
cout << "Acquiring images..." << endl;
//
// Retrieve device serial number for filename
//
// *** NOTES ***
// The device serial number is retrieved in order to keep cameras from
// overwriting one another. Grabbing image IDs could also accomplish
// this.
//
gcstring deviceSerialNumber("");
CStringPtr ptrStringSerial = nodeMapTLDevice.GetNode("DeviceSerialNumber");
if (IsReadable(ptrStringSerial))
{
deviceSerialNumber = ptrStringSerial->GetValue();
cout << "Device serial number retrieved as " << deviceSerialNumber << "..." << endl;
}
cout << endl;
// Retrieve, convert, and save images
const unsigned int k_numImages = 10;
//
// Create ImageProcessor instance for post processing images
//
ImageProcessor processor;
//
// Set default image processor color processing method
//
// *** NOTES ***
// By default, if no specific color processing algorithm is set, the image
// processor will default to NEAREST_NEIGHBOR method.
//
processor.SetColorProcessing(SPINNAKER_COLOR_PROCESSING_ALGORITHM_HQ_LINEAR);
for (unsigned int imageCnt = 0; imageCnt < k_numImages; imageCnt++)
{
try
{
//
// Retrieve next received image
//
// *** NOTES ***
// Per default, the camera immediately transmits captured images
// to the PC where they fill up Spinnaker's image buffers in the
// PC's working memory.
// Depending on the buffer handling mode (see example
// BufferHandling), calling GetNextImage will return either the
// newest or oldest image from these buffers.
// If the buffers are empty when GetNextImage is called, the call
// will hang until the next image arrives or until the timeout
// value is reached.
//
// *** LATER ***
// Once an image from the buffer is saved and/or no longer
// needed, the image must be released in order to keep the
// buffer from filling up.
//
ImagePtr pResultImage = pCam->GetNextImage(1000);
//
// Ensure image completion
//
// *** NOTES ***
// Images can easily be checked for completion. This should be
// done whenever a complete image is expected or required.
// Further, check image status for a little more insight into
// why an image is incomplete.
//
if (pResultImage->IsIncomplete())
{
// Retrieve and print the image status description
cout << "Image incomplete: " << Image::GetImageStatusDescription(pResultImage->GetImageStatus())
<< "..." << endl
<< endl;
}
else
{
//
// Print image information; height and width recorded in pixels
//
// *** NOTES ***
// Images have quite a bit of available metadata including
// things such as CRC, image status, and offset values, to
// name a few.
//
const size_t width = pResultImage->GetWidth();
const size_t height = pResultImage->GetHeight();
cout << "Grabbed image " << imageCnt << ", width = " << width << ", height = " << height << endl;
//
// Convert image to mono 8
//
// *** NOTES ***
// Images can be converted between pixel formats by using
// the appropriate enumeration value. Unlike the original
// image, the converted one does not need to be released as
// it does not affect the camera buffer.
//
// When converting images, color processing algorithm is an
// optional parameter.
//
ImagePtr convertedImage = processor.Convert(pResultImage, PixelFormat_Mono8);
// Create a unique filename
ostringstream filename;
filename << "Acquisition-";
if (!deviceSerialNumber.empty())
{
filename << deviceSerialNumber.c_str() << "-";
}
filename << imageCnt << ".jpg";
//
// Save image
//
// *** NOTES ***
// The standard practice of the examples is to use device
// serial numbers to keep images of one device from
// overwriting those of another.
//
convertedImage->Save(filename.str().c_str());
cout << "Image saved at " << filename.str() << endl;
}
//
// Release image
//
// *** NOTES ***
// Images retrieved directly from the camera (i.e. non-converted
// images) need to be released in order to keep them from filling
// the buffers.
//
pResultImage->Release();
cout << endl;
}
{
cout << "Error: " << e.what() << endl;
result = -1;
}
}
//
// 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;
return -1;
}
return result;
}
// This function prints the device information of the camera from the transport
// layer; please see NodeMapInfo example for more in-depth comments on printing
// device information from the nodemap.
int PrintDeviceInfo(INodeMap& nodeMap)
{
int result = 0;
cout << endl << "*** DEVICE INFORMATION ***" << endl << endl;
try
{
FeatureList_t features;
const CCategoryPtr category = nodeMap.GetNode("DeviceInformation");
if (IsReadable(category))
{
category->GetFeatures(features);
for (auto it = features.begin(); it != features.end(); ++it)
{
const CNodePtr pfeatureNode = *it;
cout << pfeatureNode->GetName() << " : ";
CValuePtr pValue = static_cast<CValuePtr>(pfeatureNode);
cout << (IsReadable(pValue) ? pValue->ToString() : "Node not readable");
cout << endl;
}
}
else
{
cout << "Device control information not available." << endl;
}
}
{
cout << "Error: " << e.what() << endl;
result = -1;
}
return result;
}
// This function acts as the body of the example; please see NodeMapInfo example
// for more in-depth comments on setting up cameras.
{
int result;
try
{
// Retrieve TL device nodemap and print device information
INodeMap& nodeMapTLDevice = pCam->GetTLDeviceNodeMap();
result = PrintDeviceInfo(nodeMapTLDevice);
// Initialize camera
pCam->Init();
// Retrieve GenICam nodemap
INodeMap& nodeMap = pCam->GetNodeMap();
// Configure heartbeat for GEV camera
#ifdef _DEBUG
result = result | DisableGVCPHeartbeat(pCam);
#else
result = result | ResetGVCPHeartbeat(pCam);
#endif
// Set stream mode
result = result | SetStreamMode(pCam);
// Acquire images
result = result | AcquireImages(pCam, nodeMap, nodeMapTLDevice);
#ifdef _DEBUG
// Reset heartbeat for GEV camera
result = result | ResetGVCPHeartbeat(pCam);
#endif
// Deinitialize camera
pCam->DeInit();
}
{
cout << "Error: " << e.what() << endl;
result = -1;
}
return result;
}
// Example entry point; please see Enumeration 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");
// 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;
int result = 0;
// 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 = result | RunSingleCamera(pCam);
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;
}
int AcquireImages(CameraPtr pCam, INodeMap &nodeMap, INodeMap &nodeMapTLDevice)
Definition Acquisition.cpp:199
int main(int, char **)
Definition Acquisition.cpp:527
StreamMode
Definition Acquisition.cpp:54
@ STREAM_MODE_SOCKET
Definition Acquisition.cpp:57
@ STREAM_MODE_TELEDYNE_GIGE_VISION
Definition Acquisition.cpp:55
@ STREAM_MODE_PGRLWF
Definition Acquisition.cpp:56
int ResetGVCPHeartbeat(CameraPtr pCam)
Definition Acquisition.cpp:138
int ConfigureGVCPHeartbeat(CameraPtr pCam, bool enableHeartbeat)
Definition Acquisition.cpp:68
const StreamMode chosenStreamMode
Definition Acquisition.cpp:64
int RunSingleCamera(CameraPtr pCam)
Definition Acquisition.cpp:479
int PrintDeviceInfo(INodeMap &nodeMap)
Definition Acquisition.cpp:441
int DisableGVCPHeartbeat(CameraPtr pCam)
Definition Acquisition.cpp:143
int SetStreamMode(CameraPtr pCam)
Definition Acquisition.cpp:149
const unsigned int k_numImages
Definition AcquisitionMultipleCamerasWriteToFile.cpp:55
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 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
Image post processing class for converting a source image to another pixel format.
Definition ImageProcessor.h:159
void SetColorProcessing(ColorProcessingAlgorithm colorAlgorithm)
Sets the color processing algorithm used at the time of the Convert() call, therefore the most recent...
ImagePtr Convert(const ImagePtr &srcImage, PixelFormatEnums destFormat) const
Converts the source image buffer to the specified destination pixel format and returns the result in ...
A reference tracked pointer to an image object.
Definition ImagePtr.h:46
A reference tracked pointer to a system object.
Definition SystemPtr.h:44
bool IsWritable(EAccessMode AccessMode)
Tests if writable.
Definition INode.h:277
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
Definition Autovector.h:36
Definition GCString.h:31
Definition BasePtr.h:24
Provides easier access to the current version of Spinnaker.
Definition SpinnakerDefs.h:657
unsigned int minor
Minor version of the library.
Definition SpinnakerDefs.h:662
unsigned int major
Major version of the library.
Definition SpinnakerDefs.h:659
unsigned int type
Version type of the library.
Definition SpinnakerDefs.h:665
unsigned int build
Build number of the library.
Definition SpinnakerDefs.h:668