You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
360 lines
12 KiB
C++
360 lines
12 KiB
C++
//-----------------------------------------------------------------------------
|
|
#ifndef CaptureThreadBaslerH
|
|
#define CaptureThreadBaslerH CaptureThreadBaslerH
|
|
//-----------------------------------------------------------------------------
|
|
#include "baslercamera.h"
|
|
#include <QThread>
|
|
#include <QMutex>
|
|
#include <QTimer>
|
|
|
|
#include "SyncQueue.h"
|
|
#include "ASyncQueue.h"
|
|
#include "common.h"
|
|
#include <opencv2/opencv.hpp>
|
|
|
|
extern bool g_debug_mode;
|
|
extern SingleCamInfoStruct SingleCamInfo[NumberOfSupportedCameras];
|
|
enum MyEvents
|
|
{
|
|
eMyFrameBurstStartEvent = 100,
|
|
Line1RisingEdge = 200,
|
|
Line1FallingEdge = 300
|
|
// More events can be added here.
|
|
};
|
|
|
|
class CaptureThreadBasler_Func
|
|
{
|
|
public:
|
|
Pylon::CBaslerUniversalInstantCamera* pDev__;
|
|
ASyncQueue<bool> *p_result_queue_;
|
|
ASyncQueue<bool> *p_double_queue_;
|
|
QTimer *m_IOTimer_ = NULL;
|
|
void SendFeedBack(int OpID)
|
|
{
|
|
bool send_ng=false;
|
|
bool send_ok=false;
|
|
if(OpID == EdgeEvent)
|
|
{
|
|
#if defined DOUBLE_FEED_BACK
|
|
if(p_double_queue_->count() > 0)
|
|
{
|
|
bool temp;
|
|
p_double_queue_->take(temp);
|
|
send_ng=true;
|
|
}
|
|
#endif
|
|
}
|
|
if (p_result_queue_->count() > 0)
|
|
{
|
|
bool result;
|
|
p_result_queue_->take(result);
|
|
if (!result) {
|
|
#if defined DOUBLE_FEED_BACK
|
|
p_double_queue_->put(true);
|
|
#endif
|
|
send_ng=true;
|
|
}
|
|
else
|
|
{
|
|
send_ok=true;
|
|
}
|
|
}
|
|
#ifndef USB_BASLER_NEW_FW
|
|
if (send_ng) {
|
|
pDev__->UserOutputSelector.SetValue(Basler_UniversalCameraParams::UserOutputSelector_UserOutput3);
|
|
pDev__->UserOutputValue.SetValue(true);
|
|
}
|
|
else if (send_ok) {
|
|
pDev__->UserOutputSelector.SetValue(Basler_UniversalCameraParams::UserOutputSelector_UserOutput1);
|
|
pDev__->UserOutputValue.SetValue(true);
|
|
}
|
|
m_IOTimer_->start(StrobeLineTime / 2000);
|
|
#else
|
|
if (send_ng) {
|
|
pDev__->UserOutputSelector.SetValue(Basler_UniversalCameraParams::UserOutputSelector_UserOutput3);
|
|
pDev__->UserOutputValue.SetValue(false);
|
|
pDev__->UserOutputValue.SetValue(true);
|
|
}
|
|
else if (send_ok) {
|
|
pDev__->UserOutputSelector.SetValue(Basler_UniversalCameraParams::UserOutputSelector_UserOutput1);
|
|
pDev__->UserOutputValue.SetValue(false);
|
|
pDev__->UserOutputValue.SetValue(true);
|
|
}
|
|
#endif
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
class CaptureThreadBasler : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit CaptureThreadBasler(Pylon::CBaslerUniversalInstantCamera* pCurrDev, bool boTerminated,int Num,int shoot);
|
|
CaptureThreadBasler::~CaptureThreadBasler(void);
|
|
void terminate( void )
|
|
{
|
|
boTerminated_ = true;
|
|
}
|
|
|
|
signals:
|
|
void error( QString err );
|
|
void finished( void );
|
|
void requestReady( void );
|
|
void updateStatistics( const QString& data ,int Num);
|
|
|
|
private slots:
|
|
void process( void );
|
|
void fpsTimeout(void);
|
|
void ioTimeout(void);
|
|
|
|
public:
|
|
int Local_Num;
|
|
int Shoot_Num;
|
|
SyncQueue<std::pair<int, cv::Mat> > *p_image_queue;
|
|
ASyncQueue<cv::Mat> *p_unit_queue;
|
|
ASyncQueue<bool> *p_result_queue;
|
|
ASyncQueue<bool> *p_result_wait_queue;
|
|
ASyncQueue<bool> *p_double_queue;
|
|
ASyncQueue<bool> *p_shooted_queue;
|
|
SyncQueue<cv::Mat> *p_debug_queue;
|
|
QTimer *m_Timer = NULL,*m_IOTimer = NULL;
|
|
uint64_t m_cntGrabbedImages = 0;
|
|
uint64_t m_cntLastGrabbedImages = 0;
|
|
bool Ready = false;
|
|
CaptureThreadBasler_Func m_threadFunc;
|
|
private:
|
|
Pylon::CBaslerUniversalInstantCamera* pDev_;
|
|
volatile bool boTerminated_;
|
|
QMutex lock_;
|
|
};
|
|
//-----------------------------------------------------------------------------
|
|
class CSampleConfigurationEventHandler : public Pylon::CBaslerUniversalConfigurationEventHandler //CConfigurationEventHandler
|
|
{
|
|
public:
|
|
int channel_;
|
|
// This method is called from a different thread when the camera device removal has been detected.
|
|
void OnCameraDeviceRemoved( Pylon::CBaslerUniversalInstantCamera& camera )
|
|
{
|
|
SingleCamInfo[channel_].OffLine = true;
|
|
}
|
|
};
|
|
|
|
// Example handler for camera events.
|
|
class CSampleCameraEventHandler : public Pylon::CBaslerUniversalCameraEventHandler
|
|
{
|
|
public:
|
|
QTimer * ioTimer;
|
|
ASyncQueue<cv::Mat>* p_unit_queue_;
|
|
ASyncQueue<bool> *p_result_wait_queue_;
|
|
ASyncQueue<bool> *p_result_queue_;
|
|
ASyncQueue<bool> *p_double_queue_;
|
|
ASyncQueue<bool> *p_shooted_queue_;
|
|
SyncQueue<std::pair<int, cv::Mat> >* p_image_queue_;
|
|
Pylon::CBaslerUniversalInstantCamera* pDev__;
|
|
CaptureThreadBasler* pCaptureThreadBasler = NULL;
|
|
// Only very short processing tasks should be performed by this method. Otherwise, the event notification will block the
|
|
// processing of images.
|
|
virtual void OnCameraEvent(Pylon::CBaslerUniversalInstantCamera& camera, intptr_t userProvidedId, GenApi::INode* pNode)
|
|
{
|
|
switch (userProvidedId)
|
|
{
|
|
#ifndef USB_BASLER_NEW_FW
|
|
case eMyFrameBurstStartEvent:
|
|
{
|
|
#ifdef IMM_FEED_BACK
|
|
if (p_shooted_queue_->count() > 0)
|
|
{
|
|
bool temp;
|
|
p_shooted_queue_->take(temp);
|
|
}
|
|
#elif defined ONE_TIME_SHIFT
|
|
if (
|
|
p_shooted_queue_->count() > 0
|
|
#if defined DOUBLE_FEED_BACK
|
|
|| p_double_queue_->count() >0
|
|
#endif
|
|
)
|
|
{
|
|
if (p_shooted_queue_->count() > 0){
|
|
bool temp;
|
|
p_shooted_queue_->take(temp);
|
|
}
|
|
pCaptureThreadBasler->m_threadFunc.SendFeedBack(EdgeEvent);
|
|
}
|
|
#else
|
|
if(p_unit_queue_->count() > 0){
|
|
int unit_count = p_unit_queue_->count();
|
|
cv::Mat long_image;
|
|
for (int i = 0; i < unit_count; i++)
|
|
{
|
|
cv::Mat image;
|
|
p_unit_queue_->take(image);
|
|
if (0 == i)
|
|
{
|
|
long_image = cv::Mat::zeros(image.rows * unit_count, image.cols, image.type());
|
|
}
|
|
cv::Rect r(0, i * image.rows, image.cols, image.rows);
|
|
cv::Mat roi = long_image(r);
|
|
image.copyTo(roi);
|
|
}
|
|
p_image_queue_->put(std::make_pair(unit_count, long_image));
|
|
p_shooted_queue_->put(true);
|
|
p_unit_queue_->clear();
|
|
}
|
|
if(p_result_wait_queue_->count() > 0)
|
|
{
|
|
bool temp;
|
|
p_result_wait_queue_->take(temp);
|
|
pCaptureThreadBasler->m_threadFunc.SendFeedBack(EdgeEvent);
|
|
}
|
|
if(p_shooted_queue_->count() > 0)
|
|
{
|
|
bool temp;
|
|
p_shooted_queue_->take(temp);
|
|
p_result_wait_queue_->put(true);
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
#else
|
|
case Line1RisingEdge:
|
|
{
|
|
#ifdef IMM_FEED_BACK
|
|
if (p_shooted_queue_->count() > 0)
|
|
{
|
|
bool temp;
|
|
p_shooted_queue_->take(temp);
|
|
}
|
|
#elif defined ONE_TIME_SHIFT
|
|
if (
|
|
p_shooted_queue_->count() > 0
|
|
#if defined DOUBLE_FEED_BACK
|
|
|| p_double_queue_->count() >0
|
|
#endif
|
|
)
|
|
{
|
|
bool temp;
|
|
p_shooted_queue_->take(temp);
|
|
pCaptureThreadBasler->m_threadFunc.SendFeedBack(EdgeEvent);
|
|
}
|
|
#else
|
|
if(p_result_wait_queue_->count() > 0)
|
|
{
|
|
bool temp;
|
|
p_result_wait_queue_->take(temp);
|
|
pCaptureThreadBasler->m_threadFunc.SendFeedBack(EdgeEvent);
|
|
}
|
|
if(p_shooted_queue_->count() > 0)
|
|
{
|
|
bool temp;
|
|
p_shooted_queue_->take(temp);
|
|
p_result_wait_queue_->put(true);
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
case Line1FallingEdge:
|
|
{
|
|
int unit_count = p_unit_queue_->count();
|
|
if (unit_count > 0)
|
|
{
|
|
cv::Mat long_image;
|
|
for (int i = 0; i < unit_count; i++)
|
|
{
|
|
cv::Mat image;
|
|
p_unit_queue_->take(image);
|
|
if (0 == i)
|
|
{
|
|
long_image = cv::Mat::zeros(image.rows * unit_count, image.cols, image.type());
|
|
}
|
|
cv::Rect r(0, i * image.rows, image.cols, image.rows);
|
|
cv::Mat roi = long_image(r);
|
|
image.copyTo(roi);
|
|
}
|
|
p_image_queue_->put(std::make_pair(unit_count, long_image));
|
|
p_shooted_queue_->put(true);
|
|
}
|
|
p_unit_queue_->clear();
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
class CSampleImageEventHandler : public Pylon::CBaslerUniversalImageEventHandler
|
|
{
|
|
public:
|
|
ASyncQueue<cv::Mat>* p_unit_queue_;
|
|
SyncQueue<std::pair<int, cv::Mat> >* p_image_queue_;
|
|
SyncQueue<cv::Mat>* p_debug_queue_;
|
|
ASyncQueue<bool> *p_shooted_queue_;
|
|
Pylon::CBaslerUniversalInstantCamera* pDev__;
|
|
uint64_t* m_cntGrabbedImages_;
|
|
int Shoot_Num_;
|
|
virtual void OnImageGrabbed(Pylon::CBaslerUniversalInstantCamera& camera, const Pylon::CBaslerUniversalGrabResultPtr& ptrGrabResult)
|
|
{
|
|
// Create a pylon ImageFormatConverter object.
|
|
Pylon::CImageFormatConverter formatConverter;
|
|
|
|
// Specify the output pixel format.
|
|
formatConverter.OutputPixelFormat = Pylon::PixelType_Mono8;
|
|
|
|
cv::Mat openCvImage;
|
|
|
|
// Create a PylonImage that will be used to create OpenCV images later.
|
|
Pylon::CPylonImage pylonImage;
|
|
|
|
// Convert the grabbed buffer to a pylon image.
|
|
formatConverter.Convert(pylonImage, ptrGrabResult);
|
|
|
|
// Create an OpenCV image from a pylon image.
|
|
openCvImage = cv::Mat(ptrGrabResult->GetHeight(), ptrGrabResult->GetWidth(), CV_8UC1, (uint8_t*)pylonImage.GetBuffer());
|
|
cv::Mat image_clone = openCvImage.clone();
|
|
|
|
if (!g_debug_mode)
|
|
{
|
|
#ifdef IMM_PROCESS
|
|
p_image_queue_->put(std::make_pair(1,image_clone));
|
|
#else
|
|
p_unit_queue_->put(image_clone);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
p_debug_queue_->put(image_clone);
|
|
}
|
|
(*m_cntGrabbedImages_)++;
|
|
#ifndef IMM_PROCESS
|
|
#ifndef USB_BASLER_NEW_FW
|
|
int unit_count = p_unit_queue_->count();
|
|
if (unit_count == Shoot_Num_)
|
|
{
|
|
cv::Mat long_image;
|
|
for (int i = 0; i < unit_count; i++)
|
|
{
|
|
cv::Mat image;
|
|
p_unit_queue_->take(image);
|
|
if (0 == i)
|
|
{
|
|
long_image = cv::Mat::zeros(image.rows * unit_count, image.cols, image.type());
|
|
}
|
|
cv::Rect r(0, i * image.rows, image.cols, image.rows);
|
|
cv::Mat roi = long_image(r);
|
|
image.copyTo(roi);
|
|
}
|
|
p_image_queue_->put(std::make_pair(unit_count, long_image));
|
|
p_shooted_queue_->put(true);
|
|
DEBUG(" unit_count\n");
|
|
p_unit_queue_->clear();
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
};
|
|
|
|
#endif // CaptureThreadBasler
|