541 lines
16 KiB
C++
541 lines
16 KiB
C++
#include "Hd_CameraModule_Basler_hard.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_hard::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_hard::OnImageGrabbed(Pylon::CInstantCamera& camera, const Pylon::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;
|
||
|
||
// 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());
|
||
}
|
||
//--- End of sample image processing ---
|
||
// Convert the processed image to a bmp so we can display it on the screen.
|
||
// We must lock the bitmap, so we don't modify the pixels while the GUI thread is painting.
|
||
m_bitmapImage.CopyImage(grabResult);
|
||
|
||
//++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_hard::OnCameraDeviceRemoved(Pylon::CInstantCamera& camera)
|
||
{
|
||
moduleStatus = false;
|
||
qDebug() << "[Hd_CameraModule_Basler_hard] " << " Camera disconnected! try auto connect";
|
||
|
||
//运行重连线程
|
||
QFuture<bool> future2 = QtConcurrent::run(this, &Hd_CameraModule_Basler_hard::reConnctDevice);
|
||
}
|
||
|
||
//OnImageGrabbed和OnCameraDeviceRemoved函数,相机创建时自动绑定;相机释放时,自动解除绑定。
|
||
//重连
|
||
bool Hd_CameraModule_Basler_hard::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_hard] " << " Camera create success again! ";
|
||
moduleStatus = true;
|
||
//m_mutex->unlock();
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
//连接设备
|
||
bool Hd_CameraModule_Basler_hard::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_Line1);
|
||
//触发源
|
||
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;
|
||
|
||
}
|
||
|
||
void Hd_CameraModule_Basler_hard::OnCameraEvent(Pylon::CInstantCamera& camera, intptr_t userProvidedId, GenApi::INode* pNode)
|
||
{
|
||
std::cout << "Hd_CameraModule_Basler_hard OnCameraEvent:: " << std::endl;
|
||
}
|
||
|
||
//错误
|
||
void Hd_CameraModule_Basler_hard::OnGrabError(Pylon::CInstantCamera& camera, const char* errorMessage)
|
||
{
|
||
std::cout << "Hd_CameraModule_Basler_hard err:: " << errorMessage << std::endl;
|
||
|
||
moduleStatus = false;
|
||
}
|
||
|
||
|
||
Hd_CameraModule_Basler_hard* create()
|
||
{
|
||
qDebug() << "[info] " << "Hd_CameraModule_Basler_hard create success!";
|
||
return new Hd_CameraModule_Basler_hard;
|
||
}
|
||
|
||
|
||
void destory(Hd_CameraModule_Basler_hard* ptr)
|
||
{
|
||
if (ptr)
|
||
{
|
||
delete ptr;
|
||
ptr = nullptr;
|
||
}
|
||
qDebug() << "[info] " << "Hd_CameraModule_Basler_hard destory success!";
|
||
}
|
||
|
||
Hd_CameraModule_Basler_hard::Hd_CameraModule_Basler_hard()
|
||
{
|
||
PylonInitialize();
|
||
|
||
m_mutex = new QMutex();
|
||
}
|
||
|
||
|
||
//关闭设备
|
||
void Hd_CameraModule_Basler_hard::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_hard::~Hd_CameraModule_Basler_hard()
|
||
{
|
||
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_hard::readData(std::vector<cv::Mat>& mat, QByteArray& data)
|
||
{
|
||
mat.push_back(imread("E:/Download/12.7/ZJ/Image__2023-12-07__10-44-07.bmp", -1));
|
||
return true;
|
||
int cnt = 0;
|
||
while (srcImage.empty())
|
||
{
|
||
cnt++;
|
||
QThread::msleep(1);
|
||
if (cnt > 3000)
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
mat.push_back(srcImage);
|
||
srcImage.release();
|
||
return true;
|
||
}
|
||
|
||
|
||
//实例对象把数据写入到类
|
||
bool Hd_CameraModule_Basler_hard::writeData(std::vector<cv::Mat>& mat, QByteArray& data)
|
||
{
|
||
Q_UNUSED(mat)
|
||
m_flag = false;
|
||
Username = data.toStdString();
|
||
return true;
|
||
}
|
||
|
||
bool Hd_CameraModule_Basler_hard::initParas(QByteArray&)
|
||
{
|
||
return true;
|
||
return ConnctDevice();
|
||
}
|
||
|
||
bool Hd_CameraModule_Basler_hard::run()
|
||
{
|
||
return true;
|
||
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_hard:" ;
|
||
}
|
||
m_mutex->unlock();
|
||
return result;
|
||
}
|
||
|
||
|
||
//相机连接状态:正常连接或断开
|
||
bool Hd_CameraModule_Basler_hard::checkStatus()
|
||
{
|
||
//m_mutex->lock();
|
||
//status = modulestatus;
|
||
return moduleStatus;
|
||
//m_mutex->unlock();
|
||
}
|
||
|