> 技术文档 > 3:QT联合HALCON编程—海康相机SDK二次程序开发_海康相机二次开发

3:QT联合HALCON编程—海康相机SDK二次程序开发_海康相机二次开发


思路:

1.定义带UI界面的主函数类

         1.1在主函数中包含其它所有类头文件,进行声明和实例化;使用相机时,是用公共相机的接口在某一个具体函数中去实例化具体的海康相机对象。

        1.2设计界面:连接相机,单次采集,连续采集,停止采集,关闭相机

        1.3在连续采集中,开始启用线程。需要在线程类中采集图像,通过信号与槽在主函数中接收并显示图像。

2.定义公共相机接口类

3.定义海康相机类

4.定义线程类

        4.1里面包含:接收海康相机的函数,在主函数中可以直接调用线程里面的这个函数,并通过指针传参。

        4.2定义run函数,在函数里面采集图像,并发送信号。

         4.3定义if语句判断线程状态,控制线程启停。

        4.4定义bool变量去结合if进行判断

5.定义日志类

6.定义加载保存参数,公共结构体类

7.定义其它图像处理功能类

        7.1例如:测量,匹配,检测等...............


1.主目录框架

列表中含有:

1.src里面是图像处理的各种模块功能以及公共文件(日志和参数加载)

2.相机的公共接口类

3.Halcon类

4.海康相机类

5.主函数

6.线程类

include文件

lib文件

realse文件

.pro目录

INCLUDEPATH += $$PWD/include/Hik_IncludesLIBS += -L$$PWD/lib/Hik_Libs/ -lMvCameraControl

声明

#include\"camerainterface.h\"#include\"MvCameraControl.h\"//海康相机#include \"HalconCpp.h\"#include \"HDevThread.h\"#include using namespace HalconCpp;

2.定义公共相机接口(camerainterface)

camerainterface.h

#ifndef CAMERAINTERFACE_H#define CAMERAINTERFACE_H#include \"HalconCpp.h\"#include \"HDevThread.h\"using namespace HalconCpp;#include\"iostream\"class CameraInterface{public: CameraInterface(); ~CameraInterface(); //关闭相机采集 // ch:连接设备 virtual int connectCamera(int id)=0; //设置是否为触发模式 virtual int setTriggerMode(unsigned int TriggerModeNum)=0; //开启相机采集 virtual int startCamera()=0; virtual int stopCamera()=0; //关闭相机 virtual int closeCamera()=0; //软触发 virtual int softTrigger()=0; //读取buffer virtual int ReadBuffer(HObject &image)=0; //设置图像高度 virtual int setHeight(unsigned int height)=0; //设置图像ROI宽度 virtual int setWidth(unsigned int width)=0; //获取图像高度值 virtual int getHeight()=0; //获取图像宽度值 virtual int getWidth()=0; //获取相机曝光时间 virtual float getExposureTime()=0; //设置图像水平偏移OffsetX virtual int setOffsetX(unsigned int offsetX)=0; //设置图像竖直偏移OffsetY virtual int setOffsetY(unsigned int offsetY)=0; //设置触发源 virtual int setTriggerSource(unsigned int TriggerSourceNum)=0; //设置帧率控制使能 virtual int setFrameRateEnable(bool comm)=0; //设置心跳时间 virtual int setHeartBeatTime(unsigned int time)=0; //设置曝光时间 virtual int setExposureTime(float ExposureTimeNum)=0; //设置增益 virtual int setGain(float Gain)=0; //关闭自动曝光 virtual int setExposureAuto(bool exposureAutoFlag)=0; //关闭自动增益 virtual int setGainAuto(bool gainAutoFlag)=0; //virtual int setGain(float Gain)=0; //清理相机缓存 virtual void clearBuffer()=0;};#endif // CAMERAINTERFACE_H

3.定义海康相机类(hikvisionsdk)

1.hikvisionsdk.h文件,海康相机功能函数声明(包含公共相机头文件)

#ifndef HIKVISIONSDK_H#define HIKVISIONSDK_H#include\"camerainterface.h\"#include\"MvCameraControl.h\"#include \"HalconCpp.h\"#include \"HDevThread.h\"#include using namespace HalconCpp;class HikvisionSDK:public CameraInterface{public: HikvisionSDK(); ~HikvisionSDK(); // ch:连接设备 //int connectCamera(std::string id); int connectCamera(int id); //设置是否为触发模式 int setTriggerMode(unsigned int TriggerModeNum); //开启相机采集 int startCamera(); //关闭相机采集 int stopCamera(); //关闭相机 int closeCamera(); //软触发 int softTrigger(); //读取buffer int ReadBuffer(HObject &image); //设置图像高度 int setHeight(unsigned int height); //设置图像ROI宽度 int setWidth(unsigned int width); //获取图像高度值 int getHeight(); //获取图像宽度值 int getWidth(); //获取相机曝光时间 float getExposureTime(); //设置图像水平偏移OffsetX int setOffsetX(unsigned int offsetX); //设置图像竖直偏移OffsetY int setOffsetY(unsigned int offsetY); //设置触发源 int setTriggerSource(unsigned int TriggerSourceNum); //设置帧率控制使能 int setFrameRateEnable(bool comm); //设置心跳时间 int setHeartBeatTime(unsigned int time); //设置曝光时间 int setExposureTime(float ExposureTimeNum); //设置增益 int setGain(float Gain); //关闭自动曝光 int setExposureAuto(bool exposureAutoFlag); //关闭自动增益 int setGainAuto(bool gainAutoFlag); //清理相机缓存 void clearBuffer(); bool QImage2HObject(QImage &qImg, HObject &hImg);private: void* m_hDevHandle;public: // 用于保存图像的缓存 unsigned int m_nBufSizeForSaveImage; // 用于从驱动获取图像的缓存 unsigned int m_nBufSizeForDriver;};#endif // HIKVISIONSDK_H

2.hikvisionsdk.cpp文件(海康相机各功能实现)

在读图相机中图像函数里面有个事件,此时需要找到自己相机的型号才能执行,要不然程序容易闪退

#include \"hikvisionsdk.h\"MV_CC_DEVICE_INFO_LIST m_stDevList; // ch:设备信息列表结构体变量,用来存储设备列表MV_CC_DEVICE_INFO* m_Device=NULL;  //设备对象#include #include #include HikvisionSDK::HikvisionSDK(){ m_hDevHandle = NULL;}HikvisionSDK::~HikvisionSDK(){ if (m_hDevHandle) { MV_CC_DestroyHandle(m_hDevHandle); m_hDevHandle = NULL; }}//连接相机int HikvisionSDK::connectCamera(int id){ // Enum device MV_CC_DEVICE_INFO_LIST stDeviceList; memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST)); int nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList); if (nRet!=0) { qDebug()<<\"nRet:=\"< 0) { for (unsigned int i = 0; i < stDeviceList.nDeviceNum; i++) { MV_CC_DEVICE_INFO* pDeviceInfo = stDeviceList.pDeviceInfo[i]; if (NULL == pDeviceInfo) { break; } } } else { return -1; } unsigned int nIndex = 0; // Select device and create handle nRet = MV_CC_CreateHandle(&m_hDevHandle, stDeviceList.pDeviceInfo[nIndex]); if (nRet!=0) { //printf(\"Create Handle fail! nRet [0x%x]\\n\", nRet); return -1; } // open device nRet = MV_CC_OpenDevice(m_hDevHandle); if (nRet!=0) { //printf(\"Open Device fail! nRet [0x%x]\\n\", nRet); return -1; } return 0;}//启动相机采集int HikvisionSDK::startCamera(){ int tempValue=MV_CC_StartGrabbing(m_hDevHandle); if(tempValue!=0) { return -1; }else { return 0; }}//停止相机采集int HikvisionSDK::stopCamera(){ int tempValue=MV_CC_StopGrabbing(m_hDevHandle); if(tempValue!=0) { return -1; }else { return 0; }}//关闭相机int HikvisionSDK::closeCamera(){ if (NULL == m_hDevHandle) { return -1; } MV_CC_CloseDevice(m_hDevHandle); int tempValue = MV_CC_DestroyHandle(m_hDevHandle); m_hDevHandle = NULL; if(tempValue!=0) { return -1; }else { return 0; }}//发送软触发int HikvisionSDK::softTrigger(){ int tempValue= MV_CC_SetCommandValue(m_hDevHandle, \"TriggerSoftware\"); if(tempValue!=0) { return -1; }else { return 0; }}//读取相机中的图像int HikvisionSDK::ReadBuffer(HObject &halconImage){ //Mat* getImage=new Mat(); unsigned int nRecvBufSize = 0; MVCC_INTVALUE stParam; qDebug()<<\"enter3\"; memset(&stParam, 0, sizeof(MVCC_INTVALUE)); int tempValue = MV_CC_GetIntValue(m_hDevHandle, \"PayloadSize\", &stParam); qDebug()<<\"enter4\"; if (tempValue != 0) { return -1; } //分配一个指针的内存大小 , c语言的库函数 malloc; nRecvBufSize = stParam.nCurValue; //指针 图像接收数据的指针 unsigned char* pDate; pDate=(unsigned char *)malloc(nRecvBufSize); qDebug()<<\"enter41\"; //句柄 指针 nRecvBufSize 700 , 输出 (指针和图像信息的结构体)stImageInfo。 MV_FRAME_OUT_INFO_EX stImageInfo = {0}; tempValue= MV_CC_GetOneFrameTimeout(m_hDevHandle, pDate, nRecvBufSize, &stImageInfo, 700); if(tempValue!=0) { return -1; }// m_nBufSizeForSaveImage = stImageInfo.nWidth * stImageInfo.nHeight * 3 + 2048;// unsigned char* m_pBufForSaveImage;// m_pBufForSaveImage = (unsigned char*)malloc(m_nBufSizeForSaveImage); qDebug()<<\"enter42\"; bool isMono; //HObject halconImage; //stImageInfo.enPixelType //像素格式 的 stImageInfo ,switch 调整, switch (stImageInfo.enPixelType) { case PixelType_Gvsp_Mono8: case PixelType_Gvsp_Mono10: case PixelType_Gvsp_Mono10_Packed: case PixelType_Gvsp_Mono12: case PixelType_Gvsp_Mono12_Packed: case 17301512: isMono=true; break; default: isMono=false; break; } if(isMono) { //*getImage=Mat(stImageInfo.nHeight,stImageInfo.nWidth,CV_8UC1,pDate); //imwrite(\"d:\\\\测试opencv_Mono.tif\", image); qDebug()<<\" stImageInfo.nHeight:\"<< stImageInfo.nHeight; qDebug()<<\" stImageInfo.nWidth:\"<< stImageInfo.nWidth; qDebug()<<\"pDate:\"<<pDate; GenImage1(&halconImage, \"byte\", stImageInfo.nWidth,stImageInfo.nHeight,(Hlong)(pDate));//转换为hoject// GenImage1(&hImg, \"byte\", tFrameInfo.iWidth, tFrameInfo.iHeight, (Hlong)m_pchImgBuffer[camId]);// qDebug()<<\"pDate11:\"<<pDate; //WriteImage(halconImage, \"png\", 0, \"./picture/halcon_Mono.png\"); } else { //转换图像格式为BGR8 MV_CC_PIXEL_CONVERT_PARAM stConvertParam = {0}; memset(&stConvertParam, 0, sizeof(MV_CC_PIXEL_CONVERT_PARAM)); stConvertParam.nWidth = stImageInfo.nWidth;  //ch:图像宽 | en:image width stConvertParam.nHeight = stImageInfo.nHeight;  //ch:图像高 | en:image height //stConvertParam.pSrcData = m_pBufForDriver;  //ch:输入数据缓存 | en:input data buffer stConvertParam.pSrcData = pDate;  //ch:输入数据缓存 | en:input data buffer stConvertParam.nSrcDataLen = stImageInfo.nFrameLen; //ch:输入数据大小 | en:input data size stConvertParam.enSrcPixelType = stImageInfo.enPixelType; //ch:输入像素格式 | en:input pixel format stConvertParam.enDstPixelType = PixelType_Gvsp_BGR8_Packed; //ch:输出像素格式 | en:output pixel format 适用于OPENCV的图像格式 //stConvertParam.enDstPixelType = PixelType_Gvsp_RGB8_Packed; //ch:输出像素格式 | en:output pixel format //stConvertParam.pDstBuffer = m_pBufForSaveImage;  //ch:输出数据缓存 | en:output data buffer stConvertParam.nDstBufferSize = m_nBufSizeForSaveImage; //ch:输出缓存大小 | en:output buffer size MV_CC_ConvertPixelType(m_hDevHandle, &stConvertParam); QImage img = QImage((const uchar*)pDate, stImageInfo.nWidth,stImageInfo.nHeight, QImage::Format_RGB888); QImage2HObject(img, halconImage); //QImage2HObject(img, hImg); //halconImage 输出 rgb hobject 格式的图像 。 //因为 这里没有 图片 输出 所以 代码就奔溃了。 //*getImage=Mat(stImageInfo.nHeight,stImageInfo.nWidth,CV_8UC3,m_pBufForSaveImage); //imwrite(\"d:\\\\测试opencv_Color.tif\", image); } //CopyImage(halconImage, &image); free(pDate); //free(m_pBufForSaveImage); return 0;}//Qimage 转换成 hobject imagebool HikvisionSDK::QImage2HObject(QImage &qImg, HObject &hImg){ try { if (qImg.isNull()) return false; int width = qImg.width(); int height = qImg.height(); QImage::Format format = qImg.format(); if (format == QImage::Format_RGB32 || format == QImage::Format_ARGB32 || format == QImage::Format_ARGB32_Premultiplied) { GenImageInterleaved(&hImg, Hlong(qImg.bits()), \"bgrx\", width, height, 0, \"byte\", width, height, 0, 0, 8, 0); } else if (format == QImage::Format_RGB888) { GenImageInterleaved(&hImg, Hlong(qImg.bits()), \"bgr\", width, height, 0, \"byte\", width, height, 0, 0, 8, 0); } else if (format == QImage::Format_Grayscale8 || format == QImage::Format_Indexed8) { GenImage1Extern(&hImg, \"byte\", width, height, Hlong(qImg.bits()), NULL); } } catch (const std::exception&) { return false; } return true;}//获取图像高度值int HikvisionSDK::getHeight(){ MVCC_INTVALUE stParam; memset(&stParam, 0, sizeof(MVCC_INTVALUE)); int tempValue=MV_CC_GetIntValue(m_hDevHandle, \"Height\", &stParam); int value= stParam.nCurValue; if(tempValue!=0) { return -1; }else { return value; }}//获取图像宽度值int HikvisionSDK::getWidth(){ MVCC_INTVALUE stParam; memset(&stParam, 0, sizeof(MVCC_INTVALUE)); int tempValue=MV_CC_GetIntValue(m_hDevHandle, \"Width\", &stParam); int value= stParam.nCurValue; if(tempValue!=0) { return -1; }else { return value; }}//获取相机曝光时间float HikvisionSDK::getExposureTime(){ MVCC_FLOATVALUE stParam; memset(&stParam, 0, sizeof(MVCC_INTVALUE)); int tempValue=MV_CC_GetFloatValue(m_hDevHandle, \"ExposureTime\", &stParam); float value= stParam.fCurValue; if(tempValue!=0) { return -1; }else { return value; }}//设置图像ROI高度int HikvisionSDK::setHeight(unsigned int height){ int tempValue=MV_CC_SetIntValue(m_hDevHandle, \"Height\", height); if(tempValue!=0) { return -1; } else { return 0; }}//设置图像ROI宽度int HikvisionSDK::setWidth(unsigned int width){ int tempValue=MV_CC_SetIntValue(m_hDevHandle, \"Width\", width); if(tempValue!=0) { return -1; } else { return 0; }}//设置图像水平偏移OffsetXint HikvisionSDK::setOffsetX(unsigned int offsetX){ int tempValue=MV_CC_SetIntValue(m_hDevHandle, \"OffsetX\", offsetX); if(tempValue!=0) { return -1; } else { return 0; }}//设置图像竖直偏移OffsetYint HikvisionSDK::setOffsetY(unsigned int offsetY){ int tempValue=MV_CC_SetIntValue(m_hDevHandle, \"OffsetY\", offsetY); if(tempValue!=0) { return -1; } else { return 0; }}//设置是否为触发模式int HikvisionSDK::setTriggerMode(unsigned int TriggerModeNum){ //0:Off 1:On int tempValue= MV_CC_SetEnumValue(m_hDevHandle,\"TriggerMode\", TriggerModeNum); if(tempValue!=0) { return -1; }else { return 0; }}//设置触发源int HikvisionSDK::setTriggerSource(unsigned int TriggerSourceNum){ //0:Line0 1:Line1 7:Software int tempValue= MV_CC_SetEnumValue(m_hDevHandle,\"TriggerSource\", TriggerSourceNum); if(tempValue!=0) { return -1; }else { return 0; }}//设置帧率控制使能int HikvisionSDK::setFrameRateEnable(bool comm){ int tempValue =MV_CC_SetBoolValue(m_hDevHandle, \"AcquisitionFrameRateEnable\", comm); if (tempValue != 0) { return -1; } else { return 0; }}//设置心跳时间int HikvisionSDK::setHeartBeatTime(unsigned int time){ //心跳时间最小为500ms if(time<500) time=500; int tempValue=MV_CC_SetIntValue(m_hDevHandle, \"GevHeartbeatTimeout\", time); if(tempValue!=0) { return -1; } else { return 0; }}//设置曝光时间int HikvisionSDK::setExposureTime(float ExposureTimeNum){ int tempValue= MV_CC_SetFloatValue(m_hDevHandle, \"ExposureTime\",ExposureTimeNum ); if(tempValue!=0) { return -1; } else { return 0; }}//设置曝光时间int HikvisionSDK::setGain(float Gain){ int tempValue= MV_CC_SetFloatValue(m_hDevHandle, \"Gain\",Gain); if(tempValue!=0) { return -1; } else { return 0; }}//关闭自动曝光int HikvisionSDK::setExposureAuto(bool exposureAutoFlag){ int tempValue= MV_CC_SetEnumValue(m_hDevHandle,\"ExposureAuto\", exposureAutoFlag); if (tempValue != 0) { return -1; } else { return 0; }}//关闭自动增益int HikvisionSDK::setGainAuto(bool gainAutoFlag){ int tempValue= MV_CC_SetEnumValue(m_hDevHandle,\"GainAuto\", gainAutoFlag); if (tempValue != 0) { return -1; } else { return 0; }}//清理相机缓存void HikvisionSDK::clearBuffer(){ //stopCamera(); //startCamera();}

4.在主程序相机实例化

1.首先包含公共相机和海康相机的头文件

2.用公共相机接口去实例化海康相机

.h主文件

private: //相机指针 CameraInterface * camera=NULL;

.cpp主文件

 camera=new HikvisionSDK();用公共相机接口实例化海康相机类

析构函数中

 if(camera!=NULL) { delete camera; camera=NULL; }

5.连接相机

1.在IU界面下添加连接相机按钮转到槽函数

//连接相机void MainWindow::on_btn_Connect_clicked(){ //初始化相机句柄 if(camera!=NULL) { delete camera; camera=NULL; } qDebug()<<111; if(camera==NULL) { qDebug()<btn_Close->setEnabled(false); ui->btn_Connect->setEnabled(false); ui->btn_Trigger->setEnabled(true); ui->lxcj->setEnabled(true); ui->StopAcquisition->setEnabled(true); }}

2.连接相机函数实现

注意:次函数是实例化具体的相机(因为在项目中可能用到不同类型的相机,所以在头文件首先用公共相机接口)然后在具体的连接相机下面去实例化具体的相机类型对象。

  最后一行程序,是把这个具体的海康相机对象通过传参,传入到线程类中去。

void MainWindow::InitCam(){ camera=new HikvisionSDK();此时用到了上面提到的海康相机实例化 //连接相机 //std::cout<<\"Connect: \"<connectCamera(1)<connectCamera(1); if(ret!=0) { //失败 //QMessageBox::warning() } //设置为触发模式 打开 std::cout<<\"TriggerMode: \"<setTriggerMode(1)<<std::endl; //设置触发源为软触发 std::cout<<\"TriggerSource: \"<setTriggerSource(7)<<std::endl; //设置曝光时间 std::cout<<\"SetExposureTime: \"<setExposureTime(40000)<<std::endl; //开启相机采集 std::cout<<\"StartCamera: \"<startCamera()<getCameraPtr(camera);//把实例化后的海康相机类传入到线程中去 //myThread->getImagePtr(myImage); }

6.定义线程类(mythread)

1.在线程里面需要包含公共相机的头文件

#include \"QThread\"//线程#include \"camerainterface.h\"//公共相机接口#include 

2.头文件定义接收海康相机类的函数

 void getCameraPtr(CameraInterface* camera);

3..cpp文件具体实现

//析构函数MyThread::~MyThread(){ if(cameraPtr==NULL) { delete cameraPtr; }}//具体实现void MyThread::getCameraPtr(CameraInterface *camera){ cameraPtr=camera;}

7.单次采集

1.在IU界面添加单次采集按钮转跳槽函数

2.需要在主头文件中,private: 下面去声明 bool IsRun = false;(目的是为了更好的调节相机采图启停,方便后续操作(在这里可以不用))

3.转到线程中,去执行停止线程工作内容(因为单次采集不需要启动线程)

//单次采集void MainWindow::on_btn_Trigger_clicked(){ HObject image; HTuple hv_Width,hv_Height; IsRun =true;//单次采图状态  myThread->ChangeCloseStatus();//线程状态启停 std::cout<<\"TriggerMode: \"<setTriggerMode(1)<<std::endl; std::cout<<\"SoftTrigger: \"<softTrigger()<<std::endl; //读取Mat格式的图像 qDebug()<ReadBuffer(image); //相机类里面的读图函数 CopyImage(image, &halconImage); if(ui->checkBox_saveImage->isChecked()) {  //保存图像 QString path=\"./data/\"+QString::number(ui->sB_Num->value())+\".png\"; WriteImage(halconImage, \"png\", 0, HTuple(path.toLatin1().data())); } GetImageSize(image, &hv_Width, &hv_Height);  SetPart(WindowHandle, 0, 0, hv_Height,hv_Width); // 1944 2592 qDebug()<OutMeasure01(halconImage);}

4.在线程类中,.h的public:下定义 bool Status=false;

同时定义线程状态启停函数

 void ChangeCloseStatus();//关闭 void ChangeOpenStatus();//打开.cpp文件void MyThread::ChangeCloseStatus(){ Status=false; //qDebug()<<\"Status:=\"<<Status;}void MyThread::ChangeOpenStatus(){ Status=true; //qDebug()<<\"Status:=\"<<Status;}


8.连续采集

1.此时需要利用线程进行连续图像采集,需要在主程序中实例化线程类(应该在一开始就实例化)

 //线程对象 MyThread* myThread=NULL;
 // 线程对象实例化 myThread = new MyThread();
 if(myThread!=NULL) { delete myThread; myThread=NULL; }

2.在IU界面上添加连续采集按钮转到槽函数

void MainWindow::on_lxcj_clicked(){ std::cout<<\"TriggerMode: \"<setTriggerMode(0)<ChangeOpenStatus();//打开线程工作内容 if(!IsRun)//判断单次采集是否打开 { IsRun = false;关闭单次采集 myThread->start();//开启连续彩图线程  } else { IsRun = false;//关闭单次采集 myThread->start();//开启连续彩图线程 }}

3.在线程类里面

.h文件

 void run();//定义run函数(线程里的工作内容) void display( HObject imagePtr);//(用来其它作用显示)signals: void CaptureImage(HObject);//定义一个发送图像的信号

.cpp文件

void MyThread::run(){ if(cameraPtr==NULL) { return; } while(!isInterruptionRequested()) { if(Status) //判断是否停止的状态 {  qDebug()<<\"thread current\" <<currentThread();  std::cout<<\"Thread_Trigger:\"<softTrigger()<ReadBuffer(image);  emit CaptureImage(image);//发送图像信号  msleep(100);  } }}
void MyThread::display( HObject imagePtr){ //qDebug()<<\"Enter2\"; //std::cout<<\"so\"<sB_Num->value(); //ui->sB_Num->setValue(num+1);}

4.在线程中发送图像信号之后,需要在主函数中去接收这个图像信号

 //信号与槽 connect(myThread,SIGNAL(CaptureImage(HObject)),this,SLOT(ImageProcess01(HObject)),\\ Qt::BlockingQueuedConnection);//信号槽函数 。必须display 是slot
private slots: //显示连续图像,接收槽函数 void ImageProcess01(HObject image); //信号槽函数 --收到图像之后的 图像处理槽函数
//槽函数接收显示图像void MainWindow::ImageProcess01(HObject halconImage){ HTuple hv_Width,hv_Height; qDebug()<OutMeasure01(halconImage); //输出一个宽度 //tuple -length ,length ==1 识别 成功 //TCP 服务器 发给客户端 ,一个字符串。 myThread->ChangeOpenStatus();//采图 收到图像处理完的信号,可以启动继续采图。同步采集! qDebug()<<\"Enter2\";}

9.停止采集

void MainWindow::on_StopAcquisition_clicked(){ myThread->ChangeCloseStatus();//停止线程状态 ui->btn_Close->setEnabled(true); if(IsRun) { myThread->requestInterruption(); myThread->wait();//线程等待 IsRun =false;//单次采集关闭 // camera->stopCamera(); // camera->closeCamera(); }}

10.关闭相机

void MainWindow::on_btn_Close_clicked(){ ui->btn_Trigger->setEnabled(false); ui->lxcj->setEnabled(false); ui->StopAcquisition->setEnabled(false); if(camera!=NULL) { myThread->requestInterruption(); camera->closeCamera(); } //ui->Image_Label->clear(); ui->btn_Connect->setEnabled(true);}

11.保存图像

void MainWindow::on_saveImage_clicked(){ QString filePath =\"./data/picture/\"+ QDateTime::currentDateTime().toString(\"yyyy-MM-dd\"); HTuple file1=HTuple(filePath.toStdString().c_str()); WriteImage(halconImage, \"bmp\", 0, file1); //ui->textBrowser_log->append(\"write image success.\");}

12.设置曝光、增益

//曝光void MainWindow::on_pB_exposTime_clicked(){ int exposTime=ui->sB_exposure->value(); int ret=camera->setExposureTime(exposTime); qDebug()<<\"ret:=\"<sB_Gain->value(); int ret=camera->setGain(Gain); qDebug()<<\"ret:=\"<<ret;}

13.保存参数

//把界面的参数 固化 到 本地文件void Measure01::on_pB_saveParameters_clicked(){ /* AmplitudeThreshold = 23; RoiWidthLen = 67; Alpha1 = 3.4; LineRowStart = 879.281; LineColumnStart = 1436.34; LineRowEnd = 1769.58; LineColumnEnd = 3055.55; */ //把界面的参数 赋值 给局部作用域的变量 MeasureParam01.AmplitudeThreshold=ui->SpinBox_AmpThre->value(); MeasureParam01.Alpha1=ui->SpinBox_Alpha1->value(); MeasureParam01.RoiWidthLen=ui->SpinBox_RoiWidthLen->value(); MeasureParam01.LineRowStart=ui->SpinBox_LineRowStart->value(); MeasureParam01.LineColumnStart=ui->SpinBox_LineColumnStart->value(); MeasureParam01.LineRowEnd=ui->SpinBox_LineRowEnd->value(); MeasureParam01.LineColumnEnd=ui->SpinBox_LineColumnEnd->value(); //再通过qsetting的方法 把参数保存到qt 本地的 文件中去 SaveSetting(CONFIG_FILEPATH,\"Measure01\",\"AmplitudeThreshold\",\\ QVariant(MeasureParam01.AmplitudeThreshold));//AmpThre SaveSetting(CONFIG_FILEPATH,\"Measure01\",\"Alpha1\",\\ QVariant(MeasureParam01.Alpha1));//AmpThre SaveSetting(CONFIG_FILEPATH,\"Measure01\",\"RoiWidthLen\",\\ QVariant(MeasureParam01.RoiWidthLen));//AmpThre SaveSetting(CONFIG_FILEPATH,\"Measure01\",\"LineRowStart\",\\ QVariant(MeasureParam01.LineRowStart));//AmpThre SaveSetting(CONFIG_FILEPATH,\"Measure01\",\"LineColumnStart\",\\ QVariant(MeasureParam01.LineColumnStart));//AmpThre SaveSetting(CONFIG_FILEPATH,\"Measure01\",\"LineRowEnd\",\\ QVariant(MeasureParam01.LineRowEnd));//AmpThre SaveSetting(CONFIG_FILEPATH,\"Measure01\",\"LineColumnEnd\",\\ QVariant(MeasureParam01.LineColumnEnd));//AmpThre}

14.加载参数

构造函数里面

 // //把界面的参数 赋值 给局部作用域的变量 //double AmpThre=ui->SpinBox_AmpThre->value(); //再通过qsetting的方法 把参数保存到qt 本地的 文件中去 //SaveSetting(CONFIG_FILEPATH,\"Measure01\",\"AmplitudeThreshold\",QVariant(AmpThre));//AmpThre QVariant ValueAmpThre; QVariant ValueAlpha1; QVariant ValueRoiWidthLen; QVariant ValueRowStart; QVariant ValueColumnStart; QVariant ValueRowEnd; QVariant ValueColumnEnd; LoadSetting(CONFIG_FILEPATH,\"Measure01\",\"AmplitudeThreshold\",ValueAmpThre); LoadSetting(CONFIG_FILEPATH,\"Measure01\",\"Alpha1\",ValueAlpha1);//AmpThre LoadSetting(CONFIG_FILEPATH,\"Measure01\",\"RoiWidthLen\",ValueRoiWidthLen);//AmpThre LoadSetting(CONFIG_FILEPATH,\"Measure01\",\"LineRowStart\",ValueRowStart);//AmpThre LoadSetting(CONFIG_FILEPATH,\"Measure01\",\"LineColumnStart\",ValueColumnStart);//AmpThre LoadSetting(CONFIG_FILEPATH,\"Measure01\",\"LineRowEnd\",ValueRowEnd);//AmpThre LoadSetting(CONFIG_FILEPATH,\"Measure01\",\"LineColumnEnd\",ValueColumnEnd);//AmpThre //把QVariant 类型 转换 double 类型 MeasureParam01.AmplitudeThreshold=ValueAmpThre.toDouble(); MeasureParam01.Alpha1=ValueAlpha1.toDouble(); MeasureParam01.RoiWidthLen=ValueRoiWidthLen.toDouble(); MeasureParam01.LineRowStart=ValueRowStart.toDouble(); MeasureParam01.LineColumnStart=ValueColumnStart.toDouble(); MeasureParam01.LineRowEnd=ValueRowEnd.toDouble(); MeasureParam01.LineColumnEnd=ValueColumnEnd.toDouble(); ui->SpinBox_AmpThre->setValue(MeasureParam01.AmplitudeThreshold); ui->SpinBox_Alpha1->setValue(MeasureParam01.Alpha1); ui->SpinBox_RoiWidthLen->setValue(MeasureParam01.RoiWidthLen); ui->SpinBox_LineRowStart->setValue(MeasureParam01.LineRowStart); ui->SpinBox_LineColumnStart->setValue(MeasureParam01.LineColumnStart); ui->SpinBox_LineRowEnd->setValue(MeasureParam01.LineRowEnd); ui->SpinBox_LineColumnEnd->setValue(MeasureParam01.LineColumnEnd); ui->SpinBox_AmpThre->setStyleSheet(\"background-color: green\");

15.日志类(lxlog)

.h

#ifndef __LX_LOG_H__#define __LX_LOG_H__#include#include void WriteLog(QString LogType, QString str);void MessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);#endif

.cpp

#include \"lxlog.h\"#include \"paramsconfig.h\"#include #include #include #include extern QTextBrowser * g_pTb;void WriteLog(QString LogType, QString str){ //文件名 QString filePath = QString(LOG_PATH) + \'/\'+ QDateTime::currentDateTime().toString(\"yyyy-MM-dd\")+\".log\"; //时间 QString strToWrite = QDateTime::currentDateTime().toString(\"yyyy-MM-dd hh:mm:ss\"); //类型 strToWrite.append(QString(\" %1 \").arg(LogType)); //信息 strToWrite.append(QString(\"%1\").arg(str)); QFile file(filePath); file.open(QIODevice::WriteOnly | QIODevice::Append); QTextStream text_stream(&file); text_stream << strToWrite <append(strToWrite);}void MessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg){ QString txtMessage = \"\"; QString messageType = \"\"; switch (type) { case QtDebugMsg: //调试信息提示 messageType = \"Debug\"; txtMessage = QString(\"Debug: %1 (%2:%3, %4)\\n\").arg(msg).arg(context.file).arg(QString::number(context.line)).arg(context.function); break; case QtInfoMsg: messageType = \"Info\"; txtMessage = QString(\"Warning: %1 (%2:%3, %4)\\n\").arg(msg).arg(context.file).arg(QString::number(context.line)).arg(context.function); break; case QtWarningMsg: //一般的warning提示 messageType = \"Waring\"; txtMessage = QString(\"Warning: %1 (%2:%3, %4)\\n\").arg(msg).arg(context.file).arg(QString::number(context.line)).arg(context.function); break; case QtCriticalMsg: //严重错误提示 messageType = \"Critical\"; txtMessage = QString(\"Critical: %1 (%2:%3, %4)\\n\").arg(msg).arg(context.file).arg(QString::number(context.line)).arg(context.function); //PostErrorMessage(txtMessage, messageType); break; case QtFatalMsg: //致命错误提示 messageType = \"Fatal\"; txtMessage = QString(\"Fatal: %1 (%2:%3, %4)\\n\").arg(msg).arg(context.file).arg(QString::number(context.line)).arg(context.function); abort(); } WriteLog(txtMessage, messageType);}


16.公共参数、结构体类(paramsconfig)

.h

#ifndef PARAMSCONFIG_H#define PARAMSCONFIG_H#include #include #define SYS_CONFIG_FILE\"./data/sysConfig/params.ini\"#define USER_CONFIG_PATH\"./data/userConfig\"#define LOG_PATH\"./data/log\"#define TRAIN_FILEPATH  \"./data/train\"#define CALIB_DATA_PATH \"data/calib\"#define IMG_DEPETH_FILEPATH \"data/imageDepth\"#define IMG_RAW_FILEPATH \"data/imageRaw\"#define MODEL_FILEPATH  \"data/model\"#define SENCE_FILEPATH  \"data/sence\"#define CONFIG_FILEPATH \"data/config/params.ini\"#define CONFIG_Main_FILEPAT \"data/config/my.ini\"#define CONFIG_Face_FILEPAT \"data/config/Face.ini\"#define CONFIG_Box_FILEPAT \"data/config/Box.ini\"#define CONFIG_CreatModel_FILEPAT \"data/config/CreatModel.ini\"#define POSE_TO_HTUPLE(pose, hTuple) {hTuple[0] = pose.x; hTuple[1] = pose.y; hTuple[2] = pose.z; hTuple[3] = pose.rx; hTuple[4] = pose.ry; hTuple[5] = pose.rz; hTuple[6] = 0.0;}#define HTUPLE_TO_POSE(hTuple, pose) {pose.x = hTuple[0]; pose.y = hTuple[1]; pose.z = hTuple[2]; pose.rx = hTuple[3]; pose.ry = hTuple[4]; pose.rz = hTuple[5];}#define KD_PI 3.141592653#define LENGTH_UNIT \"mm\"#define LX_STATIONS_NUM 3 // 相机数量#include \"HalconCpp.h\"using namespace HalconCpp;/** * measure */typedef struct{ double AmplitudeThreshold; double RoiWidthLen; double Alpha1; double LineRowStart; double LineColumnStart; double LineRowEnd; double LineColumnEnd;}MeasureParam;/** * pose */typedef struct { double x; ///X偏移 double y; ///Y偏移 double z; ///Z偏移 double rx; ///X旋转 double ry; ///Y旋转 double rz; ///Z旋转 int type; ///姿态类型} KD_POSE;/** * point select */typedef struct { double xMin; ///X范围 double xMax; ///X范围 double yMin; ///Y范围 double yMax; ///Y范围 double zMin; ///Z范围 double zMax; ///Z范围 int type; ///备用} KD_POINT_SELECT;/** * 机械臂工具类型 */typedef enum { ROT_TOOL_SUCKER = 0,  ///吸盘 ROT_POSE_GRIPPER_PNEUMATIC, ///夹具气动 ROT_POSE_GRIPPER_ELECTRIC,  ///夹具电动}ROT_TOOL_TYPE;/** * 三维点云控制参数 */typedef struct { KD_POSE calibPose;///校正Pose KD_POINT_SELECT potSelc; ///范围限定} KD_3D_CTRL; ///三维控制参数/** * 三维物体参数 */typedef struct { KD_POSE * pObjChangePose;  ///偏移pose unsigned int surfaceNum; ///面数 double objGuideHigh;  ///物体抓取引导高度} KD_OBJECT_CTRL; ///三维控制参数/** * 3d匹配参数 */typedef struct { double objectMaxLength;  ///物体最大长度 double sampleDis; ///采样距离 double keyPotFraction;  ///特征点最小得分 double minScore; ///最小得分 QString * modelFileName; ///模型文件名 KD_POSE toolInFlangeCenter; ///工具在法兰盘中心(由机械臂标定得出) KD_POSE camInBase;///相机在基础 (由halcon手眼标定得出) KD_POSE toolInObj;///工具在物体 (由halcon手眼标定得出) KD_3D_CTRL bgInfo;///背景抽取参数} KD_SURFACE_MATCH_CTRL;/** * 机械臂参数 */typedef struct { int speed; ///速度(测试用) double jointVelc; ///角速度 double jointAcc; ///角加速度 double lineVelc; ///线速度 double lineAcc; ///线加速度 int colliClass; ///防撞等级 KD_POSE toolInFlangeCenter; ///工具在法兰盘中心} KD_ROBOT_CTRL;/** * 机械臂码垛参数 */typedef struct { KD_POSE oriPose; ///起始码垛姿态 KD_POSE offsetPose;  ///偏移码垛姿态 int palletNum; ///码垛数量 double palletSize;///工件尺寸} KD_ROBOT_PALLET_CTRL;/** * 机械臂运动参数 */typedef struct { double doorHigh; ///门型高度 int ioId; ///吸盘、夹具IO口 int moveTime; ///机械臂从抓取到放置位置延时时间 int doorUpDownTime;  ///门型上下移动延时时间 int suctionTime; ///吸盘、夹具延时时间 KD_POSE halfWayPose;  ///中途路点 KD_ROBOT_PALLET_CTRL pallet; ///码垛参数 ROT_TOOL_TYPE toolType;  ///工具类型} KD_ROBOT_MOVE_CTRL;typedef enum { UNINIT,//还未初始化 RUNNING,//运行 STOP//停止}PROGRAM_STATUS;/*** DO输出0*/typedef enum { KEY_RELEASE = 0, KEY1 = 1, KEY2 = 2, KEY3 = 4, KEYS = 8, KEYU = 16, KEYD = 32}HC_KEY_TYPE;/*** DO输出1*/typedef enum { DO_NONE = 0, DO_GUIDE1 = 1,// 推进 DO_GUIDE2 = 2, // 推出 DO_BUZZER = 4, DO_LIGHT = 8, DO_BACKUP1 = 16, DO_BACKUP2 = 32}HC_DO_TYPE;/*** DI输入*/typedef enum { DI_GUIDE1 = 1,// 推进状态 DI_GUIDE2 = 2, // 推出状态 DI_START = 4, DI_RESET = 8, DI_STOP = 16, DI_BACKUP = 32}HC_DI_TYPE;/** * 矩形 */typedef struct { int x; int y; int w; int h;} LX_RECT;/** * 识别参数 */typedef struct { LX_RECT roiRect;  ///ROI区域 int erosionVal;  ///腐蚀参数 int dilationVal;  ///膨胀参数 int noiseArea;///噪声面积(小于该面积都被认为是噪声) int decimalPointArea;///小数点面积 double confidence;///最低置信率 QString trainFile;///训练文件 QString usrconfigFile;///测试项目配置文件} LX_RECOGNISE_CTRL;//LX_RECOGNISE_CTRL LX_RECOGNISE_CTRL1;//LX_RECOGNISE_CTRL LX_RECOGNISE_CTRL2;/** * 相机参数 */typedef struct { int exposureTime; int exposureTimeMin; int exposureTimeMax; int gain; int gainMin; int gainMax;// bool bMiroH;// bool bMiroV;} LX_CAMERA_CTRL;/** * io */typedef struct { QString key1Do;//io口ID QString key2Do;//io口ID QString key3Do;//io口ID QString keySDo;//io口ID QString keyUpDo;//io口ID QString keyDownDo;//io口ID QString keyBuzzerDo; //io口ID QString keyStartDi;//io口ID QString keyResetDi;//io口ID QString keyStopDi;//io口ID} LX_IO_CTRL;/** * 初始化参数 */typedef struct { int pressTime;///按下时间 QString defaultVal;  ///初始值} HC_INIT_CTRL;/** * 公英制参数 */typedef struct { int unit;///0为公制值, 1为英制} HC_METRIC_IMPERIAL_CTRL;/** * 数字缺失 */typedef struct { QString defaultVal;///预设值} HC_NUM_MISS_CTRL;/** * 记忆位 */typedef struct { int pressTime;  ///单次上升时间} HC_MEMORY_POS_CTRL;/** * 陀螺仪 */typedef struct { QString defaultVal; ///陀螺仪预设等级} HC_GYRO_CTRL;/** * 上升下降锁 */typedef struct { int pressTime;///按下时间} HC_LOCK_CTRL;/** * 异常码 *///typedef struct {// int pressTimeE05;  ///E05按下时间//}HC_EXCEPTION_CTRL;/** * 手控器检测和预设参数 */typedef struct { HC_INIT_CTRL initCtrl; HC_METRIC_IMPERIAL_CTRL metricImperialCtrl; HC_NUM_MISS_CTRL numMisCtrl; HC_MEMORY_POS_CTRL memoryPosCtrl; HC_GYRO_CTRL gyroCtrl; HC_LOCK_CTRL lockCtrl; int testItem;//测试项 int workStationId;} LX_HC_CTRL;/** *2d模板匹配的预设参数 */typedef struct { double OffsetRow; double OffsetColumn; double TPhi; double TLength1; double TLength2; int m_nModecase; // =1 HTuple ModelID; HObject ShapeModel;} LX_MATCH_CTRL;//保存加载配置void SaveSetting(QString fileName, QString group, QString key, QVariant value);void LoadSetting(QString fileName, QString group, QString key, QVariant &value);//保存加载识别配置void SaveRecogniseCtrl(QString fileName, QString group, LX_RECOGNISE_CTRL recCtrl);void LoadRecogniseCtrl(QString fileName, QString group, LX_RECOGNISE_CTRL &recCtrl);//保存加载IO配置void SaveIoCtrl(QString fileName, QString group, LX_IO_CTRL ioCtrl);void LoadIoCtrl(QString fileName, QString group, LX_IO_CTRL &ioCtrl);//保存加载相机配置void SaveCameraCtrl(QString fileName, QString group, LX_CAMERA_CTRL camCtrl);void LoadCameraCtrl(QString fileName, QString group, LX_CAMERA_CTRL &camCtrl);//保存加载手控器配置void SaveHandCtrlerCtrl(QString fileName, QString group, LX_HC_CTRL hcCtrl);void LoadHandCtrlerCtrl(QString fileName, QString group, LX_HC_CTRL &hcCtrl);//保存相机的 产品唯一序列号和工位void SaveCameraAscn(QString fileName, QString Key,QString CameraNumber );void LoadCameraAscn(QString fileName, QString Key,QString &CameraNumber );double AngleToRad(double angle);double RadToAngle(double rad);//保存posevoid SavePose(QString group, KD_POSE pose);//加载posevoid LoadPose(QString group, KD_POSE &pose);class paramsConfig{public: paramsConfig();};#endif // PARAMSCONFIG_H

.cpp

#include \"paramsconfig.h\"#include #include paramsConfig::paramsConfig(){}void SaveRecogniseCtrl(QString fileName, QString group, LX_RECOGNISE_CTRL recCtrl){}void SaveCameraCtrl(QString fileName, QString group, LX_CAMERA_CTRL camCtrl){ // 淇濆瓨鍔犺浇鐩告満閰嶇疆 SaveSetting(fileName, group, \"exposureTime\", QVariant(camCtrl.exposureTime)); SaveSetting(fileName, group, \"gain\", QVariant(camCtrl.gain)); SaveSetting(fileName, group, \"gainMin\", QVariant(camCtrl.gainMin)); SaveSetting(fileName, group, \"gainMax\", QVariant(camCtrl.gainMax)); SaveSetting(fileName, group, \"exposureTimeMin\", QVariant(camCtrl.exposureTimeMin)); SaveSetting(fileName, group, \"exposureTimeMax\", QVariant(camCtrl.exposureTimeMax));}void LoadCameraCtrl(QString fileName, QString group, LX_CAMERA_CTRL &camCtrl){ // 鍔犺浇鐩告満閰嶇疆 QVariant qexposureTime; QVariant qexposureTimeMin; QVariant qexposureTimeMax; QVariant qGain; QVariant qGainMin; QVariant qGainMax; LoadSetting(fileName, group, \"exposureTime\", qexposureTime); LoadSetting(fileName, group, \"exposureTimeMin\", qexposureTimeMin); LoadSetting(fileName, group, \"exposureTimeMax\", qexposureTimeMax); LoadSetting(fileName, group, \"gain\", qGain); LoadSetting(fileName, group, \"gainMin\", qGainMin); LoadSetting(fileName, group, \"gainMax\", qGainMax); camCtrl.exposureTime = qexposureTime.toInt(); camCtrl.exposureTimeMin = qexposureTimeMin.toInt(); camCtrl.exposureTimeMax = qexposureTimeMax.toInt(); camCtrl.gain = qGain.toInt(); camCtrl.gainMin = qGainMin.toInt(); camCtrl.gainMax = qGainMax.toInt();// qDebug()<<\"camCtrl.gain\"<<camCtrl.gain;// qDebug()<<\"camCtrl.qexposureTime:+\"<<camCtrl.exposureTime;}void SaveHandCtrlerCtrl(QString fileName, QString group, LX_HC_CTRL hcCtrl){}void LoadCameraAscn(QString fileName, QString Key, QString &CameraNumber){ QString group = \"CameraManage\"; QVariant ValueCameraNumber; LoadSetting(fileName,group,Key,ValueCameraNumber); CameraNumber = ValueCameraNumber.toString(); qDebug() << \"CameraName:= \" << CameraNumber;}void LoadSetting(QString fileName, QString group, QString key, QVariant &value){ QSettings settings(fileName,QSettings::IniFormat); if(group.size() != 0) { settings.beginGroup(group); } value = settings.value(key); if(group.size() != 0) { settings.endGroup(); }}void SaveSetting(QString fileName, QString group, QString key, QVariant value){ QSettings settings(fileName, QSettings::IniFormat); if (group.size() != 0) { settings.beginGroup(group); } settings.setValue(key, value); if (group.size() != 0) { settings.endGroup(); }}void SavePose(QString group, KD_POSE pose){}

已经看到这里了,点个赞和关注吧!

      刚开始写文章,如有不足请多多包含;之后会持续更新关于(halcon学习,VS联合编程,QT联合编程,C++,C#,Opencv图像处理库,三维点云库pcl,相机以及机器人的二次开发)等系统化学习文章。