Skip to content

Instantly share code, notes, and snippets.

@fernandoc1
Created January 23, 2017 15:29
Show Gist options
  • Save fernandoc1/395f77d868d51a154c2ebd34408b76a9 to your computer and use it in GitHub Desktop.
Save fernandoc1/395f77d868d51a154c2ebd34408b76a9 to your computer and use it in GitHub Desktop.
GeniCam image grabbing with Pleora SDK on Ubuntu 16.04
cmake_minimum_required(VERSION 2.8.3)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -g3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3 -fPIC")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIC")
find_package(OpenCV 2.4 REQUIRED opencv_core opencv_highgui opencv_imgproc opencv_calib3d opencv_video opencv_features2d opencv_objdetect opencv_ocl)
set(PLEORA_BASE_DIR /opt/pleora/ebus_sdk/Ubuntu-14.04-x86_64/)
set(PLEORA_INCLUDE_DIR ${PLEORA_BASE_DIR}/include/)
set(PLEORA_LIBRARY_DIR ${PLEORA_BASE_DIR}/lib/)
set(PLEORA_GENICAM_ROOT ${PLEORA_BASE_DIR}/lib/genicam)
file(GLOB IVSN_FLIR_SOURCES ${CMAKE_SOURCE_DIR}/src/*.cpp)
message("\n ${IVSN_FLIR_SOURCES} \n")
include_directories(${PLEORA_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/include)
link_directories(${PLEORA_LIBRARY_DIR})
add_executable(IvsnFlir.bin ${IVSN_FLIR_SOURCES})
target_link_libraries(IvsnFlir.bin PvBase PvBuffer PvStream PvDevice PvGenICam opencv_core opencv_highgui pthread)
set(EXECUTABLE_SCRIPT ${CMAKE_BINARY_DIR}/IvsnFlir)
file(WRITE ${EXECUTABLE_SCRIPT} "#! /bin/bash \n\nGENICAM_ROOT_V2_4=${PLEORA_GENICAM_ROOT} ./IvsnFlir.bin\n\n")
execute_process(COMMAND /bin/chmod +x "${EXECUTABLE_SCRIPT}")
#include "gev_camera.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <iomanip>
GEVCamera::GEVCamera(std::string macAddress)
: macAddress(macAddress.c_str())
, running(true)
, system()
, stream(NULL)
, device(NULL)
, bufferList()
, deviceInfo()
, imgWidth()
, imgHeight()
, imgBufferPtr(NULL)
, threadPtr()
, imgReadyConditionVariable()
, imgReadyMutex()
{
}
void GEVCamera::connect()
{
if(this->threadPtr != nullptr)
{
std::cerr << "GEVCamera::connect: error: there is a connection running." << std::endl;
return;
}
PvResult result = this->system.FindDevice(this->macAddress, &this->deviceInfo);
this->device = PvDevice::CreateAndConnect(this->deviceInfo, &result);
this->stream = this->openStream(deviceInfo);
this->configureStream(device, stream);
this->createStreamBuffers(this->device, stream, &this->bufferList);
this->running = true;
this->threadPtr = std::make_shared<std::thread>(&GEVCamera::acquireImages, this, this->device, this->stream);
}
PvStream* GEVCamera::openStream(const PvDeviceInfo *aDeviceInfo)
{
PvStream *lStream;
PvResult lResult;
// Open stream to the GigE Vision or USB3 Vision device
std::cout << "Opening stream to device." << std::endl;
lStream = PvStream::CreateAndOpen( aDeviceInfo->GetConnectionID(), &lResult );
if ( lStream == NULL )
{
std::cout << "Unable to stream from " << aDeviceInfo->GetDisplayID().GetAscii() << "." << std::endl;
}
return lStream;
}
void GEVCamera::configureStream(PvDevice* aDevice, PvStream* aStream)
{
// If this is a GigE Vision device, configure GigE Vision specific streaming parameters
PvDeviceGEV* lDeviceGEV = dynamic_cast<PvDeviceGEV *>( aDevice );
if ( lDeviceGEV != NULL )
{
PvStreamGEV *lStreamGEV = static_cast<PvStreamGEV *>( aStream );
// Negotiate packet size
lDeviceGEV->NegotiatePacketSize();
// Configure device streaming destination
lDeviceGEV->SetStreamDestination( lStreamGEV->GetLocalIPAddress(), lStreamGEV->GetLocalPort() );
}
}
void GEVCamera::createStreamBuffers(PvDevice* aDevice, PvStream* aStream, BufferList* aBufferList)
{
// Reading payload size from device
uint32_t lSize = aDevice->GetPayloadSize();
// Use BUFFER_COUNT or the maximum number of buffers, whichever is smaller
uint32_t lBufferCount = ( aStream->GetQueuedBufferMaximum() < BUFFER_COUNT ) ?
aStream->GetQueuedBufferMaximum() :
BUFFER_COUNT;
// Allocate buffers
for ( uint32_t i = 0; i < lBufferCount; i++ )
{
// Create new buffer object
PvBuffer *lBuffer = new PvBuffer;
// Have the new buffer object allocate payload memory
lBuffer->Alloc( static_cast<uint32_t>( lSize ) );
// Add to external list - used to eventually release the buffers
aBufferList->push_back( lBuffer );
}
// Queue all buffers in the stream
BufferList::iterator lIt = aBufferList->begin();
while ( lIt != aBufferList->end() )
{
aStream->QueueBuffer( *lIt );
lIt++;
}
}
cv::Mat1b GEVCamera::getImage()
{
std::unique_lock<std::mutex> lock(this->imgReadyMutex);
this->imgReadyConditionVariable.wait(lock);
return cv::Mat1b(this->imgHeight, this->imgWidth, this->imgBufferPtr);
}
void GEVCamera::acquireImages(PvDevice *aDevice, PvStream *aStream)
{
// Get device parameters need to control streaming
PvGenParameterArray *lDeviceParams = aDevice->GetParameters();
// Map the GenICam AcquisitionStart and AcquisitionStop commands
PvGenCommand *lStart = dynamic_cast<PvGenCommand *>(lDeviceParams->Get("AcquisitionStart"));
// Get stream parameters
PvGenParameterArray *lStreamParams = aStream->GetParameters();
// Map a few GenICam stream stats counters
PvGenFloat *lFrameRate = dynamic_cast<PvGenFloat *>(lStreamParams->Get("AcquisitionRate"));
PvGenFloat *lBandwidth = dynamic_cast<PvGenFloat *>(lStreamParams->Get("Bandwidth"));
// Enable streaming and send the AcquisitionStart command
std::cout << "Enabling streaming and sending AcquisitionStart command." << std::endl;
aDevice->StreamEnable();
lStart->Execute();
double lFrameRateVal = 0.0;
double lBandwidthVal = 0.0;
while(this->running)
{
PvBuffer *lBuffer = NULL;
PvResult lOperationResult;
// Retrieve next buffer
PvResult lResult = aStream->RetrieveBuffer( &lBuffer, &lOperationResult, 1000 );
if ( lResult.IsOK() )
{
//std::cout << "Result OK" << std::endl;
if ( lOperationResult.IsOK() )
{
//std::cout << "Operation OK" << std::endl;
PvPayloadType lType;
//
// We now have a valid buffer. This is where you would typically process the buffer.
// -----------------------------------------------------------------------------------------
// ...
lFrameRate->GetValue( lFrameRateVal );
lBandwidth->GetValue( lBandwidthVal );
// If the buffer contains an image, display width and height.
lType = lBuffer->GetPayloadType();
if ( lType == PvPayloadTypeImage )
{
// Get image specific buffer interface.
PvImage *lImage = lBuffer->GetImage();
// Read width, height.
this->imgWidth = lImage->GetWidth();
this->imgHeight = lImage->GetHeight();
//std::cout << " W: " << std::dec << lWidth << " H: " << lHeight;
uint32_t imgSize = this->imgHeight*this->imgWidth;
if(this->imgBufferPtr == NULL)
{
this->imgBufferPtr = (uint8_t*)malloc(imgSize);
}
memcpy(this->imgBufferPtr, lImage->GetDataPointer(), imgSize);
this->imgReadyConditionVariable.notify_one();
//cv::Mat1b img(this->imgHeight, this->imgWidth, lImage->GetDataPointer());
//cv::imshow("Display", img);
//cv::waitKey(1);
}
else
{
std::cout << " (buffer does not contain image)";
}
}
// Re-queue the buffer in the stream object
aStream->QueueBuffer( lBuffer );
}
else
{
std::cout << "error: " << lResult.GetCodeString().GetAscii() << std::endl;
}
}
// Tell the device to stop sending images.
}
void GEVCamera::disconnect()
{
this->running = false;
this->threadPtr.get()->join();
PvGenParameterArray *lDeviceParams = this->device->GetParameters();
PvGenCommand *lStop = dynamic_cast<PvGenCommand *>(lDeviceParams->Get("AcquisitionStop"));
std::cout << "Sending AcquisitionStop command to the device" << std::endl;
lStop->Execute();
// Disable streaming on the device
std::cout << "Disable streaming on the controller." << std::endl;
this->device->StreamDisable();
// Abort all buffers from the stream and dequeue
std::cout << "Aborting buffers still in stream" << std::endl;
this->stream->AbortQueuedBuffers();
while (this->stream->GetQueuedBufferCount() > 0)
{
PvBuffer *lBuffer = NULL;
PvResult lOperationResult;
this->stream->RetrieveBuffer(&lBuffer, &lOperationResult);
}
this->threadPtr.reset();
}
#include <PvSystem.h>
#include <PvInterface.h>
#include <PvDevice.h>
#include <PvStream.h>
#include <PvBuffer.h>
#include <PvStreamGEV.h>
#include <PvDeviceGEV.h>
#include <PvPixelType.h>
#include <PvBufferWriter.h>
#include <PvBufferConverterRGBFilter.h>
#include <opencv2/core/core.hpp>
#include <list>
#include <thread>
#include <memory>
#include <mutex>
#include <condition_variable>
typedef std::list<PvBuffer *> BufferList;
#define BUFFER_COUNT ( 16 )
class GEVCamera
{
public:
GEVCamera(std::string macAddress);
void connect();
void disconnect();
PvStream* openStream(const PvDeviceInfo *aDeviceInfo);
void configureStream(PvDevice* aDevice, PvStream* aStream);
void createStreamBuffers(PvDevice* aDevice, PvStream* aStream, BufferList* aBufferList);
void acquireImages(PvDevice *aDevice, PvStream *aStream);
cv::Mat1b getImage();
bool running;
std::mutex imgReadyMutex;
std::condition_variable imgReadyConditionVariable;
PvString macAddress;
PvSystem system;
PvStream* stream;
PvDevice* device;
BufferList bufferList;
uint32_t imgWidth;
uint32_t imgHeight;
uint8_t* imgBufferPtr;
const PvDeviceInfo* deviceInfo;
std::shared_ptr<std::thread> threadPtr;
};
#include "gev_camera.hpp"
#include <iostream>
#include <iomanip>
#include <thread>
#include <chrono>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
int main()
{
GEVCamera camera("00:11:1c:02:32:54");
camera.connect();
std::cout << "Waiting for 10 seconds" << std::endl;
//std::this_thread::sleep_for(std::chrono::seconds(10));
for(int i = 0; i < 100; i++)
{
cv::Mat1b img = camera.getImage();
cv::imshow("DISPLAY", img);
cv::waitKey(1);
}
camera.disconnect();
std::cout << "Done" << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment