This repository has been archived by the owner. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 2afbcb4
Showing
6 changed files
with
415 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# C++ objects and libs | ||
|
||
*.slo | ||
*.lo | ||
*.o | ||
*.a | ||
*.la | ||
*.lai | ||
*.so | ||
*.dll | ||
*.dylib | ||
|
||
# Qt-es | ||
|
||
/.qmake.cache | ||
/.qmake.stash | ||
*.pro.user | ||
*.pro.user.* | ||
*.qbs.user | ||
*.qbs.user.* | ||
*.moc | ||
moc_*.cpp | ||
qrc_*.cpp | ||
ui_*.h | ||
Makefile* | ||
*build-* | ||
|
||
# QtCreator | ||
|
||
*.autosave | ||
|
||
# QtCtreator Qml | ||
*.qmlproject.user | ||
*.qmlproject.user.* | ||
|
||
# QtCtreator CMake | ||
CMakeLists.txt.user* | ||
|
||
#Pylon setting files | ||
*.pfs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# SpinnakerCapture |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,288 @@ | ||
#include "SpinnakerCapture.h" | ||
|
||
SpinnakerCapture::SpinnakerCapture(QObject *parent) | ||
{ | ||
// Retrieve singleton reference to system object | ||
system = System::GetInstance(); | ||
|
||
// Retrieve list of cameras from the system | ||
camList = system->GetCameras(); | ||
|
||
unsigned int numCameras = camList.GetSize(); | ||
|
||
qDebug() << "Number of cameras detected: " << numCameras; | ||
|
||
// Finish ifthere are no cameras | ||
if(numCameras == 0){ | ||
// Clear camera list before releasing system | ||
camList.Clear(); | ||
|
||
// Release system | ||
system->ReleaseInstance(); | ||
|
||
qDebug() << "Not enough cameras!" ; | ||
qDebug() << "Done! Press Enter to exit..." ; | ||
getchar(); | ||
|
||
qDebug()<<"BAD"; | ||
} | ||
|
||
pCam = NULL; | ||
|
||
pCam = camList.GetByIndex(0); | ||
|
||
try{ | ||
// Retrieve TL device nodemap and print device information | ||
nodeMapTLDevice = &pCam->GetTLDeviceNodeMap(); | ||
|
||
// Initialize camera | ||
pCam->Init(); | ||
|
||
// Retrieve GenICam nodemap | ||
nodeMap = &pCam->GetNodeMap(); | ||
|
||
CIntegerPtr ptrWidth = nodeMap->GetNode("Width"); | ||
width = ptrWidth->GetValue(); | ||
CIntegerPtr ptrHeight = nodeMap->GetNode("Height"); | ||
height = ptrHeight->GetValue(); | ||
|
||
qDebug()<< "Initialized Spinnaker compatible camera (" << width << "x" << height << ")"; | ||
isInitialized = true; | ||
} | ||
catch (Spinnaker::Exception &e){ | ||
qDebug() << "Error: " << e.what() ; | ||
} | ||
} | ||
|
||
// This function configures a custom exposure time. Automatic exposure is turned | ||
// off in order to allow for the customization, and then the custom setting is | ||
// applied. | ||
int SpinnakerCapture::configureExposure(double exposureTimeToSet) | ||
{ | ||
int result = 0; | ||
|
||
qDebug() << "*** CONFIGURING EXPOSURE ***"; | ||
|
||
try{ | ||
// | ||
// Turn off automatic exposure mode | ||
// | ||
// *** NOTES *** | ||
// Automatic exposure prevents the manual configuration of exposure | ||
// time and needs to be turned off. | ||
// | ||
// *** LATER *** | ||
// Exposure time can be set automatically or manually as needed. This | ||
// example turns automatic exposure off to set it manually and back | ||
// on in order to return the camera to its default state. | ||
// | ||
CEnumerationPtr ptrExposureAuto = nodeMap->GetNode("ExposureAuto"); | ||
if(!IsAvailable(ptrExposureAuto) || !IsWritable(ptrExposureAuto)){ | ||
qDebug() << "Unable to disable automatic exposure (node retrieval). Aborting..."; | ||
return -1; | ||
} | ||
|
||
CEnumEntryPtr ptrExposureAutoOff = ptrExposureAuto->GetEntryByName("Off"); | ||
if(!IsAvailable(ptrExposureAutoOff) || !IsReadable(ptrExposureAutoOff)){ | ||
qDebug() << "Unable to disable automatic exposure (enum entry retrieval). Aborting..."; | ||
return -1; | ||
} | ||
|
||
ptrExposureAuto->SetIntValue(ptrExposureAutoOff->GetValue()); | ||
|
||
qDebug() << "Automatic exposure disabled..."; | ||
|
||
// | ||
// Set exposure time manually; exposure time recorded in microseconds | ||
// | ||
// *** NOTES *** | ||
// The node is checked for availability and writability prior to the | ||
// setting of the node. Further, it is ensured that the desired exposure | ||
// time does not exceed the maximum. Exposure time is counted in | ||
// microseconds. This information can be found out either by | ||
// retrieving the unit with the GetUnit() method or by checking SpinView. | ||
// | ||
CFloatPtr ptrExposureTime = nodeMap->GetNode("ExposureTime"); | ||
if(!IsAvailable(ptrExposureTime) || !IsWritable(ptrExposureTime)){ | ||
qDebug() << "Unable to set exposure time. Aborting..."; | ||
return -1; | ||
} | ||
|
||
// Ensure desired exposure time does not exceed the maximum | ||
const double exposureTimeMax = ptrExposureTime->GetMax(); | ||
|
||
if(exposureTimeToSet > exposureTimeMax){ | ||
exposureTimeToSet = exposureTimeMax; | ||
} | ||
|
||
ptrExposureTime->SetValue(exposureTimeToSet); | ||
|
||
qDebug() << "Exposure time set to " << exposureTimeToSet << " us..."; | ||
} | ||
catch(Spinnaker::Exception &e){ | ||
qDebug() << "Error: " << e.what() ; | ||
result = -1; | ||
} | ||
|
||
return result; | ||
} | ||
|
||
// This function acquires and saves 10 images from a device. | ||
int SpinnakerCapture::acquireImages(unsigned int nImagesToCapture) | ||
{ | ||
int result = 0; | ||
|
||
qDebug() << "*** IMAGE ACQUISITION ***"; | ||
|
||
try{ | ||
// | ||
// Set acquisition mode to continuous | ||
// | ||
// *** NOTES *** | ||
// Because the example acquires and saves 10 images, setting acquisition | ||
// mode to continuous lets the example finish. ifset 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(!IsAvailable(ptrAcquisitionMode) || !IsWritable(ptrAcquisitionMode)){ | ||
qDebug() << "Unable to set acquisition mode to continuous (enum retrieval). Aborting..."; | ||
return -1; | ||
} | ||
|
||
// Retrieve entry node from enumeration node | ||
CEnumEntryPtr ptrAcquisitionModeContinuous = ptrAcquisitionMode->GetEntryByName("Continuous"); | ||
if(!IsAvailable(ptrAcquisitionModeContinuous) || !IsReadable(ptrAcquisitionModeContinuous)){ | ||
qDebug() << "Unable to set acquisition mode to continuous (entry retrieval). Aborting..."; | ||
return -1; | ||
} | ||
|
||
// Retrieve integer value from entry node | ||
int64_t acquisitionModeContinuous = ptrAcquisitionModeContinuous->GetValue(); | ||
|
||
// Set integer value from entry node as new value of enumeration node | ||
ptrAcquisitionMode->SetIntValue(acquisitionModeContinuous); | ||
|
||
|
||
pCam->BeginAcquisition(); | ||
|
||
// Retrieve, convert, and emit images | ||
for (unsigned int imageCnt = 0; imageCnt < nImagesToCapture; imageCnt++){ | ||
try{ | ||
ImagePtr pResultImage = pCam->GetNextImage(); | ||
|
||
if(pResultImage->IsIncomplete()){ | ||
qDebug() << "Image incomplete with image status " << pResultImage->GetImageStatus() << "..."; | ||
}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. | ||
// | ||
|
||
ImagePtr convertedImage = pResultImage->Convert(PixelFormat_BGR8, NEAREST_NEIGHBOR); | ||
|
||
unsigned int XPadding = convertedImage->GetXPadding(); | ||
unsigned int YPadding = convertedImage->GetYPadding(); | ||
unsigned int rowsize = convertedImage->GetWidth(); | ||
unsigned int colsize = convertedImage->GetHeight(); | ||
|
||
//image data contains padding. When allocating Mat container size, you need to account for the X,Y image data padding. | ||
cv::Mat cvMat = cv::Mat(colsize + YPadding, rowsize + XPadding, CV_8UC3, convertedImage->GetData(), convertedImage->GetStride()); | ||
|
||
emit(sendFrame(cvMat.clone())); | ||
|
||
} | ||
|
||
// Images retrieved directly from the camera (i.e. non-converted | ||
// images) need to be released in order to keep from filling the | ||
// buffer. | ||
pResultImage->Release(); | ||
|
||
}catch (Spinnaker::Exception &e){ | ||
qDebug() << "Error: " << e.what() ; | ||
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(); | ||
} | ||
catch (Spinnaker::Exception &e){ | ||
qDebug() << "Error: " << e.what() ; | ||
result = -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 SpinnakerCapture::printDeviceInfo() | ||
{ | ||
int result = 0; | ||
|
||
qDebug() << "*** DEVICE INFORMATION ***"; | ||
|
||
try{ | ||
FeatureList_t features; | ||
CCategoryPtr category = nodeMap->GetNode("DeviceInformation"); | ||
if(IsAvailable(category) && IsReadable(category)){ | ||
category->GetFeatures(features); | ||
|
||
FeatureList_t::const_iterator it; | ||
for (it = features.begin(); it != features.end(); ++it){ | ||
CNodePtr pfeatureNode = *it; | ||
qDebug() << pfeatureNode->GetName() << " : "; | ||
CValuePtr pValue = (CValuePtr)pfeatureNode; | ||
qDebug() << (IsReadable(pValue) ? pValue->ToString() : "Node not readable"); | ||
} | ||
} | ||
else{ | ||
qDebug() << "Device control information not available."; | ||
} | ||
} | ||
catch (Spinnaker::Exception &e){ | ||
qDebug() << "Error: " << e.what() ; | ||
result = -1; | ||
} | ||
|
||
return result; | ||
} | ||
|
||
SpinnakerCapture::~SpinnakerCapture() | ||
{ | ||
// Deinitialize camera | ||
pCam->DeInit(); | ||
delete nodeMapTLDevice; | ||
delete nodeMap; | ||
// Clear camera list before releasing system | ||
camList.Clear(); | ||
// // Release system | ||
system->ReleaseInstance(); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#ifndef SPINNAKERCAPTURE_H | ||
#define SPINNAKERCAPTURE_H | ||
#include "Spinnaker.h" | ||
#include "SpinGenApi/SpinnakerGenApi.h" | ||
#include <opencv2/core/core.hpp> | ||
#include <QDebug> | ||
#include <QObject> | ||
|
||
using namespace Spinnaker; | ||
using namespace Spinnaker::GenApi; | ||
using namespace Spinnaker::GenICam; | ||
using namespace std; | ||
|
||
class SpinnakerCapture : public QObject | ||
{ | ||
Q_OBJECT | ||
public: | ||
SpinnakerCapture(QObject *parent = 0); | ||
int printDeviceInfo(); | ||
bool isInitialized = false; | ||
unsigned int width = 0; | ||
unsigned int height = 0; | ||
~SpinnakerCapture(); | ||
private: | ||
CameraPtr pCam; | ||
INodeMap* nodeMapTLDevice; | ||
INodeMap* nodeMap; | ||
SystemPtr system; | ||
CameraList camList; | ||
signals: | ||
void sendFrame(cv::Mat); | ||
public slots: | ||
int configureExposure(double exposureTimeToSet); | ||
int acquireImages(unsigned int nImagesToCapture); | ||
}; | ||
|
||
#endif // SPINNAKERCAPTURE_H |
Oops, something went wrong.