From 2afbcb4ea2e3d4d4416a329b1e5555acf8477b4d Mon Sep 17 00:00:00 2001 From: MPIBR-kretschmerf Date: Thu, 1 Jun 2017 10:45:30 +0200 Subject: [PATCH] first commit --- .gitignore | 40 ++++++ README.md | 1 + SpinnakerCapture.cpp | 288 +++++++++++++++++++++++++++++++++++++++++++ SpinnakerCapture.h | 37 ++++++ SpinnakerCapture.pro | 41 ++++++ main.cpp | 8 ++ 6 files changed, 415 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 SpinnakerCapture.cpp create mode 100644 SpinnakerCapture.h create mode 100644 SpinnakerCapture.pro create mode 100644 main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9cf40e8 --- /dev/null +++ b/.gitignore @@ -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 diff --git a/README.md b/README.md new file mode 100644 index 0000000..278159f --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# SpinnakerCapture diff --git a/SpinnakerCapture.cpp b/SpinnakerCapture.cpp new file mode 100644 index 0000000..12b0af7 --- /dev/null +++ b/SpinnakerCapture.cpp @@ -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(); +} + diff --git a/SpinnakerCapture.h b/SpinnakerCapture.h new file mode 100644 index 0000000..87ef6da --- /dev/null +++ b/SpinnakerCapture.h @@ -0,0 +1,37 @@ +#ifndef SPINNAKERCAPTURE_H +#define SPINNAKERCAPTURE_H +#include "Spinnaker.h" +#include "SpinGenApi/SpinnakerGenApi.h" +#include +#include +#include + +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 diff --git a/SpinnakerCapture.pro b/SpinnakerCapture.pro new file mode 100644 index 0000000..2c29cee --- /dev/null +++ b/SpinnakerCapture.pro @@ -0,0 +1,41 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2017-05-31T14:20:58 +# +#------------------------------------------------- + +QT += core + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = PtGrey +TEMPLATE = app + + +SOURCES += main.cpp\ + SpinnakerCapture.cpp + +HEADERS += \ + SpinnakerCapture.h + +FORMS += + +INCLUDEPATH += "C:\\Program Files\\Point Grey Research\\Spinnaker\\include" +INCLUDEPATH += "D:\\opencv\\build_vc12\\install\\include" + + +LIBS += -L"C:\\Program Files\\Point Grey Research\\Spinnaker\\lib64\\vs2013" +LIBS += -lSpinnaker_v120 + +LIBS += -L"D:\\opencv\\build_vc12\\install\\x64\\vc12\\lib" \ + -lopencv_core310 \ + -lopencv_highgui310 \ + -lopencv_imgproc310 \ + -lopencv_features2d310 \ + -lopencv_videoio310 \ + -lopencv_video310 \ + -lopencv_videostab310 \ +#LIBS += -L"C:\\Program Files\\Point Grey Research\\Spinnaker\\bin64\\vs2013" +#LIBS += -lSpinnaker_* +#LIBS += -lGenTL_* +#LIBS += -llibiomp5md diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..584b4af --- /dev/null +++ b/main.cpp @@ -0,0 +1,8 @@ +#include "SpinnakerCapture.h" + +int main(int argc, char *argv[]) +{ + SpinnakerCapture spinnakerCapture(); + + return 0; +}