Files
2024-02-23 13:34:13 +08:00

539 lines
16 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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->configuration
//m_camera->UserSetLoad("User Set 1");
//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)
{
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 ConnctDevice();
}
bool Hd_CameraModule_Basler_hard::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_hard:" ;
}
m_mutex->unlock();
return result;
}
//相机连接状态:正常连接或断开
bool Hd_CameraModule_Basler_hard::checkStatus()
{
//m_mutex->lock();
//status = modulestatus;
return moduleStatus;
//m_mutex->unlock();
}