393 lines
12 KiB
C++
393 lines
12 KiB
C++
#include "hd_mvcamera_module.h"
|
|
#include <QByteArray>
|
|
#include <QDebug>
|
|
#include <qqueue.h>
|
|
std::vector<cv::Mat> matVec;
|
|
std::mutex queueMutex;//掉线锁
|
|
|
|
std::mutex moduleMutex;//掉线锁
|
|
int reconnectCount = 0;
|
|
int SearchDevice();
|
|
void __stdcall ImageCallBackEx(unsigned char* pData0, MV_FRAME_OUT_INFO_EX* pFrameInfo0, void* pUser0);
|
|
//0106 断连提示
|
|
void _stdcall ExceptionCB(unsigned int nMesgType, void* pUser) {
|
|
mv_Status = "disconnect";
|
|
qDebug() << "[Error] " << " MV camera disconnects!trying to reconnect";
|
|
//moduleMutex.lock();
|
|
reconnectCount++;
|
|
//消除句柄关闭相机
|
|
MV_CC_StopGrabbing(handle);
|
|
MV_CC_CloseDevice(handle);
|
|
MV_CC_DestroyHandle(handle);
|
|
//尝试重连
|
|
while (1)
|
|
{
|
|
SearchDevice();
|
|
unsigned char* serialNumber = m_stDevList.pDeviceInfo[index]->chUserDefinedName;
|
|
string userName = static_cast<string>((LPCSTR)serialNumber);
|
|
qDebug() << "[INFO] " << " start" << "--UserName:" << QString::fromStdString(userName);
|
|
if (handle != NULL)
|
|
{
|
|
//MV_CC_CreateHandle(&handle, m_stDevList.pDeviceInfo[index]);
|
|
//int nRet = MV_CC_OpenDevice(handle);
|
|
//////触发模式
|
|
//MV_CC_SetEnumValue(handle, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE);
|
|
//MV_CC_SetEnumValue(handle, "TriggerMode", MV_TRIGGER_MODE_ON);
|
|
//// //加载用户集
|
|
//nRet = MV_CC_SetEnumValueByString(handle, "UserSetSelector", "UserSet1");
|
|
//if (MV_OK != nRet)
|
|
//{
|
|
// qDebug() << "Set UserSetSelector fail! nRet " << nRet;
|
|
//}
|
|
//// ch:注册抓图回调 | en:Register image callback
|
|
//MV_CC_SetIntValueEx(handle, "GevHeartbeatTimeout", 3000);//心跳日志
|
|
//nRet = MV_CC_RegisterImageCallBackEx(handle, ImageCallBackEx, handle);//注册回调
|
|
//nRet = MV_CC_RegisterExceptionCallBack(handle, ExceptionCB, NULL);//注册报警回调
|
|
//MV_CC_StartGrabbing(handle);
|
|
////moduleMutex.unlock();
|
|
//break;
|
|
}
|
|
_sleep(100);
|
|
}
|
|
}
|
|
int RGB2BGR(unsigned char* pRgbData, unsigned int nWidth, unsigned int nHeight)
|
|
{
|
|
|
|
if (NULL == pRgbData)
|
|
{
|
|
return MV_E_PARAMETER;
|
|
}
|
|
|
|
for (unsigned int j = 0; j < nHeight; j++)
|
|
{
|
|
for (unsigned int i = 0; i < nWidth; i++)
|
|
{
|
|
unsigned char red = pRgbData[j * (nWidth * 3) + i * 3];
|
|
pRgbData[j * (nWidth * 3) + i * 3] = pRgbData[j * (nWidth * 3) + i * 3 + 2];
|
|
pRgbData[j * (nWidth * 3) + i * 3 + 2] = red;
|
|
}
|
|
}
|
|
|
|
return MV_OK;
|
|
|
|
}
|
|
Hd_MvCamera_module* create()
|
|
{
|
|
qDebug() << "[INFO] " << "Hd_MvCamera_module create success!";
|
|
return new Hd_MvCamera_module;
|
|
}
|
|
|
|
void destory(Hd_MvCamera_module* ptr)
|
|
{
|
|
if (ptr)
|
|
{
|
|
delete ptr;
|
|
ptr = nullptr;
|
|
}
|
|
qDebug() << "[INFO] " << "Hd_MvCamera_module destory success!";
|
|
}
|
|
/// <summary>
|
|
/// 回调取图
|
|
/// </summary>
|
|
void __stdcall ImageCallBackEx(unsigned char* pData0, MV_FRAME_OUT_INFO_EX* pFrameInfo0, void* pUser0)
|
|
{
|
|
double time_Start = (double)clock();
|
|
if (pFrameInfo0)
|
|
{
|
|
//获取的是单通道灰度图
|
|
if (pFrameInfo0->enPixelType == PixelType_Gvsp_Mono8)//获取当前采集到的图像格式
|
|
{
|
|
srcImage = cv::Mat(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC1, pData0);
|
|
}
|
|
//获取的是RGB8图
|
|
else if (pFrameInfo0->enPixelType == PixelType_Gvsp_RGB8_Packed)
|
|
{
|
|
RGB2BGR(pData0, pFrameInfo0->nWidth, pFrameInfo0->nHeight);
|
|
srcImage = cv::Mat(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC3, pData0);
|
|
|
|
//cvtColor(srcImage, srcImage, COLOR_RGB2BGR);//导致异色
|
|
}
|
|
else if (pFrameInfo0->enPixelType == PixelType_Gvsp_HB_YUV422_YUYV_Packed) {
|
|
srcImage = cv::Mat(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC2, pData0);
|
|
cv::cvtColor(srcImage, srcImage, cv::COLOR_YUV2BGR_UYVY);
|
|
|
|
}
|
|
//获取的是yuv或bayer图
|
|
else if (pFrameInfo0->enPixelType == PixelType_Gvsp_YUV422_Packed || pFrameInfo0->enPixelType == PixelType_Gvsp_BayerRG8)
|
|
{
|
|
MvGvspPixelType enDstPixelType = PixelType_Gvsp_Undefined;
|
|
enDstPixelType = PixelType_Gvsp_BGR8_Packed;
|
|
unsigned int nConvertDataSize = pFrameInfo0->nWidth * pFrameInfo0->nHeight * 3;
|
|
unsigned char* pConvertData = (unsigned char*)malloc(nConvertDataSize);
|
|
if (NULL == pConvertData)
|
|
{
|
|
printf("malloc pConvertData1 fail!\n");
|
|
m_flag = true;
|
|
srcImage = cv::Mat(5, 5, CV_8UC1).setTo(0);
|
|
return;
|
|
}
|
|
MV_CC_PIXEL_CONVERT_PARAM stConvertParam = { 0 };
|
|
stConvertParam.nWidth = pFrameInfo0->nWidth;
|
|
stConvertParam.nHeight = pFrameInfo0->nHeight;
|
|
stConvertParam.pSrcData = pData0;
|
|
stConvertParam.nSrcDataLen = pFrameInfo0->nFrameLen;
|
|
stConvertParam.enSrcPixelType = pFrameInfo0->enPixelType;
|
|
stConvertParam.enDstPixelType = enDstPixelType;
|
|
stConvertParam.pDstBuffer = pConvertData;
|
|
stConvertParam.nDstBufferSize = nConvertDataSize;
|
|
|
|
int nRet = MV_CC_ConvertPixelType(handle, &stConvertParam);
|
|
if (MV_OK == nRet)
|
|
{
|
|
srcImage = cv::Mat::zeros(cv::Size(pFrameInfo0->nWidth, pFrameInfo0->nHeight), CV_8UC3);
|
|
memcpy(srcImage.data, stConvertParam.pDstBuffer, nConvertDataSize);
|
|
//Mat mysrcImage = cv::Mat(mypFrameInfo->nHeight, mypFrameInfo->nWidth, CV_8UC3, stConvertParam.pDstBuffer);
|
|
//mysrcImage.copyTo(srcImage);
|
|
//mysrcImage.release();
|
|
stConvertParam = { 0 };
|
|
}
|
|
else
|
|
{
|
|
srcImage = cv::Mat(0, 0, CV_8UC3).setTo(0);
|
|
}
|
|
if (pConvertData)
|
|
{
|
|
free(pConvertData);
|
|
pConvertData = NULL;
|
|
}
|
|
}
|
|
}
|
|
if (!srcImage.empty())
|
|
{
|
|
m_flag = true;
|
|
double time_End = (double)clock();
|
|
//imwrite("C://" + to_string(clock()) + "X.bmp", srcImage);
|
|
//统计图片成像时间
|
|
qDebug() << "[INFO] " << " srcImage Exist,Time:" << (time_End - time_Start) / 1000.0 << "s" << "--CameraName:" << QString::fromStdString(Username);
|
|
}
|
|
queueMutex.lock();
|
|
matVec.push_back(srcImage);
|
|
srcImage.release();
|
|
queueMutex.unlock();
|
|
pData0 = { 0 };
|
|
}
|
|
|
|
//搜索所有设备
|
|
int SearchDevice()
|
|
{
|
|
int nRet = MV_OK;
|
|
MV_GENTL_IF_INFO_LIST pstIFList;
|
|
if (m_stDevList.nDeviceNum == 0)
|
|
{
|
|
memset(&m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
|
|
|
|
// ch:枚举子网内所有设备 | en:Enumerate all devices within subnet
|
|
//nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE || MV_USB_DEVICE, &m_stDevList);
|
|
nRet = MV_CC_EnumInterfacesByGenTL(&pstIFList, ".//config//MvFGProducerCML.cti");
|
|
nRet = MV_CC_EnumDevicesByGenTL(pstIFList.pIFInfo[pstIFList.nInterfaceNum - 1], &m_stDevList);
|
|
}
|
|
for (int i = 0; i < m_stDevList.nDeviceNum; i++)
|
|
{
|
|
//unsigned char* name = m_stDevList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.chUserDefinedName;
|
|
unsigned char* name = m_stDevList.pDeviceInfo[i]->chUserDefinedName;
|
|
string serialNumber = static_cast<string>((LPCSTR)name);
|
|
if (Username == serialNumber)
|
|
{
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
if (MV_OK != nRet)
|
|
{
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
#include <QByteArray>
|
|
#include <QtGlobal>
|
|
|
|
// 将 QByteArray 转换为 MV_CC_DEVICE_INFO_LIST
|
|
MV_CC_DEVICE_INFO_LIST QByteArrayToMV_CC_DeviceInfoList(const QByteArray& byteArray) {
|
|
MV_CC_DEVICE_INFO_LIST deviceInfoList;
|
|
if (byteArray.size() == sizeof(MV_CC_DEVICE_INFO_LIST)) {
|
|
memcpy(&deviceInfoList, byteArray.constData(), sizeof(MV_CC_DEVICE_INFO_LIST));
|
|
}
|
|
else {
|
|
qDebug() << "Invalid size of QByteArray for MV_CC_DEVICE_INFO_LIST!";
|
|
}
|
|
return deviceInfoList;
|
|
}
|
|
Hd_MvCamera_module::Hd_MvCamera_module()
|
|
{
|
|
m_thread = new MyThread;
|
|
}
|
|
|
|
void CloseDevice()
|
|
{
|
|
MV_CC_StopGrabbing(handle);
|
|
MV_CC_CloseDevice(handle);
|
|
MV_CC_DestroyHandle(handle);
|
|
}
|
|
Hd_MvCamera_module::~Hd_MvCamera_module()
|
|
{
|
|
CloseDevice();
|
|
if (m_thread)
|
|
{
|
|
m_thread->exit();
|
|
m_thread->wait(1);
|
|
delete m_thread;
|
|
m_thread = nullptr;
|
|
}
|
|
|
|
qDebug() << "[INFO] " << " delete success!";
|
|
}
|
|
|
|
bool Hd_MvCamera_module::sendData(std::vector<cv::Mat>& mat, QByteArray& data)
|
|
{
|
|
|
|
QString inputString = QString::fromUtf8(data);
|
|
if (data == "connect")
|
|
{
|
|
data = mv_Status;
|
|
return true;
|
|
}
|
|
int underscorePos = inputString.indexOf('_');
|
|
if (underscorePos != -1) {
|
|
QString command = inputString.left(underscorePos);
|
|
QString value = inputString.mid(underscorePos + 1);
|
|
if (command == "userset")
|
|
return false;
|
|
else if (command == "exposure")
|
|
{
|
|
int nRet = MV_CC_SetFloatValue(handle, "ExposureTime", value.toFloat());
|
|
if (nRet != MV_OK)
|
|
{
|
|
cout << "exposure set fail!" << inputString.toStdString() << endl;
|
|
|
|
}
|
|
}
|
|
else if (command == "DigitalShift")
|
|
{
|
|
int nRet = MV_CC_SetFloatValue(handle, "DigitalShift", value.toFloat());
|
|
if (nRet != MV_OK)
|
|
{
|
|
cout << "DigitalShift" << inputString.toStdString() << endl;
|
|
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int cnt = 0;
|
|
while (matVec.size() <= 1)
|
|
{
|
|
cnt++;
|
|
QThread::msleep(1);
|
|
if (cnt > 10000)
|
|
return false;
|
|
}
|
|
queueMutex.lock();
|
|
for(auto matImg: matVec)
|
|
mat.push_back(matImg);
|
|
//mat.push_back(matQueue.dequeue());
|
|
|
|
matVec.clear();
|
|
queueMutex.unlock();
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Hd_MvCamera_module::reciveData(std::vector<cv::Mat>& mat, QByteArray& data)
|
|
{
|
|
m_flag = false;
|
|
Username = data.toStdString();
|
|
return true;
|
|
}
|
|
|
|
bool Hd_MvCamera_module::initParas(QByteArray&)
|
|
{
|
|
return true;
|
|
if (!Username.compare("dummy"))
|
|
{
|
|
qDebug() << "[INFO] " << " start" << "--UserName: dummy creat sucess";
|
|
return true;
|
|
}
|
|
SearchDevice();
|
|
unsigned char* defineName = m_stDevList.pDeviceInfo[index]->chUserDefinedName;
|
|
string userName = static_cast<string>((LPCSTR)defineName);
|
|
//QByteArray abc = MV_CC_DeviceInfoListToQByteArray(m_stDevList);
|
|
//MV_CC_DEVICE_INFO_LIST ttt;
|
|
//ttt = QByteArrayToMV_CC_DeviceInfoList(abc);
|
|
qDebug() << "[INFO] " << " start" << "--UserName:" << QString::fromStdString(userName);
|
|
if (handle != NULL)
|
|
{
|
|
MV_CC_StopGrabbing(handle);
|
|
MV_CC_CloseDevice(handle);
|
|
MV_CC_DestroyHandle(handle);
|
|
return false;
|
|
}
|
|
|
|
//打开相机
|
|
MV_CC_CreateHandleByGenTL(&handle, m_stDevList.pDeviceInfo[index]);
|
|
int nRet = MV_CC_OpenDevice(handle);
|
|
////触发模式
|
|
//MV_CC_SetEnumValue(handle, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE);
|
|
//MV_CC_SetEnumValue(handle, "TriggerMode", MV_TRIGGER_MODE_ON);
|
|
// //加载用户集
|
|
nRet = MV_CC_SetEnumValueByString(handle, "UserSetSelector", "UserSet1");
|
|
if (MV_OK != nRet)
|
|
{
|
|
qDebug() << "Set UserSetSelector fail! nRet " << nRet;
|
|
}
|
|
// ch:注册抓图回调 | en:Register image callback
|
|
MV_CC_SetIntValueEx(handle, "GevHeartbeatTimeout", 3000);//心跳日志
|
|
nRet = MV_CC_RegisterImageCallBackEx(handle, ImageCallBackEx, handle);//注册回调
|
|
if (MV_OK != nRet)
|
|
return false;
|
|
nRet = MV_CC_RegisterExceptionCallBack(handle, ExceptionCB, NULL);//注册报警回调
|
|
//if (MV_OK != nRet)
|
|
// return false;
|
|
MV_CC_StartGrabbing(handle);
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Hd_MvCamera_module::run()
|
|
{
|
|
qDebug() << "[INFO] " << " run start" << QString::fromStdString(Username);
|
|
return true;
|
|
try
|
|
{
|
|
srcImage.release();
|
|
m_thread->start();
|
|
int reconnectSign = reconnectCount;
|
|
while (true)
|
|
{
|
|
if (reconnectCount != reconnectSign)
|
|
m_thread->start();
|
|
if (m_flag)
|
|
{
|
|
break;
|
|
}
|
|
QThread::msleep(1);
|
|
}
|
|
m_flag = false;
|
|
|
|
}
|
|
catch (QString ev)
|
|
{
|
|
qDebug() << "[Error] " << " ev:" << ev;
|
|
}
|
|
qDebug() << "[INFO] " << __LINE__ << " run end";
|
|
return true;
|
|
}
|
|
|
|
|
|
void MyThread::run()
|
|
{
|
|
MV_CC_SetCommandValue(handle, "TriggerSoftware");
|
|
}
|