1204 lines
47 KiB
C++
1204 lines
47 KiB
C++
#include "Hd_CameraModule_HIK3.h"
|
||
|
||
#include <QThread>
|
||
#include <QQueue>
|
||
#include <QMutex>
|
||
#include <QTextCodec>
|
||
#include <QCoreApplication>
|
||
#include <QDebug>
|
||
#include <QRandomGenerator>
|
||
#pragma execution_character_set("utf-8")
|
||
|
||
//0106 断线重连
|
||
void __stdcall ReconnectDevice(unsigned int nMsgType, void* pUser0);
|
||
void __stdcall ImageCallBackEx(unsigned char* pData0, MV_FRAME_OUT_INFO_EX* pFrameInfo0, void* pUser0);
|
||
void SetExposureTime(float exposureValue, MyData* m_MyData);
|
||
void SetGain(float GainValue, MyData* m_MyData);
|
||
QString byteArrayToUnicode(const QByteArray array);
|
||
//关闭设备
|
||
void CloseDevice(MyData* m_MyData);
|
||
|
||
Hd_CameraModule_HIK3* create(int settype)
|
||
{
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "Hd_CameraModule_HIK3 create success!";
|
||
return new Hd_CameraModule_HIK3(settype);
|
||
}
|
||
|
||
void destory(Hd_CameraModule_HIK3* ptr)
|
||
{
|
||
if (ptr)
|
||
{
|
||
delete ptr;
|
||
ptr = nullptr;
|
||
}
|
||
qDebug() << "[INFO] " << "Hd_CameraModule_HIK3 destory success!";
|
||
}
|
||
|
||
//int myIDS[10000] = { 0 };
|
||
|
||
//类创建
|
||
Hd_CameraModule_HIK3::Hd_CameraModule_HIK3(int settype, QObject* parent) : PbGlobalObject(settype, parent)
|
||
{
|
||
m_MyData = new MyData();
|
||
MyThread* newMyThread = new MyThread();
|
||
newMyThread->camera = this;
|
||
|
||
m_MyData->n_mutex = new QMutex();
|
||
m_MyData->ifRunning = true;
|
||
//QFuture<void> myF= QtConcurrent::run(this, &Hd_CameraModule_HIK3::threadCheckCallBack);
|
||
if (type1 < 15)
|
||
famliy = PGOFAMLIY::CAMERA2D;
|
||
else if (type1 == 15)
|
||
famliy = PGOFAMLIY::CAMERA2_5D;
|
||
else if (type1 < 100)
|
||
famliy = PGOFAMLIY::CAMERA3D;
|
||
//id = myIDS[type1]++;
|
||
qDebug() << "famliy::" << famliy;
|
||
}
|
||
|
||
|
||
Hd_CameraModule_HIK3::~Hd_CameraModule_HIK3()
|
||
{
|
||
//myIDS[type1]--;
|
||
m_MyData->ifFirst = true;
|
||
m_MyData->ifRunning = false;
|
||
m_MyData->m_flag = false;
|
||
Sleep(10);
|
||
CloseDevice(m_MyData);
|
||
if (m_MyData->n_mutex)
|
||
{
|
||
delete m_MyData->n_mutex;
|
||
m_MyData->n_mutex = nullptr;
|
||
}
|
||
/*if(m_thread)
|
||
{
|
||
m_thread->exit();
|
||
m_thread->wait(1);
|
||
delete m_thread;
|
||
m_thread = nullptr;
|
||
}*/
|
||
|
||
qDebug() << __FUNCTION__ << "line:" << __LINE__ << " delete success!";
|
||
}
|
||
|
||
//
|
||
//Hd_CameraModule_HIK3::Hd_CameraModule_HIK3()
|
||
//{
|
||
//
|
||
//}
|
||
//
|
||
//Hd_CameraModule_HIK3::~Hd_CameraModule_HIK3()
|
||
//{
|
||
// m_thread.camera = nullptr;
|
||
// ifRunning = false;
|
||
// m_flag = false;
|
||
// Sleep(10);
|
||
// CloseDevice();
|
||
// if (n_mutex)
|
||
// {
|
||
// delete n_mutex;
|
||
// n_mutex = nullptr;
|
||
// }
|
||
// /*if(m_thread)
|
||
// {
|
||
// m_thread->exit();
|
||
// m_thread->wait(1);
|
||
// delete m_thread;
|
||
// m_thread = nullptr;
|
||
// }*/
|
||
//
|
||
// qDebug() << "[INFO] " << " delete success!";
|
||
//}
|
||
//
|
||
//Hd_CameraModule_HIK3* create()
|
||
//{
|
||
// qDebug() << "[INFO] " << "Hd_CameraModule_HIK3 create success!";
|
||
// return new Hd_CameraModule_HIK3;
|
||
//}
|
||
//
|
||
//void destory(Hd_CameraModule_HIK3* ptr)
|
||
//{
|
||
// if (ptr)
|
||
// {
|
||
// delete ptr;
|
||
// ptr = nullptr;
|
||
// }
|
||
// qDebug() << "[INFO] " << "Hd_CameraModule_HIK3 destory success!";
|
||
//}
|
||
|
||
|
||
//setParameter之后再调用,返回当前参数
|
||
//相机:获取默认参数;
|
||
//通信:获取初始化示例参数
|
||
QMap<QString, QString> Hd_CameraModule_HIK3::parameters()
|
||
{
|
||
if (m_MyData->ifFirst == true)
|
||
{
|
||
m_MyData->ifFirst = false;
|
||
|
||
m_MyData->moduleName= "Hd_CameraModule_HIK3#" + QString::number(id);
|
||
|
||
QJsonObject ExampleObj = load_camera_Example();
|
||
QJsonObject cameraObj;
|
||
QJsonArray ExampleArray = ExampleObj.value("相机模块列表").toArray();
|
||
for (int i = 0; i < ExampleArray.size(); i++)
|
||
{
|
||
QString name = ExampleArray[i].toObject().value("模块名称").toString();
|
||
if (m_MyData->moduleName.split("#")[0] == name)
|
||
cameraObj = ExampleArray[i].toObject();
|
||
} //参数设置的数据
|
||
QMap<QString, QString> myParasValueMap;
|
||
myParasValueMap.insert("相机key", "输入SN");
|
||
//默认参数显示到界面
|
||
QJsonArray ParameterArray = cameraObj.value("相机参数").toArray();
|
||
for (int T = 0; T < ParameterArray.size(); T++)
|
||
{
|
||
QJsonObject ParameterObj = ParameterArray[T].toObject();
|
||
QString ParameterKey = ParameterObj.value("参数名").toString();
|
||
QString ParameterValue;
|
||
QJsonArray ParameterValueArray = ParameterObj.value("相机参数值").toArray();
|
||
for (int P = 0; P < ParameterValueArray.size(); P++)
|
||
{
|
||
if (P > 0)ParameterValue.append(",");
|
||
ParameterValue.append(ParameterValueArray[P].toString());
|
||
}
|
||
myParasValueMap.insert(ParameterKey, ParameterValue);
|
||
}
|
||
return myParasValueMap;
|
||
}
|
||
else return m_MyData->ParasValueMap;
|
||
}
|
||
|
||
//初始化参数;通信/相机的初始化参数
|
||
bool Hd_CameraModule_HIK3::setParameter(const QMap<QString, QString>& ParameterMap)
|
||
{
|
||
m_MyData->ParasValueMap = ParameterMap;
|
||
//if (m_module.moduleName.isEmpty())
|
||
//m_module.moduleName = getmoduleName();// = ParasValueMap.value()
|
||
//if(id=)
|
||
m_MyData->moduleName = "Hd_CameraModule_HIK3#" + QString::number(id);
|
||
return true;
|
||
}
|
||
|
||
//初始化(加载模块待内存)
|
||
bool Hd_CameraModule_HIK3::init()
|
||
{
|
||
////传入initParas函数,格式为:相机key+参数名1#参数值1#参数值2+参数名2#参数值1...
|
||
QString initByte = m_MyData->ParasValueMap.value("相机key");
|
||
foreach(QString key, m_MyData->ParasValueMap.keys())
|
||
{
|
||
if (key == "相机key")
|
||
continue;
|
||
initByte += "+" + key + "#";
|
||
QString ParameterValue = m_MyData->ParasValueMap.value(key);
|
||
initByte += ParameterValue.replace(",", "#");
|
||
}
|
||
|
||
this->disconnect();
|
||
if (initParas(initByte.toLocal8Bit()))
|
||
{
|
||
qDebug() << __FUNCTION__ << " line: " << __LINE__ << " key: " << m_MyData->ParasValueMap.value("相机key") << " initParas success! ";
|
||
//handdleAI3.0,重置计数,emit trigged(1000);
|
||
connect(this, &PbGlobalObject::trigged, [=](int Code) {
|
||
if (Code == 1000)
|
||
{
|
||
std::vector<cv::Mat> mat;
|
||
QByteArray data="rest_newProductIn";
|
||
writeData(mat,data);
|
||
}
|
||
});
|
||
}
|
||
else
|
||
{
|
||
qCritical() << __FUNCTION__ << " line: " << __LINE__ << " moduleName: " << m_MyData->ParasValueMap.value("相机key") << " initParas failed! ";
|
||
return false;
|
||
}
|
||
//}
|
||
//else
|
||
//{
|
||
// delete m_lib;
|
||
// m_lib = nullptr;
|
||
// return false;
|
||
//}
|
||
return true;
|
||
}
|
||
|
||
//设置数据
|
||
//相机:第一张图的参数,QStringList:00 曝光值 增益值;
|
||
//相机:第N张图的参数,QStringList:非00 曝光值 增益值;
|
||
bool Hd_CameraModule_HIK3::setData(const std::vector<cv::Mat>& mats, const QStringList& data)
|
||
{
|
||
//foreach(QString kidData,data)
|
||
//if (kidData.contains("SetExposureTime"))
|
||
{
|
||
std::vector<cv::Mat> ImgS;
|
||
QByteArray bData;
|
||
for (int i = 0; i < data.size(); i++)
|
||
//if(i>0)
|
||
// bData +=","+ data[i].toLocal8Bit();
|
||
//else
|
||
bData += data[i].toLocal8Bit();
|
||
qDebug() << "Hd_CameraModule_All::setData::" << bData;
|
||
writeData(ImgS, bData);
|
||
//if (m_module.module_ptr)
|
||
// m_module.module_ptr->writeData(ImgS, bData);
|
||
//return true;
|
||
}
|
||
foreach(QString kidData, data)
|
||
if (kidData.contains("SetExposureTime") || kidData.contains("rest_newProductIn"))
|
||
return true;
|
||
bool runResult = run(); //m_module.module_ptr->run();
|
||
return runResult;
|
||
}
|
||
//获取数据
|
||
bool Hd_CameraModule_HIK3::data(std::vector<cv::Mat>& ImgS, QStringList& QStringListdata)
|
||
{
|
||
//std::vector<cv::Mat> ImgS;
|
||
QByteArray data;
|
||
//m_module.module_ptr->readData(ImgS, data);
|
||
readData(ImgS, data);
|
||
if (!data.isEmpty())QStringListdata.append(byteArrayToUnicode(data));
|
||
return true;
|
||
}
|
||
|
||
|
||
QJsonObject Hd_CameraModule_HIK3::load_camera_Example()
|
||
{
|
||
QDir dir = QCoreApplication::applicationDirPath();
|
||
QString currPath = dir.path();
|
||
currPath = "../runtime/Bin_DEVICE";
|
||
QString json_cfg_file_path = currPath + "/camera_Example.json";
|
||
|
||
QJsonObject json_object;
|
||
try
|
||
{
|
||
QJsonParseError jsonError;
|
||
if (json_cfg_file_path.isEmpty())
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " JsonPath is null!";
|
||
return json_object;
|
||
}
|
||
|
||
QFile JsonFile;
|
||
JsonFile.setFileName(json_cfg_file_path);
|
||
//if (!JsonFile.isReadable())
|
||
//{
|
||
// qCritical() << __FUNCTION__ << " line:" << __LINE__ << " camera_Example.json not isReadable!";
|
||
// //return json_object;
|
||
//}
|
||
JsonFile.open(QIODevice::ReadOnly);
|
||
|
||
QByteArray m_Byte = JsonFile.readAll();
|
||
if (m_Byte.isEmpty())
|
||
{
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << json_cfg_file_path + " Content is empty";
|
||
JsonFile.close();
|
||
return json_object;
|
||
}
|
||
|
||
QJsonDocument jsonDocument(QJsonDocument::fromJson(m_Byte, &jsonError));
|
||
|
||
if (!jsonDocument.isNull() && jsonError.error == QJsonParseError::NoError)
|
||
{
|
||
if (jsonDocument.isObject())
|
||
{
|
||
json_object = jsonDocument.object();
|
||
JsonFile.close();
|
||
return json_object;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << json_cfg_file_path + " is error!";
|
||
}
|
||
JsonFile.close();
|
||
|
||
}
|
||
catch (QString ev)
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " ev:" << ev;
|
||
}
|
||
return json_object;
|
||
}
|
||
|
||
|
||
QString byteArrayToUnicode(const QByteArray array) {
|
||
|
||
// state用于保存转换状态,它的成员invalidChars,可用来判断是否转换成功
|
||
// 如果转换成功,则值为0,如果值大于0,则说明转换失败
|
||
QTextCodec::ConverterState state;
|
||
// 先尝试使用utf-8的方式把QByteArray转换成QString
|
||
QString text = QTextCodec::codecForName("UTF-8")->toUnicode(array.constData(), array.size(), &state);
|
||
// 如果转换时无效字符数量大于0,说明编码格式不对
|
||
if (state.invalidChars > 0)
|
||
{
|
||
// 再尝试使用GBK的方式进行转换,一般就能转换正确(当然也可能是其它格式,但比较少见了)
|
||
text = QTextCodec::codecForName("GBK")->toUnicode(array);
|
||
}
|
||
return text;
|
||
}
|
||
|
||
|
||
bool IsColor(MvGvspPixelType enType)
|
||
{
|
||
switch (enType)
|
||
{
|
||
case PixelType_Gvsp_RGB8_Packed:
|
||
case PixelType_Gvsp_YUV422_Packed:
|
||
case PixelType_Gvsp_YUV422_YUYV_Packed:
|
||
case PixelType_Gvsp_BayerGR8:
|
||
case PixelType_Gvsp_BayerRG8:
|
||
case PixelType_Gvsp_BayerGB8:
|
||
case PixelType_Gvsp_BayerBG8:
|
||
case PixelType_Gvsp_BayerGB10:
|
||
case PixelType_Gvsp_BayerGB10_Packed:
|
||
case PixelType_Gvsp_BayerBG10:
|
||
case PixelType_Gvsp_BayerBG10_Packed:
|
||
case PixelType_Gvsp_BayerRG10:
|
||
case PixelType_Gvsp_BayerRG10_Packed:
|
||
case PixelType_Gvsp_BayerGR10:
|
||
case PixelType_Gvsp_BayerGR10_Packed:
|
||
case PixelType_Gvsp_BayerGB12:
|
||
case PixelType_Gvsp_BayerGB12_Packed:
|
||
case PixelType_Gvsp_BayerBG12:
|
||
case PixelType_Gvsp_BayerBG12_Packed:
|
||
case PixelType_Gvsp_BayerRG12:
|
||
case PixelType_Gvsp_BayerRG12_Packed:
|
||
case PixelType_Gvsp_BayerGR12:
|
||
case PixelType_Gvsp_BayerGR12_Packed:
|
||
return true;
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
//搜索所有设备
|
||
int Hd_CameraModule_HIK3::SearchDevice()
|
||
{
|
||
memset(&m_MyData->m_stDevList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
|
||
// ch:枚举子网内所有设备 | en:Enumerate all devices within subnet
|
||
int nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE || MV_USB_DEVICE, &m_MyData->m_stDevList);
|
||
for (int i = 0; i < m_MyData->m_stDevList.nDeviceNum; i++)
|
||
{
|
||
//SN
|
||
unsigned char* name = m_MyData->m_stDevList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.chSerialNumber;
|
||
//userID
|
||
//unsigned char* name=m_stDevList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.chUserDefinedName;
|
||
std::string userName = static_cast<std::string>((LPCSTR)name);
|
||
if (m_MyData->Username == userName)
|
||
{
|
||
m_MyData->index = i;
|
||
break;
|
||
}
|
||
}
|
||
if (MV_OK != nRet)
|
||
{
|
||
return 0;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
bool Hd_CameraModule_HIK3::connctDevice()
|
||
{
|
||
m_MyData->index = -1;
|
||
SearchDevice();
|
||
if (m_MyData->index == -1)
|
||
{
|
||
//未匹配到相机
|
||
//qDebug() << "[Waring] " << "Hd_CameraModule_HIK3 not match --CameraName:" << QString::fromStdString(Username);
|
||
return false;
|
||
}
|
||
unsigned char* name = m_MyData->m_stDevList.pDeviceInfo[m_MyData->index]->SpecialInfo.stGigEInfo.chUserDefinedName;
|
||
std::string userName = static_cast<std::string>((LPCSTR)name);
|
||
qDebug() << "[INFO] " << " start" << "--UserName:" << QString::fromStdString(userName);
|
||
if (m_MyData->handle != NULL)
|
||
{
|
||
MV_CC_StopGrabbing(m_MyData->handle);
|
||
MV_CC_CloseDevice(m_MyData->handle);
|
||
MV_CC_DestroyHandle(m_MyData->handle);
|
||
m_MyData->handle = NULL; //此处注释掉的话,软件断开再连接,回调函数不出图
|
||
return false;
|
||
}
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "m_MyData->handle:" << m_MyData->handle;
|
||
//打开相机
|
||
int nRet=MV_CC_CreateHandle(&m_MyData->handle, m_MyData->m_stDevList.pDeviceInfo[m_MyData->index]);
|
||
if (MV_OK != nRet)
|
||
{
|
||
//qDebug() << "Set MV_CC_CreateHandle fail! nRet " << nRet;
|
||
return false;
|
||
}
|
||
|
||
//自动IP功能:注意,只获取GIGE、USB相机,其它相机不可和HIK相机在同网段。
|
||
|
||
// ch:判断设备IP是否可达
|
||
bool bAccessible=true;// = MV_CC_IsDeviceAccessible(m_stDevList.pDeviceInfo[index], MV_ACCESS_Exclusive);
|
||
if (m_MyData->m_stDevList.pDeviceInfo[m_MyData->index]->SpecialInfo.stGigEInfo.nNetExport / 256 !=
|
||
m_MyData->m_stDevList.pDeviceInfo[m_MyData->index]->SpecialInfo.stGigEInfo.nCurrentIp / 256)//nCurrentIp相机IP;nNetExport网口IP;判断前3位
|
||
bAccessible = false;
|
||
if (!bAccessible)
|
||
{
|
||
unsigned int m_dwIpaddress = m_MyData->m_stDevList.pDeviceInfo[m_MyData->index]->SpecialInfo.stGigEInfo.nNetExport; //nCurrentIp相机IP;nNetExport网口IP
|
||
unsigned int m_dwNetworkMask = m_MyData->m_stDevList.pDeviceInfo[m_MyData->index]->SpecialInfo.stGigEInfo.nCurrentSubNetMask;//掩码
|
||
unsigned int m_dwDefaultGateway = m_dwIpaddress - m_dwIpaddress % 256 + 254;//默认网关是254
|
||
for (int i = 2; i < 253; i++)//自动IP
|
||
{
|
||
unsigned int auto_dwIpaddress = m_dwIpaddress - m_dwIpaddress % 256 + i;
|
||
bool ifHas = false;
|
||
for (int k = 0; k < m_MyData->m_stDevList.nDeviceNum; k++)
|
||
{
|
||
unsigned int m_nNetExport = m_MyData->m_stDevList.pDeviceInfo[k]->SpecialInfo.stGigEInfo.nNetExport;
|
||
unsigned int m_nCurrentIp = m_MyData->m_stDevList.pDeviceInfo[k]->SpecialInfo.stGigEInfo.nCurrentIp;
|
||
//qDebug() << "k:" << k << " nNetExport:" << m_nNetExport << " nCurrentIp::" << m_nCurrentIp;
|
||
if (auto_dwIpaddress == m_nNetExport
|
||
|| auto_dwIpaddress == m_nCurrentIp) //IP占用判断
|
||
{
|
||
ifHas = true;
|
||
break;
|
||
}
|
||
}
|
||
if (ifHas)
|
||
continue;
|
||
nRet = MV_GIGE_ForceIpEx(m_MyData->handle, auto_dwIpaddress, m_dwNetworkMask, m_dwDefaultGateway);
|
||
if (MV_OK == nRet)
|
||
break;
|
||
else
|
||
{
|
||
MV_CC_DestroyHandle(m_MyData->handle);
|
||
m_MyData->handle = NULL;
|
||
nRet = MV_CC_CreateHandle(&m_MyData->handle, m_MyData->m_stDevList.pDeviceInfo[m_MyData->index]);
|
||
if (MV_OK != nRet)
|
||
{
|
||
qDebug() << "Set MV_GIGE_ForceIpEx fail! nRet " << nRet;
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
if (MV_OK != nRet)
|
||
{
|
||
//ShowErrorMsg(TEXT("ForceIp fail"), nRet);
|
||
qDebug() << "Set ForceIp fail! nRet " << nRet;
|
||
MV_CC_DestroyHandle(m_MyData->handle);
|
||
m_MyData->handle = NULL;
|
||
return false;
|
||
}
|
||
MV_CC_DestroyHandle(m_MyData->handle);
|
||
m_MyData->handle = NULL;
|
||
|
||
//ch:需要重新创建句柄,设置为静态IP方式进行保存
|
||
m_MyData->m_stDevList.pDeviceInfo[m_MyData->index]->SpecialInfo.stGigEInfo.nCurrentIp = m_dwIpaddress;
|
||
m_MyData->m_stDevList.pDeviceInfo[m_MyData->index]->SpecialInfo.stGigEInfo.nCurrentSubNetMask = m_dwNetworkMask;
|
||
m_MyData->m_stDevList.pDeviceInfo[m_MyData->index]->SpecialInfo.stGigEInfo.nDefultGateWay = m_dwDefaultGateway;
|
||
|
||
/*qDebug()<<"m_dwIpaddress "<< QString::number(m_dwIpaddress / (256 * 256 * 256)) + "." + QString::number(m_dwIpaddress / (256 * 256) % 256) + "."
|
||
+ QString::number(m_dwIpaddress / 256 % 256) + "." + QString::number(m_dwIpaddress % 256);
|
||
qDebug() << "m_dwNetworkMask " << QString::number(m_dwNetworkMask / (256 * 256 * 256)) + "." + QString::number(m_dwNetworkMask / (256 * 256) % 256) + "."
|
||
+ QString::number(m_dwNetworkMask / 256 % 256) + "." + QString::number(m_dwNetworkMask % 256);
|
||
qDebug() << "m_dwDefaultGateway " << QString::number(m_dwDefaultGateway / (256 * 256 * 256)) + "." + QString::number(m_dwDefaultGateway / (256 * 256) % 256) + "."
|
||
+ QString::number(m_dwDefaultGateway / 256 % 256) + "." + QString::number(m_dwDefaultGateway % 256);*/
|
||
|
||
|
||
nRet = MV_CC_CreateHandle(&m_MyData->handle, m_MyData->m_stDevList.pDeviceInfo[m_MyData->index]);
|
||
if (MV_OK != nRet)
|
||
{
|
||
qDebug() << "MV_CC_CreateHandle fail! nRet " << nRet;
|
||
//ShowErrorMsg(TEXT("Create handle fail"), nRet);
|
||
return false;
|
||
}
|
||
|
||
nRet = MV_GIGE_SetIpConfig(m_MyData->handle, MV_IP_CFG_STATIC);
|
||
if (MV_OK != nRet)//这里会失败,再试一次。
|
||
{
|
||
qDebug() << "MV_GIGE_SetIpConfig fail! nRet " << nRet;
|
||
//ShowErrorMsg(TEXT("Set Ip config fail"), nRet);
|
||
MV_CC_DestroyHandle(m_MyData->handle);
|
||
m_MyData->handle = NULL;
|
||
return false;
|
||
}
|
||
}
|
||
|
||
nRet = MV_CC_OpenDevice(m_MyData->handle);
|
||
////触发模式
|
||
if (m_MyData->currentTriggerSource != MV_TRIGGER_SOURCE_SOFTWARE)
|
||
MV_CC_SetEnumValue(m_MyData->handle, "TriggerSource", MV_TRIGGER_SOURCE_LINE0);
|
||
else
|
||
MV_CC_SetEnumValue(m_MyData->handle, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE);
|
||
MVCC_ENUMVALUE stEnumValue = { 0 };
|
||
MV_CC_GetEnumValue(m_MyData->handle, "TriggerSource", &stEnumValue); //获取当前触发方式
|
||
if (m_MyData->currentTriggerSource != stEnumValue.nCurValue)
|
||
MV_CC_SetEnumValue(m_MyData->handle, "TriggerSource", m_MyData->currentTriggerSource);
|
||
|
||
MV_CC_SetEnumValue(m_MyData->handle, "TriggerMode", MV_TRIGGER_MODE_ON);
|
||
// //加载用户集,相机设置应当UserSet1
|
||
//nRet = MV_CC_SetEnumValueByString(handle, "UserSetSelector", "UserSet1");
|
||
if (MV_OK != nRet)
|
||
{
|
||
//qDebug() << "Set UserSetSelector fail! nRet " << nRet;
|
||
return false;
|
||
}
|
||
// ch:注册抓图回调 | en:Register image callback
|
||
MV_CC_SetIntValueEx(m_MyData->handle, "GevHeartbeatTimeout", 3000);//心跳日志
|
||
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "m_MyData->handle:" << m_MyData->handle;
|
||
|
||
nRet = MV_CC_RegisterImageCallBackEx(m_MyData->handle, ImageCallBackEx, (void*)this);//注册回调
|
||
if (MV_OK != nRet)
|
||
return false;
|
||
nRet = MV_CC_RegisterExceptionCallBack(m_MyData->handle, ReconnectDevice, (void*)this);//断线重连
|
||
if (MV_OK != nRet)
|
||
return false;
|
||
MV_CC_StartGrabbing(m_MyData->handle);
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "m_MyData->handle:" << m_MyData->handle;
|
||
return true;
|
||
}
|
||
|
||
//0106 断线重连
|
||
void __stdcall ReconnectDevice(unsigned int nMsgType, void* pUser0)
|
||
{
|
||
Hd_CameraModule_HIK3* ptr = (Hd_CameraModule_HIK3*)pUser0;
|
||
ptr->m_MyData->mv_Status = "disconnect";
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "[Error] " << " MV camera disconnects!";
|
||
ptr->m_MyData->moduleStatus = false;
|
||
if (nMsgType == MV_EXCEPTION_DEV_DISCONNECT)
|
||
{
|
||
//断开连接
|
||
MV_CC_CloseDevice(ptr->m_MyData->handle);
|
||
int nRet = MV_CC_DestroyHandle(ptr->m_MyData->handle);
|
||
ptr->m_MyData->handle = NULL;
|
||
ptr->threadCheckCallBack(1);
|
||
//newMyThread->runEmit(1, ptr->m_MyData);
|
||
BOOL bConnected = FALSE;
|
||
// 初始化随机数生成器
|
||
//QRandomGenerator::seed();
|
||
while (1)
|
||
{
|
||
// 生成一个随机整数
|
||
int randomNumber = QRandomGenerator::global()->bounded(500); //多相机无随机时,重连稍慢
|
||
|
||
Sleep(randomNumber);
|
||
// 输出到控制台
|
||
//qDebug() << "Random Number:" << randomNumber;
|
||
Sleep(100);
|
||
if (ptr->connctDevice() == true)
|
||
{
|
||
qWarning() << __FUNCTION__ << " line:" << __LINE__ << "[Hd_CameraModule_HIK3] " << " Hd_CameraModule_HIK3 create success again! ";
|
||
ptr->m_MyData->moduleStatus = true;
|
||
ptr->threadCheckCallBack(0);
|
||
//newMyThread->runEmit(0, ptr->m_MyData);
|
||
//m_thread.runEmit(0);
|
||
break;
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
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;
|
||
|
||
}
|
||
|
||
//cameraIndex,函数指针的map
|
||
//QMap< QString, QObject*> mMap_cameraIndex_QObject;
|
||
|
||
//注册回调 string对应自身的参数协议 (自定义)
|
||
void Hd_CameraModule_HIK3::registerCallBackFun(PBGLOBAL_CALLBACK_FUN callBackFun, QObject* m_QObject, const QString& cameraIndex)
|
||
{
|
||
m_MyData->n_mutex->lock();
|
||
myPBGLOBAL_callBack m_myPBGLOBAL_callBack;
|
||
m_myPBGLOBAL_callBack.callBackFun = callBackFun;
|
||
m_myPBGLOBAL_callBack.m_QObject = m_QObject;
|
||
m_myPBGLOBAL_callBack.cameraIndex = cameraIndex;
|
||
m_MyData->QQueue_myPBGLOBAL_callBack.enqueue(m_myPBGLOBAL_callBack);
|
||
m_MyData->n_mutex->unlock();
|
||
}
|
||
//注销回调 string对应自身的参数协议 (自定义)--->注销后还得取消连接状态
|
||
void Hd_CameraModule_HIK3::cancelCallBackFun(PBGLOBAL_CALLBACK_FUN callBackFun, QObject* m_QObject, const QString& cameraIndex)
|
||
{
|
||
m_MyData->n_mutex->lock();
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "try cancelCallBackFun";
|
||
for (int i = 0; i < m_MyData->QQueue_myPBGLOBAL_callBack.size(); i++)
|
||
{
|
||
if (m_MyData->QQueue_myPBGLOBAL_callBack[i].callBackFun == NULL)
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "QQueue_myPBGLOBAL_callBack[i].callBackFun == NULL";
|
||
if(m_MyData->QQueue_myPBGLOBAL_callBack[i].m_QObject ==NULL)
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "QQueue_myPBGLOBAL_callBack[i].m_QObject == NULL";
|
||
|
||
if (m_MyData->QQueue_myPBGLOBAL_callBack[i].callBackFun == callBackFun &&
|
||
m_MyData->QQueue_myPBGLOBAL_callBack[i].m_QObject == m_QObject &&
|
||
m_MyData->QQueue_myPBGLOBAL_callBack[i].cameraIndex == cameraIndex)
|
||
{
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "try QQueue_myPBGLOBAL_callBack.removeAt(i)";
|
||
m_MyData->QQueue_myPBGLOBAL_callBack.removeAt(i);
|
||
break;
|
||
}
|
||
}
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "try cancelCallBackFun done!";
|
||
m_MyData->n_mutex->unlock();
|
||
}
|
||
|
||
//回调函数;
|
||
//经测试,相机像素格式Mono8、RGB8是可以正常转换的,YUV422还需要优化;RGB8格式比YUV422帧率低;BGR格式会导致异色问题
|
||
void __stdcall ImageCallBackEx(unsigned char* pData0, MV_FRAME_OUT_INFO_EX* pFrameInfo0, void* pUser0)//this
|
||
{
|
||
Hd_CameraModule_HIK3* Data = (Hd_CameraModule_HIK3*)pUser0;
|
||
|
||
Data->m_MyData->n_mutex->lock();
|
||
double time_Start = (double)clock();
|
||
int frameNum = 0;
|
||
Data->m_MyData->QQueue_srcImage.clear();
|
||
Data->m_MyData->srcImage = cv::Mat();
|
||
// ch:像素格式转换 | en:Convert pixel format
|
||
MV_CC_PIXEL_CONVERT_PARAM stConvertParam = { 0 };
|
||
unsigned char* pConvertData = NULL;
|
||
if (pFrameInfo0)
|
||
{
|
||
//获取的是单通道灰度图
|
||
if (pFrameInfo0->enPixelType == PixelType_Gvsp_Mono8)//获取当前采集到的图像格式
|
||
{
|
||
Data->m_MyData->srcImage = cv::Mat(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC1, pData0);
|
||
}
|
||
//获取的是BGR8图
|
||
else if (pFrameInfo0->enPixelType == PixelType_Gvsp_BGR8_Packed)
|
||
{
|
||
Data->m_MyData->srcImage = cv::Mat(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC3, pData0);
|
||
}
|
||
|
||
////获取的是RGB8图
|
||
//else if (pFrameInfo0->enPixelType == PixelType_Gvsp_RGB8_Packed)
|
||
//{
|
||
// cv::Mat dst = cv::Mat(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC3, pData0);
|
||
// //cv::cvtColor(matimage, matimage, cv::COLOR_RGB2BGR);
|
||
// srcImage = cv::Mat::zeros(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC3);
|
||
// std::vector<cv::Mat> channels;
|
||
// cv::split(dst, channels);//分割matimage的通道
|
||
// std::vector<cv::Mat> dstchannels;
|
||
// for (int i = 2; i >= 0; i--)
|
||
// {
|
||
// dstchannels.push_back(channels[i]);
|
||
// }
|
||
// merge(dstchannels, srcImage);
|
||
//}
|
||
|
||
else if (IsColor(pFrameInfo0->enPixelType)) //其它格式彩色图
|
||
{
|
||
MvGvspPixelType enDstPixelType = PixelType_Gvsp_Undefined;
|
||
enDstPixelType = PixelType_Gvsp_BGR8_Packed;
|
||
pConvertData = (unsigned char*)malloc(pFrameInfo0->nWidth * pFrameInfo0->nHeight * 3);
|
||
if (NULL == pConvertData)
|
||
{
|
||
printf("malloc pConvertData fail!\n");
|
||
}
|
||
else
|
||
{
|
||
unsigned int nConvertDataSize = 0;
|
||
nConvertDataSize = pFrameInfo0->nWidth * pFrameInfo0->nHeight * 3;
|
||
|
||
frameNum = pFrameInfo0->nFrameNum; //ch:帧号 | en:frame number
|
||
stConvertParam.nWidth = pFrameInfo0->nWidth; //ch:图像宽 | en:image width
|
||
stConvertParam.nHeight = pFrameInfo0->nHeight; //ch:图像高 | en:image height
|
||
stConvertParam.pSrcData = pData0; //ch:输入数据缓存 | en:input data buffer
|
||
stConvertParam.nSrcDataLen = pFrameInfo0->nFrameLen; //ch:输入数据大小 | en:input data size
|
||
stConvertParam.enSrcPixelType = pFrameInfo0->enPixelType; //ch:输入像素格式 | en:input pixel format
|
||
stConvertParam.enDstPixelType = enDstPixelType; //ch:输出像素格式 | en:output pixel format
|
||
stConvertParam.pDstBuffer = pConvertData; //ch:输出数据缓存 | en:output data buffer
|
||
stConvertParam.nDstBufferSize = nConvertDataSize; //ch:输出缓存大小 | en:output buffer size
|
||
int nRet = MV_CC_ConvertPixelType(Data->m_MyData->handle, &stConvertParam);
|
||
|
||
//Mat mysrcImage = cv::Mat(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC3, stConvertParam.pDstBuffer);
|
||
//mysrcImage.copyTo(srcImage);//回调需要深拷贝,否则图像会出现重复
|
||
Data->m_MyData->srcImage= cv::Mat(pFrameInfo0->nHeight, pFrameInfo0->nWidth, CV_8UC3, pConvertData);
|
||
stConvertParam = { 0 };
|
||
}
|
||
}
|
||
}
|
||
if(Data->m_MyData->srcImage.empty())
|
||
{
|
||
Data->m_MyData->srcImage = cv::Mat(5, 5, CV_8UC1).setTo(0);
|
||
}
|
||
Data->m_MyData->QQueue_srcImage.enqueue(Data->m_MyData->srcImage.clone());
|
||
//cv::Mat resizeM;
|
||
//cv::resize(srcImage, resizeM, cv::Size(), 0.1, 0.1);
|
||
//cv::imwrite("../runtime/Bin_DEVICE/testImg/"+Username + ".png", resizeM);
|
||
|
||
Data->m_MyData->m_flag = true;
|
||
Data->m_MyData->callBackNum++;
|
||
QString tmpDate = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
|
||
if (Data->m_MyData->currentTriggerSource == MV_TRIGGER_SOURCE_LINE0)//硬触发,回调
|
||
{
|
||
std::vector<cv::Mat> mat;
|
||
mat.push_back(Data->m_MyData->QQueue_srcImage.dequeue());
|
||
//触发回调
|
||
for (int i = 0; i < Data->m_MyData->QQueue_myPBGLOBAL_callBack.size(); i++)
|
||
if (Data->m_MyData->QQueue_myPBGLOBAL_callBack[i].cameraIndex == QString::number(Data->m_MyData->imgIndex))
|
||
(*Data->m_MyData->QQueue_myPBGLOBAL_callBack[i].callBackFun)(Data->m_MyData->QQueue_myPBGLOBAL_callBack[i].m_QObject, mat);
|
||
Data->m_MyData->imgIndex++;
|
||
if (Data->m_MyData->expourseTimeList.size() > 1 && Data->m_MyData->expourseTimeList[Data->m_MyData->imgIndex % Data->m_MyData->expourseTimeList.size()]
|
||
!= Data->m_MyData->expourseTimeList[(Data->m_MyData->imgIndex - 1) % Data->m_MyData->expourseTimeList.size()])
|
||
SetExposureTime(Data->m_MyData->expourseTimeList[Data->m_MyData->imgIndex % Data->m_MyData->expourseTimeList.size()], Data->m_MyData);
|
||
//Sleep(1);
|
||
if (Data->m_MyData->gainList.size() > 1 && Data->m_MyData->gainList[Data->m_MyData->imgIndex % Data->m_MyData->gainList.size()]
|
||
!= Data->m_MyData->gainList[(Data->m_MyData->imgIndex - 1) % Data->m_MyData->gainList.size()])
|
||
SetGain(Data->m_MyData->gainList[Data->m_MyData->imgIndex % Data->m_MyData->gainList.size()], Data->m_MyData);
|
||
|
||
|
||
if (Data->m_MyData->imgIndex >= Data->m_MyData->expourseTimeList.size())
|
||
Data->m_MyData->imgIndex = 0;
|
||
}
|
||
//else
|
||
// Data->m_MyData->imgIndex++;
|
||
stConvertParam = { 0 };
|
||
free(pConvertData);
|
||
pConvertData= NULL;
|
||
Data->m_MyData->n_mutex->unlock();
|
||
double time_End = (double)clock();
|
||
qDebug() << tmpDate << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getImg,Time:" << (time_End - time_Start) << "ms"
|
||
<< "--CameraName:" << QString::fromStdString(Data->m_MyData->Username) << " imgIndex:" << Data->m_MyData->imgIndex << "nFrameNum : " << frameNum<<" callBackNum::"<< Data->m_MyData->callBackNum;
|
||
|
||
//m_thread.run();
|
||
|
||
/*QString savePath = "../runtime/Bin_DEVICE/testImg/camera_"+QString::fromStdString(Username) +"_" + QString::number(imgIndex + 1) + ".png";
|
||
cv::Mat resizeS;
|
||
cv::resize(srcImage, resizeS, cv::Size(), 0.1, 0.1);
|
||
cv::imwrite(savePath.toStdString(), resizeS);*/
|
||
}
|
||
|
||
void SetExposureTime(float exposureValue, MyData* m_MyData)
|
||
{
|
||
qDebug() << "[INFO] " << "exposureValue:" << exposureValue;
|
||
MV_CC_SetEnumValue(m_MyData->handle, "ExposureAuto", MV_EXPOSURE_AUTO_MODE_OFF);
|
||
MV_CC_SetFloatValue(m_MyData->handle, "ExposureTime", exposureValue);
|
||
}
|
||
|
||
void SetGain(float GainValue, MyData* m_MyData)
|
||
{
|
||
qDebug() << "[INFO] " << "GainValue:" << GainValue;
|
||
MV_CC_SetEnumValue(m_MyData->handle, "GainAuto", 0);
|
||
MV_CC_SetFloatValue(m_MyData->handle, "Gain", GainValue);
|
||
}
|
||
//关闭设备
|
||
void CloseDevice(MyData* m_MyData)
|
||
{
|
||
MV_CC_StopGrabbing(m_MyData->handle);
|
||
MV_CC_CloseDevice(m_MyData->handle);
|
||
MV_CC_DestroyHandle(m_MyData->handle);
|
||
m_MyData->handle = NULL; //此处注释掉的话,软件断开再连接,回调函数不出图
|
||
}
|
||
|
||
void MyThread::runEmit(int code, MyData* m_MyData)
|
||
{
|
||
if (camera)
|
||
camera->threadCheckCallBack(code);
|
||
}
|
||
void Hd_CameraModule_HIK3::threadCheckCallBack(int code)
|
||
{
|
||
//while (ifRunning)
|
||
{
|
||
//if (currentTriggerSource != MV_TRIGGER_SOURCE_SOFTWARE)
|
||
/* if (m_flag == true)
|
||
{
|
||
qDebug() << QThread::currentThreadId()<< " Username::" << QString::fromStdString(Username) << "[INFO] " << "emit trigged,triggedNum:"<< triggedNum++;
|
||
emit trigged(true);
|
||
n_mutex->lock();
|
||
m_flag = false;
|
||
n_mutex->unlock();
|
||
}*/
|
||
|
||
if (m_MyData->ifThemoduleStatus != m_MyData->moduleStatus)
|
||
{
|
||
qDebug() << "[INFO] " << "moduleStatus changed emit trigged:" << m_MyData->moduleStatus;
|
||
if(m_MyData->moduleStatus)
|
||
emit trigged(0);
|
||
else
|
||
emit trigged(1);
|
||
m_MyData->ifThemoduleStatus = m_MyData->moduleStatus;
|
||
}
|
||
if(m_MyData->moduleStatus==false)
|
||
qApp->processEvents();
|
||
Sleep(5);
|
||
}
|
||
}
|
||
|
||
//从类中读数据到实例对象
|
||
bool Hd_CameraModule_HIK3::readData(std::vector<cv::Mat> &mat,QByteArray &data)
|
||
{
|
||
if (m_MyData->QQueue_srcImage.isEmpty())//(!srcImage.data)
|
||
{
|
||
qCritical() << __FUNCTION__ << " line:" <<__LINE__ << " srcImage is null";
|
||
return false;
|
||
}
|
||
m_MyData->n_mutex->lock();
|
||
//mat.push_back(srcImage.clone());
|
||
//mat.push_back(srcImage);//非深拷贝,显示时或其他使用mat的时间,回调函数进来,改掉了srcImage,导致使用时崩溃。
|
||
mat.push_back(m_MyData->QQueue_srcImage.dequeue());// .clone());
|
||
//srcImage = cv::Mat();
|
||
m_MyData->n_mutex->unlock();
|
||
QString qimgIndex = "imgIndex_" + QString::number(m_MyData->imgIndex-1)+"_中文测试";
|
||
data = qimgIndex.toLocal8Bit();
|
||
QString tmpDate = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
|
||
qDebug() << tmpDate << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg readData--CameraName:" << QString::fromStdString(m_MyData->Username) << "--imgIndex : " << m_MyData->imgIndex-1;
|
||
return true;
|
||
}
|
||
//实例对象把数据写入到类
|
||
bool Hd_CameraModule_HIK3::writeData(std::vector<cv::Mat> &mat,QByteArray &data)
|
||
{
|
||
//2024.02.18更新,相机对应的读SN信号时,表示新产品进入,设置初始值
|
||
if (data == "rest_newProductIn")
|
||
{
|
||
m_MyData->n_mutex->lock();
|
||
//根据实际项目,设置初始值:曝光、增益,ROI区域等
|
||
{
|
||
if (m_MyData->expourseTimeList.size() > 0)
|
||
SetExposureTime(m_MyData->expourseTimeList[0], m_MyData);
|
||
if (m_MyData->gainList.size() > 0)
|
||
SetGain(m_MyData->gainList[0], m_MyData);
|
||
}
|
||
//srcImage = cv::Mat();
|
||
m_MyData->QQueue_srcImage.clear();
|
||
m_MyData->n_mutex->unlock();
|
||
if (m_MyData->ifRunning == true)
|
||
{
|
||
m_MyData->ifBreak = true;
|
||
Sleep(10);
|
||
}
|
||
m_MyData->imgIndex = 0;
|
||
return true;
|
||
}
|
||
//else
|
||
//{
|
||
// //m_flag = false;
|
||
// //expourseTimeList.clear();
|
||
// //gainList.clear();
|
||
//}
|
||
if (data == "ifChangeExpourseAndGain_false")
|
||
m_MyData->ifChangeExpourseAndGain = false;
|
||
else
|
||
m_MyData->ifChangeExpourseAndGain = true;
|
||
m_MyData->n_mutex->lock();
|
||
if (data.contains("SetExposureTime_"))
|
||
{
|
||
QByteArrayList dataList = data.split('#');
|
||
for (int i = 0; i < dataList.size(); i++)
|
||
{
|
||
if (dataList[i].contains("SetExposureTime_"))
|
||
{
|
||
int value = byteArrayToUnicode(dataList[i]).split("SetExposureTime_")[1].toInt();
|
||
SetExposureTime(value, m_MyData);
|
||
}
|
||
if (dataList[i].contains("SetGain_"))
|
||
{
|
||
double value = byteArrayToUnicode(dataList[i]).split("SetGain_")[1].toInt();
|
||
SetGain(value, m_MyData);
|
||
}
|
||
if (dataList[i].contains("TriggerMode_"))
|
||
{
|
||
QString value = byteArrayToUnicode(dataList[i]).split("TriggerMode_")[1];
|
||
if (value == "软触发" || value == "soft")
|
||
////触发模式
|
||
{
|
||
qDebug() << "MV_CC_SetEnumValue MV_TRIGGER_SOURCE_SOFTWARE";
|
||
if (m_MyData->currentTriggerSource != MV_TRIGGER_SOURCE_SOFTWARE)
|
||
{
|
||
MV_CC_SetEnumValue(m_MyData->handle, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE);
|
||
m_MyData->currentTriggerSource = MV_TRIGGER_SOURCE_SOFTWARE;
|
||
}
|
||
}
|
||
else if (value == "硬触发" || value == "hard")
|
||
{
|
||
qDebug() << "MV_CC_SetEnumValue MV_TRIGGER_SOURCE_LINE0";
|
||
if (m_MyData->currentTriggerSource != MV_TRIGGER_SOURCE_LINE0)
|
||
{
|
||
MV_CC_SetEnumValue(m_MyData->handle, "TriggerSource", MV_TRIGGER_SOURCE_LINE0);
|
||
m_MyData->currentTriggerSource = MV_TRIGGER_SOURCE_LINE0;
|
||
}
|
||
}
|
||
else
|
||
qDebug() << "TriggerMode err ,may Chinese Name!";
|
||
|
||
MVCC_ENUMVALUE stEnumValue = { 0 };
|
||
MV_CC_GetEnumValue(m_MyData->handle, "TriggerSource", &stEnumValue); //获取当前触发方式
|
||
if (m_MyData->currentTriggerSource != stEnumValue.nCurValue)
|
||
MV_CC_SetEnumValue(m_MyData->handle, "TriggerSource", m_MyData->currentTriggerSource);
|
||
}
|
||
}
|
||
}
|
||
//调试模式下,data==ifChangeExpourseAndGain_false;非调试模式运行时,data不包含SetExposureTime_
|
||
else if (data != "ifChangeExpourseAndGain_false" && m_MyData->initTriggerSource != m_MyData->currentTriggerSource)
|
||
{
|
||
MV_CC_SetEnumValue(m_MyData->handle, "TriggerSource", m_MyData->initTriggerSource);
|
||
m_MyData->currentTriggerSource = m_MyData->initTriggerSource;
|
||
}
|
||
m_MyData->n_mutex->unlock();
|
||
|
||
|
||
/*data.append("SetExposureTime_" + ui.spinBox->text() + "#");
|
||
data.append("SetGain_" + ui.doubleSpinBox->text() + "#");
|
||
data.append("TriggerMode_" + ui.comboBox_triggerMode->currentText());*/
|
||
|
||
|
||
qDebug() << "Hd_CameraModule_HIK3::writeData::" << data;
|
||
|
||
//m_flag = false;
|
||
//Username = data.toStdString();
|
||
return true;
|
||
}
|
||
|
||
|
||
//传入initParas函数,格式为:相机key+参数名1#参数值1#参数值2+参数名2#参数值1...
|
||
bool Hd_CameraModule_HIK3::initParas(QByteArray& initData)
|
||
{
|
||
QByteArrayList valueList = initData.split('+');
|
||
m_MyData->Username = valueList[0];
|
||
m_MyData->imgIndex = 0;
|
||
|
||
m_MyData->expourseTimeList.clear();
|
||
m_MyData->gainList.clear();
|
||
|
||
|
||
bool ifOk = true;
|
||
if (m_MyData->handle == NULL)
|
||
ifOk = connctDevice();
|
||
if (ifOk == false)
|
||
{
|
||
qDebug() << "try connctDevice again!"<<QString::fromStdString(m_MyData->Username);
|
||
ifOk = connctDevice();
|
||
}
|
||
if (ifOk == false)
|
||
return false;
|
||
if (valueList.size() > 1)
|
||
for (int i = 1; i < valueList.size(); i++)
|
||
{
|
||
QString valuei = byteArrayToUnicode(valueList[i]);
|
||
//valuei.prepend(valueList[i]);
|
||
if (valuei.contains("expourseTime"))
|
||
{
|
||
QStringList expourseTimeL = valuei.split('#');
|
||
if (expourseTimeL.size() > 1)
|
||
for (int j = 1; j < expourseTimeL.size(); j++)
|
||
m_MyData->expourseTimeList.enqueue(expourseTimeL[j].toFloat());
|
||
}
|
||
if (valuei.contains("gain"))
|
||
{
|
||
QStringList gainL = valuei.split('#');
|
||
if (gainL.size() > 1)
|
||
for (int j = 1; j < gainL.size(); j++)
|
||
m_MyData->gainList.enqueue(gainL[j].toFloat());
|
||
}
|
||
|
||
if (valuei.contains("是否为标准通信流程"))
|
||
{
|
||
if (valuei.contains("true"))
|
||
m_MyData->ifStandard = true;
|
||
}
|
||
if (valuei.contains("取图超时") || valuei.contains("getImageTimeOut"))
|
||
{
|
||
QStringList gainL = valuei.split('#');
|
||
if (gainL.size() > 1)
|
||
m_MyData->getImageTimeOut = gainL[1].toInt();
|
||
if (m_MyData->getImageTimeOut < 50)
|
||
m_MyData->getImageTimeOut = 1000;
|
||
}
|
||
if (valuei.contains("OffsetX"))
|
||
{
|
||
QStringList valueL = valuei.split('#');
|
||
if (valueL.size() > 1)
|
||
if(valueL[1].toInt()>=0)
|
||
MV_CC_SetIntValue(m_MyData->handle, "OffsetX", valueL[1].toInt());
|
||
}
|
||
if (valuei.contains("OffsetY"))
|
||
{
|
||
QStringList valueL = valuei.split('#');
|
||
if (valueL.size() > 1)
|
||
if (valueL[1].toInt() >= 0)
|
||
MV_CC_SetIntValue(m_MyData->handle, "OffsetY", valueL[1].toInt());
|
||
}
|
||
if (valuei.contains("Width"))
|
||
{
|
||
QStringList valueL = valuei.split('#');
|
||
if (valueL.size() > 1)
|
||
if (valueL[1].toInt() >= 0)
|
||
MV_CC_SetIntValue(m_MyData->handle, "Width", valueL[1].toInt());
|
||
}
|
||
if (valuei.contains("Height"))
|
||
{
|
||
QStringList valueL = valuei.split('#');
|
||
if (valueL.size() > 1)
|
||
if (valueL[1].toInt() >= 0)
|
||
MV_CC_SetIntValue(m_MyData->handle, "Height", valueL[1].toInt());
|
||
}
|
||
|
||
if (valuei.contains("触发方式") || valuei.contains("TriggerMode"))
|
||
{
|
||
QStringList valueL = valuei.split('#');
|
||
if (valueL.size() > 1)
|
||
if (valueL[1].toInt() >= 0)
|
||
if (valueL[1] == "软触发" || valueL[1] == "soft")
|
||
{
|
||
MV_CC_SetEnumValue(m_MyData->handle, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE);
|
||
m_MyData->currentTriggerSource = MV_TRIGGER_SOURCE_SOFTWARE;
|
||
m_MyData->initTriggerSource = MV_TRIGGER_SOURCE_SOFTWARE;
|
||
}
|
||
else if (valueL[1] == "硬触发" || valueL[1] == "hard")
|
||
{
|
||
MV_CC_SetEnumValue(m_MyData->handle, "TriggerSource", MV_TRIGGER_SOURCE_LINE0);
|
||
m_MyData->currentTriggerSource = MV_TRIGGER_SOURCE_LINE0;
|
||
m_MyData->initTriggerSource = MV_TRIGGER_SOURCE_LINE0;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (ifOk == true)
|
||
{
|
||
if (m_MyData->expourseTimeList.size() > 0)
|
||
SetExposureTime(m_MyData->expourseTimeList[0], m_MyData);
|
||
if (m_MyData->gainList.size() > 0)
|
||
SetGain(m_MyData->gainList[0], m_MyData);
|
||
}
|
||
m_MyData->imgIndex = 0;
|
||
if (ifOk == true)
|
||
{
|
||
MVCC_FLOATVALUE mf = { 0 };
|
||
MV_CC_GetFloatValue(m_MyData->handle, "ExposureTime", &mf);
|
||
std::cout << "ExposureTime::" << mf.fCurValue << std::endl;
|
||
mf = { 0 };
|
||
MV_CC_GetFloatValue(m_MyData->handle, "Gain", &mf);
|
||
std::cout << "Gain::" << mf.fCurValue << std::endl;
|
||
MVCC_INTVALUE mI = { 0 };
|
||
MV_CC_GetIntValue(m_MyData->handle, "OffsetX", &mI);
|
||
std::cout << "OffsetX::" << mI.nCurValue << std::endl;
|
||
mI = { 0 };
|
||
MV_CC_GetIntValue(m_MyData->handle, "OffsetY", &mI);
|
||
std::cout << "OffsetY::" << mI.nCurValue << std::endl;
|
||
mI = { 0 };
|
||
MV_CC_GetIntValue(m_MyData->handle, "Width", &mI);
|
||
std::cout << "Width::" << mI.nCurValue << std::endl;
|
||
mI = { 0 };
|
||
MV_CC_GetIntValue(m_MyData->handle, "Height", &mI);
|
||
std::cout << "Height::" << mI.nCurValue << std::endl;
|
||
MVCC_ENUMVALUE me = { 0 };
|
||
MV_CC_GetEnumValue(m_MyData->handle,"BalanceWhiteAuto",&me); //自动白平衡
|
||
std::cout << "BalanceWhiteAuto::" << me.nCurValue << std::endl;
|
||
|
||
}
|
||
|
||
return ifOk;
|
||
}
|
||
bool Hd_CameraModule_HIK3::run()
|
||
{
|
||
if (m_MyData->moduleStatus == false)
|
||
return false;
|
||
if (m_MyData->imgIndex >= m_MyData->expourseTimeList.size())
|
||
m_MyData->imgIndex = 0;
|
||
//Sleep(100);
|
||
QString tmpDate = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
|
||
qDebug() << tmpDate << "[INFO] " << " run start" <<QString::fromStdString(m_MyData->Username);
|
||
bool result = false;
|
||
m_MyData->ifRunning = true;
|
||
m_MyData->ifBreak = false;
|
||
//srcImage.release();
|
||
try
|
||
{
|
||
//n_mutex->lock();
|
||
m_MyData->m_flag = false;
|
||
//Sleep(2);
|
||
//n_mutex->unlock();
|
||
//m_thread->run(); //start()线程运行,频率高时有低概率无响应;
|
||
|
||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "m_MyData->handle:" << m_MyData->handle;
|
||
if (m_MyData->currentTriggerSource == MV_TRIGGER_SOURCE_SOFTWARE)
|
||
{
|
||
MV_CC_SetCommandValue(m_MyData->handle, "TriggerSoftware");
|
||
qDebug() << "[INFO] " << "TriggerSoftware";
|
||
}
|
||
else
|
||
qDebug() << "[INFO] " << "TriggerHardware";
|
||
//MV_CC_SetCommandValue(handle, "TriggerSoftware");
|
||
//Sleep(15);
|
||
int mytime = 0;
|
||
qDebug() << "[INFO] " << " waite Img" << QString::fromStdString(m_MyData->Username);
|
||
while (true)
|
||
{
|
||
if (m_MyData->moduleStatus == false || mytime++ > m_MyData->getImageTimeOut || m_MyData->ifBreak == true )//|| m_flag==true)
|
||
{
|
||
result = false;
|
||
break;
|
||
}
|
||
m_MyData->n_mutex->lock();
|
||
if (m_MyData->m_flag == true)
|
||
{
|
||
m_MyData->n_mutex->unlock();
|
||
result = true;
|
||
break;
|
||
}
|
||
m_MyData->n_mutex->unlock();
|
||
Sleep(1);
|
||
}
|
||
Sleep(1);
|
||
|
||
//qDebug() << "[INFO] " << " expourseTimeList " << QString::fromStdString(Username);
|
||
//软触发,不考虑误触发、漏触发
|
||
if (m_MyData->ifChangeExpourseAndGain == true)
|
||
{
|
||
m_MyData->imgIndex++;
|
||
if (m_MyData->expourseTimeList.size() > 1 && m_MyData->expourseTimeList[m_MyData->imgIndex % m_MyData->expourseTimeList.size()]
|
||
!= m_MyData->expourseTimeList[(m_MyData->imgIndex - 1) % m_MyData->expourseTimeList.size()])
|
||
SetExposureTime(m_MyData->expourseTimeList[m_MyData->imgIndex % m_MyData->expourseTimeList.size()], m_MyData);
|
||
//Sleep(1);
|
||
if (m_MyData->gainList.size() > 1 && m_MyData->gainList[m_MyData->imgIndex % m_MyData->gainList.size()]
|
||
!= m_MyData->gainList[(m_MyData->imgIndex - 1) % m_MyData->gainList.size()])
|
||
SetGain(m_MyData->gainList[m_MyData->imgIndex % m_MyData->gainList.size()], m_MyData);
|
||
//Sleep(1);
|
||
}
|
||
/*if (result == false)
|
||
{
|
||
QString currPath = "../runtime/Bin_DEVICE/testImg/testImg_";
|
||
if (ifChangeExpourseAndGain == true)
|
||
currPath +=QString::number(imgIndex-1);
|
||
else
|
||
currPath += QString::number(imgIndex);
|
||
currPath += ".jpg";
|
||
n_mutex->lock();
|
||
srcImage = cv::imread(currPath.toStdString());
|
||
n_mutex->unlock();
|
||
qDebug() << "取图失败,读取图片:" << currPath;
|
||
result = true;
|
||
}*/
|
||
|
||
}
|
||
catch (QString ev)
|
||
{
|
||
qDebug() << "[Error] " << " ev:" << ev ;
|
||
}
|
||
qDebug() << "[INFO] " << __LINE__ << " run end" ;
|
||
return result;
|
||
}
|
||
|
||
//相机连接状态:正常连接或断开
|
||
bool Hd_CameraModule_HIK3::checkStatus()
|
||
{
|
||
//status = moduleStatus;
|
||
return m_MyData->moduleStatus;
|
||
}
|
||
|
||
//void MyThread::run()
|
||
//{
|
||
// MV_CC_SetCommandValue(handle, "TriggerSoftware");
|
||
//}
|