Files
952-11/BaseModules/Hd_CameraModule_Basler_soft/Hd_CameraModule_Basler_soft.cpp
T

542 lines
18 KiB
C++
Raw Normal View History

2024-02-23 13:34:13 +08:00
#include "Hd_CameraModule_Basler_soft.h"
#include "qfuture.h"
#include <QtConcurrent/QtConcurrent>
QQueue<cv::Mat> queuepic;
Pylon::DeviceInfoList_t m_devices;
static int FrameID = 0;
static const size_t c_maxCamerasToUse = 2;
// Smart pointer to camera features
Pylon::CIntegerParameter m_exposureTime; //曝光
Pylon::CIntegerParameter m_gain; //增益
// The grab result retrieved from the camera.
Pylon::CGrabResultPtr m_ptrGrabResult;
bool m_invertImage=true;
// The grab result as a windows DIB to be displayed on the screen.
Pylon::CPylonBitmapImage m_bitmapImage;
bool ifGetImage = false;
bool ifmoduleRun = true;
//判断是否为彩色相机
bool IsColor(EPixelType enType)
{
switch (enType)
{
case PixelType_RGB8packed:
case PixelType_BayerGR8:
case PixelType_BayerRG8:
case PixelType_BayerGB8:
case PixelType_BayerBG8:
case PixelType_BayerGR10:
case PixelType_BayerRG10:
case PixelType_BayerGB10:
case PixelType_BayerBG10:
case PixelType_BayerGR12:
case PixelType_BayerRG12:
case PixelType_BayerGB12:
case PixelType_BayerBG12:
case PixelType_RGB10packed:
case PixelType_BGR10packed:
case PixelType_RGB12packed:
case PixelType_BGR12packed:
case PixelType_YUV422_YUYV_Packed:
case PixelType_BayerGR12Packed:
case PixelType_BayerRG12Packed:
case PixelType_BayerGB12Packed:
case PixelType_BayerBG12Packed:
return true;
default:
return false;
}
}
//搜索设备
int Hd_CameraModule_Basler_soft::SearchDevice()
{
CTlFactory& tlFactory = CTlFactory::GetInstance();
DeviceInfoList_t devices;
//找到所有相机
if (tlFactory.EnumerateDevices(devices) == 0)
{
qDebug() << "No camera present";
}
m_devices = devices;
// Fill the combo box.
int mindex = 0;
for (Pylon::DeviceInfoList_t::const_iterator it = m_devices.begin(); it != m_devices.end(); ++it)
{
// Get the pointer to the current device info.
const Pylon::CDeviceInfo* const pDeviceInfo = &(*it);
// Add the friendly name to the list.
Pylon::String_t friendlyName = pDeviceInfo->GetFriendlyName();
std::string s = friendlyName; //Basler raL4096-24gm (24731776);cam0 (23593460)
//std:cout << s << std::endl;
if (s == Username)
{
index = mindex;
break;
}
mindex++;
}
return (int)devices.size();
}
//回调函数
//当有新图像可用时,从CInstantCamera抓取线程调用此函数。
//在此处执行图像处理。
//之后,我们将把图像转换为RGB位图,并通知GUI关于新图像的信息。
//
//注意:您不能访问任何UI对象,因为此函数不是从GUI线程调用的。
//为了更新GUI,我们将在该功能结束时向主窗口发布一条消息。
//GUI线程将处理消息并更新GUI。
void Hd_CameraModule_Basler_soft::OnImageGrabbed(Pylon::CInstantCamera& camera, const CGrabResultPtr& grabResult)
{
// The following line is commented out as this function will be called very often
// filling up the debug output.
//TRACE(_T("%s\n"), __FUNCTIONW__);
// When overwriting the current CGrabResultPtr, the previous result will automatically be
// released and reused by CInstantCamera.
double time_Start = (double)clock();
//m_ptrGrabResult = grabResult;
//CBaslerUniversalGrabResultPtr ptrGrabResult;CGrabResultPtr
// First check whether the smart pointer is valid.
// Then call GrabSucceeded() on the CGrabResultData to test whether the grab resulut conatains
// an sucessfully grabbed image.
// In case of i.e. transmission errors the result may be invalid
if (grabResult.IsValid() && grabResult->GrabSucceeded())
{
// This is where you would do image processing
// and do other tasks.
// --- Start of sample image processing --- (only works for 8-bit formats)
if (m_invertImage && grabResult->GetPixelType() == PixelType_Mono8)
{
srcImage = cv::Mat(grabResult->GetHeight(), grabResult->GetWidth(), CV_8UC1, grabResult->GetBuffer());
//size_t imageSize = Pylon::ComputeBufferSize(grabResult->GetPixelType(), grabResult->GetWidth(), grabResult->GetHeight(), grabResult->GetPaddingX());
//uint8_t* p = reinterpret_cast<uint8_t*>(grabResult->GetBuffer());
//uint8_t* const pEnd = p + (imageSize / sizeof(uint8_t));
//for (; p < pEnd; ++p)
//{
// *p = 255 - *p; //For demonstration purposes only, invert the image.
//}
}
else if (m_invertImage && grabResult->GetPixelType() == PixelType_BGR8packed)
{
srcImage = cv::Mat(grabResult->GetHeight(), grabResult->GetWidth(), CV_8UC3, grabResult->GetBuffer());
}
else if (IsColor(grabResult->GetPixelType()))
{
// Create a target image.
CPylonImage targetImage;
// Create the converter and set parameters.
CImageFormatConverter converter;
converter.OutputPixelFormat = PixelType_BGR8packed;
// Now we can check if conversion is required.
if (converter.ImageHasDestinationFormat(grabResult))
{
;
}
else
{
converter.Convert(targetImage, grabResult);
}
srcImage = cv::Mat(targetImage.GetHeight(), targetImage.GetWidth(), CV_8UC3, targetImage.GetBuffer());
}
//++m_cntGrabbedImages;
ifGetImage = true;
}
else
{
// If the grab result is invalid, we also mark the bitmap as invalid.
m_bitmapImage.Release();
ifGetImage = false;
// The some TLs provide an error code why the grab failed.
//TRACE(_T("%s Grab failed. Error code. %x\n"), __FUNCTIONW__, (int)grabResult->GetErrorCode());
//CSingleLock lockErrorCount(&m_MemberLock, TRUE);
//++m_cntGrabErrors;
//lockErrorCount.Unlock();
}
// Tell the main window that there is a new image available so it can update the image window.
double time_End = (double)clock();
qDebug() << "[INFO] " " srcImage Exist,Time:" << (time_End - time_Start) / 1.0 << "ms" << "--CameraName:" << QString::fromStdString(Username) << "--FrameID : " << FrameID++;
}
//断线回调
// This will be called when the camera has been removed/disconnected.
// We'll post a message to the GUI about this event and return.
// In response to this message, the GUI will be updated and the camera will be closed.
void Hd_CameraModule_Basler_soft::OnCameraDeviceRemoved(Pylon::CInstantCamera& camera)
{
moduleStatus = false;
qDebug() << "[Hd_CameraModule_Basler_soft] " << " Camera disconnected! try auto connect";
//运行重连线程
QFuture<bool> future2 = QtConcurrent::run(this, &Hd_CameraModule_Basler_soft::reConnctDevice);
}
//OnImageGrabbed和OnCameraDeviceRemoved函数,相机创建时自动绑定;相机释放时,自动解除绑定。
//重连
bool Hd_CameraModule_Basler_soft::reConnctDevice()
{
m_camera->StopGrabbing();
m_camera->DestroyDevice();
m_camera->Close();
delete m_camera;
m_camera = nullptr;
while (1)
{
if (ifmoduleRun == false)
return false;
Sleep(100);
//m_mutex->lock();
if (ConnctDevice() == true)
{
qWarning() << "[Hd_CameraModule_Basler_soft] " << " Camera create success again! ";
moduleStatus = true;
//m_mutex->unlock();
return true;
}
}
}
//连接设备
bool Hd_CameraModule_Basler_soft::ConnctDevice()
{
index = -1;
SearchDevice();
if (index < 0)
return false;
m_camera = new CBaslerUniversalInstantCamera;
//因为用的new方式
{
// Register this object as an image event handler in order to get notified of new images.
// See Pylon::CImageEventHandler for details.
m_camera->RegisterImageEventHandler(this, Pylon::RegistrationMode_ReplaceAll, Pylon::Cleanup_None);
// Register this object as a configuration event handler in order to get notified of camera state changes.
// See Pylon::CConfigurationEventHandler for details.
m_camera->RegisterConfiguration(new Pylon::CAcquireContinuousConfiguration(), Pylon::RegistrationMode_ReplaceAll, Pylon::Cleanup_Delete);
m_camera->RegisterConfiguration(this, Pylon::RegistrationMode_Append, Pylon::Cleanup_None);
}
// Get the pointer to Pylon::CDeviceInfo selected.
const Pylon::CDeviceInfo* pDeviceInfo = &m_devices[index];// (const Pylon::CDeviceInfo*)m_cameraBox.GetItemData(index);
try
{
// Add the AutoPacketSizeConfiguration and let pylon delete it when not needed anymore.
//m_camera->RegisterConfiguration(new CAutoPacketSizeConfiguration(), Pylon::RegistrationMode_Append, Pylon::Cleanup_Delete);
// Create the device and attach it to CInstantCamera.
// Let CInstantCamera take care of destroying the device.
Pylon::IPylonDevice* pDevice = Pylon::CTlFactory::GetInstance().CreateDevice(*pDeviceInfo);
m_camera->Attach(pDevice, Pylon::Cleanup_Delete);
if (m_camera->IsPylonDeviceAttached() == false)
return false;
// Open camera.
m_camera->Open();
//设置心跳;快速进断线回调函数
CIntegerParameter heartbeat(m_camera->GetTLNodeMap(), "HeartbeatTimeout");
heartbeat.TrySetValue(1000, IntegerValueCorrection_Nearest); // set to 1000 ms timeout if writable
////设置曝光,GigE相机为ExposureTimeRaw;USB相机为ExposureTime;方法可行,断电不保存
//if (m_camera->ExposureTime.IsValid())
//{
// m_camera->ExposureTime.GetAlternativeIntegerRepresentation(m_exposureTime);
// int64_t myExposureTimeRaw=m_camera->ExposureTimeRaw.GetValue();
// m_camera->ExposureTimeRaw.SetValue(20);
//}
//else if (m_camera->ExposureTimeRaw.IsValid())
//{
// m_exposureTime.Attach(m_camera->ExposureTimeRaw.GetNode());
// m_camera->ExposureTimeRaw.SetValue(20);
//}
//线扫相机,设置增益有问题
////设置增益,GigE相机为GainRaw;USB相机为Gain
//if (m_camera->Gain.IsValid())
//{
// m_camera->Gain.GetAlternativeIntegerRepresentation(m_gain);
// m_camera->Gain.SetValue(2);
//}
//else if (m_camera->GainRaw.IsValid())
//{
// m_gain.Attach(m_camera->GainRaw.GetNode());
// m_camera->GainRaw.SetValue(2);
//}
//这几行会把相机设置重置
//像素格式
//m_camera->RegisterCameraEventHandler(this, "PixelFormat", 0, Pylon::RegistrationMode_Append, Pylon::Cleanup_None, Pylon::CameraEventAvailability_Optional);
//触发模式
//m_camera->RegisterCameraEventHandler(this, "TriggerMode", 0, Pylon::RegistrationMode_Append, Pylon::Cleanup_None, Pylon::CameraEventAvailability_Optional);
//触发源
//m_camera->RegisterCameraEventHandler(this, "TriggerSource", 0, Pylon::RegistrationMode_Append, Pylon::Cleanup_None, Pylon::CameraEventAvailability_Optional);
//触发模式
m_camera->TriggerSource.SetValue( Basler_UniversalCameraParams::TriggerSource_Software);
//触发源
m_camera->TriggerMode.SetValue(Basler_UniversalCameraParams::TriggerMode_On);
//m_camera->PixelFormat.SetValue();//
//连续采集
// Camera may have been disconnected.
if (!m_camera->IsOpen() || m_camera->IsGrabbing())
{
return false;
}
// Try set continuous frame mode if available
m_camera->AcquisitionMode.TrySetValue(Basler_UniversalCameraParams::AcquisitionMode_Continuous);
// Start grabbing until StopGrabbing() is called.
m_camera->StartGrabbing(Pylon::GrabStrategy_OneByOne, Pylon::GrabLoop_ProvidedByInstantCamera);
qDebug() << "[StartGrabbing] " << " basler camera StartGrabbing!";
}
catch (const Pylon::GenericException& e)
{
qDebug() << "[error] " << " basler camera disconnects!";
return false;
}
return true;
////创建相机对象(以最先识别的相机)
////camera = CTlFactory::GetInstance().CreateFirstDevice();
//CInstantCameraArray cameras(min(devices.size(), c_maxCamerasToUse));
//// 打印相机的名称
////std::cout << "Using device " << camera.GetDeviceInfo().GetModelName() << endl;
//
////获取相机节点映射以获得相机参数
//GenApi::INodeMap& nodemap = camera.GetNodeMap();
////打开相机
//camera.Open();
////加载用户集,相机设置应当userset1
//camera.UserSetSelector.SetValue(UserSetSelector_UserSet1);
//camera.RegisterImageEventHandler(new CSampleImageEventHandler, RegistrationMode_Append, Cleanup_Delete);
//camera.RegisterExceptionCallBack();
// 设置相机参数
/*GenApi::cenumerationptr ptracquisitionmode = camera.getparameter("acquisitionmode");
ptracquisitionmode->fromstring("continuous");
genapi::cenumerationptr ptrtriggerselector = camera.getparameter("triggerselector");
ptrtriggerselector->fromstring("framestart");
genapi::cenumerationptr ptrtriggermode = camera.getparameter("triggermode");
ptrtriggermode->fromstring("on");
genapi::cenumerationptr ptrtriggersource = camera.getparameter("triggersource");
ptrtriggersource->fromstring("software");
CIntegerParameter heartbeat( camera.GetTLNodeMap(), "HeartbeatTimeout" );
heartbeat.TrySetValue( 1000, IntegerValueCorrection_Nearest );
*/
}
//错误
void Hd_CameraModule_Basler_soft::OnGrabError(Pylon::CInstantCamera& camera, const char* errorMessage)
{
std::cout << "Hd_CameraModule_Basler_soft err:: " << errorMessage << std::endl;
moduleStatus = false;
}
Hd_CameraModule_Basler_soft* create()
{
qDebug() << "[info] " << "Hd_CameraModule_Basler_soft create success!";
return new Hd_CameraModule_Basler_soft;
}
void destory(Hd_CameraModule_Basler_soft* ptr)
{
if (ptr)
{
delete ptr;
ptr = nullptr;
}
qDebug() << "[info] " << "Hd_CameraModule_Basler_soft destory success!";
}
Hd_CameraModule_Basler_soft::Hd_CameraModule_Basler_soft()
{
PylonInitialize();
m_mutex = new QMutex();
}
//关闭设备
void Hd_CameraModule_Basler_soft::CloseDevice()
{
m_camera->StopGrabbing();
//m_bitmapImage.Release();
//// Free the grab result, if present.
//m_ptrGrabResult.Release();
//// Remove the event handlers that will be called when the feature changes.
//m_camera->DeregisterCameraEventHandler(this, "TriggerSource");
//m_camera->DeregisterCameraEventHandler(this, "TriggerMode");
//m_camera->DeregisterCameraEventHandler(this, "PixelFormat");
//if (m_gain.IsValid())
//{
// // If we must use the alternative integer representation, we don't know the name of the node as it defined by the camera
// m_camera->DeregisterCameraEventHandler(this, m_gain.GetNode()->GetName());
//}
//if (m_exposureTime.IsValid())
//{
// // If we must use the alternative integer representation, we don't know the name of the node as it defined by the camera
// m_camera->DeregisterCameraEventHandler(this, m_exposureTime.GetNode()->GetName());
//}
//// Clear the pointers to the features we set manually in Open().
//m_exposureTime.Release();
//m_gain.Release();
// Close the camera and free all ressources.
// This will also unregister all
m_camera->DestroyDevice();
m_camera->Close();
delete m_camera;
m_camera = nullptr;
//m_camera->ClearBufferModeEnable();
/*camera.StopGrabbing();
camera.DestroyDevice();
camera.Close();*/
}
Hd_CameraModule_Basler_soft::~Hd_CameraModule_Basler_soft()
{
ifmoduleRun = false;
m_mutex->lock();
CloseDevice();
m_mutex->unlock();
//PylonTerminate();
if (m_mutex)
{
delete m_mutex;
m_mutex = nullptr;
}
qDebug() << "[info] " << " delete success!";
}
//从类中读数据到实例对象
bool Hd_CameraModule_Basler_soft::readData(std::vector<cv::Mat>& mat, QByteArray& data)
{
int timeCnt = 0;
while (srcImage.empty())
{
//qCritical() << "[INFO] " << " srcImage is null!";
QThread::msleep(1);
timeCnt++;
if(timeCnt>1000)
return false;
}
mat.push_back(srcImage);
return true;
}
//实例对象把数据写入到类
bool Hd_CameraModule_Basler_soft::writeData(std::vector<cv::Mat>& mat, QByteArray& data)
{
Q_UNUSED(mat)
m_flag = false;
Username = data.toStdString();
return true;
}
bool Hd_CameraModule_Basler_soft::initParas(QByteArray&)
{
return true;
return ConnctDevice();
}
bool Hd_CameraModule_Basler_soft::run()
{
bool result = false;
ifGetImage = false;
try
{
m_mutex->lock();
if (!m_camera->IsGrabbing())
{
m_mutex->unlock();
return result;
}
//软触发一次
// Only wait if software trigger is currently turned on.
if (m_camera->TriggerSource.GetValue() == Basler_UniversalCameraParams::TriggerSource_Software
&& m_camera->TriggerMode.GetValue() == Basler_UniversalCameraParams::TriggerMode_On)
{
// If the camera is currently processing a previous trigger command,
// it will silently discard trigger commands.
// We wait until the camera is ready to process the next trigger.
if (moduleStatus == false)
{
m_mutex->unlock();
return result;
}
if (m_camera->WaitForFrameTriggerReady(3000, Pylon::TimeoutHandling_ThrowException) == true)
{
// Send trigger
m_camera->ExecuteSoftwareTrigger();
}
else {
m_mutex->unlock();
return result;
}
}
else {
m_mutex->unlock();
return result;
}
int timeOut = 0;
while (1)
{
if (ifGetImage == true)
{
result = true;
break;
}
if (timeOut++ > 3000 || moduleStatus ==false)
{
result = false;
break;
}
//else
//{
// result = true;
// break;
//}
Sleep(1);
}
}
catch (...)
{
qDebug() << "[error] " << " Hd_CameraModule_Basler_soft:" ;
}
m_mutex->unlock();
return result;
}
//相机连接状态:正常连接或断开
bool Hd_CameraModule_Basler_soft::checkStatus()
{
//m_mutex->lock();
//status = modulestatus;
return moduleStatus;
//m_mutex->unlock();
}