当前位置: 首页 > article >正文

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.线程类


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;//读取buffervirtual 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;//设置图像水平偏移OffsetXvirtual int setOffsetX(unsigned int offsetX)=0;//设置图像竖直偏移OffsetYvirtual 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 <QImage>
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();//读取bufferint ReadBuffer(HObject &image);//设置图像高度int setHeight(unsigned int height);//设置图像ROI宽度int setWidth(unsigned int width);//获取图像高度值int getHeight();//获取图像宽度值int getWidth();//获取相机曝光时间float getExposureTime();//设置图像水平偏移OffsetXint setOffsetX(unsigned int offsetX);//设置图像竖直偏移OffsetYint 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 <QDebug>
#include <QString>
#include <QDebug>
HikvisionSDK::HikvisionSDK()
{m_hDevHandle    = NULL;
}HikvisionSDK::~HikvisionSDK()
{if (m_hDevHandle){MV_CC_DestroyHandle(m_hDevHandle);m_hDevHandle    = NULL;}
}//连接相机
int  HikvisionSDK::connectCamera(int id)
{// Enum deviceMV_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:="<<nRet;return -1;}if (stDeviceList.nDeviceNum > 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 handlenRet = MV_CC_CreateHandle(&m_hDevHandle, stDeviceList.pDeviceInfo[nIndex]);if (nRet!=0){//printf("Create Handle fail! nRet [0x%x]\n", nRet);return -1;}// open devicenRet = 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{//转换图像格式为BGR8MV_CC_PIXEL_CONVERT_PARAM stConvertParam = {0};memset(&stConvertParam, 0, sizeof(MV_CC_PIXEL_CONVERT_PARAM));stConvertParam.nWidth = stImageInfo.nWidth;                 //ch:图像宽 | en:image widthstConvertParam.nHeight = stImageInfo.nHeight;               //ch:图像高 | en:image height//stConvertParam.pSrcData = m_pBufForDriver;                  //ch:输入数据缓存 | en:input data bufferstConvertParam.pSrcData = pDate;                  //ch:输入数据缓存 | en:input data bufferstConvertParam.nSrcDataLen = stImageInfo.nFrameLen;         //ch:输入数据大小 | en:input data sizestConvertParam.enSrcPixelType = stImageInfo.enPixelType;    //ch:输入像素格式 | en:input pixel formatstConvertParam.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 bufferstConvertParam.nDstBufferSize = m_nBufSizeForSaveImage;            //ch:输出缓存大小 | en:output buffer sizeMV_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 image
bool 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;}
}//设置图像水平偏移OffsetX
int HikvisionSDK::setOffsetX(unsigned int offsetX)
{int tempValue=MV_CC_SetIntValue(m_hDevHandle, "OffsetX", offsetX);if(tempValue!=0){return -1;}else{return 0;}
}//设置图像竖直偏移OffsetY
int 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:Onint 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:Softwareint 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)
{//心跳时间最小为500msif(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()<<112;InitCam();//连接相机函数//控制按钮是否可以按下ui->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:  "<<camera->connectCamera(1)<<std::endl;int  ret=camera->connectCamera(1);if(ret!=0){//失败//QMessageBox::warning()}//设置为触发模式  打开std::cout<<"TriggerMode:  "<<camera->setTriggerMode(1)<<std::endl;//设置触发源为软触发std::cout<<"TriggerSource:  "<<camera->setTriggerSource(7)<<std::endl;//设置曝光时间std::cout<<"SetExposureTime:  "<<camera->setExposureTime(40000)<<std::endl;//开启相机采集std::cout<<"StartCamera:  "<<camera->startCamera()<<std::endl;myThread->getCameraPtr(camera);//把实例化后的海康相机类传入到线程中去//myThread->getImagePtr(myImage);}

6.定义线程类(mythread)

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

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

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:  "<<camera->setTriggerMode(1)<<std::endl;std::cout<<"SoftTrigger:  "<<camera->softTrigger()<<std::endl;//读取Mat格式的图像qDebug()<<"enter1";camera->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 2592qDebug()<<"enter2";DispObj(halconImage, WindowHandle);//其它图像处理功能//m_pMeasure01->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:  "<<camera->setTriggerMode(0)<<std::endl;myThread->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:"<<cameraPtr->softTrigger()<<std::endl;HObject image;//读取Mat格式的图像cameraPtr->ReadBuffer(image);emit CaptureImage(image);//发送图像信号msleep(100);}}
}
void MyThread::display( HObject imagePtr)
{//qDebug()<<"Enter2";//std::cout<<"so"<<std::endl;//判断是黑白、彩色图像DispObj((imagePtr), WindowHandle);QString path="./picture/halcon"+QString::number(1)+".png";//WriteImage((*imagePtr), "png", 0, HTuple(path.toLatin1().data()));//int num=ui->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()<<"Enter1";GetImageSize(halconImage, &hv_Width, &hv_Height);SetPart(WindowHandle, 0, 0, hv_Height,hv_Width); // 1944 2592display(halconImage);m_pMeasure01->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:="<<ret;
}//增益
void MainWindow::on_pB_setGain_clicked()
{int Gain =ui->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));//AmpThreSaveSetting(CONFIG_FILEPATH,"Measure01","Alpha1",\QVariant(MeasureParam01.Alpha1));//AmpThreSaveSetting(CONFIG_FILEPATH,"Measure01","RoiWidthLen",\QVariant(MeasureParam01.RoiWidthLen));//AmpThreSaveSetting(CONFIG_FILEPATH,"Measure01","LineRowStart",\QVariant(MeasureParam01.LineRowStart));//AmpThreSaveSetting(CONFIG_FILEPATH,"Measure01","LineColumnStart",\QVariant(MeasureParam01.LineColumnStart));//AmpThreSaveSetting(CONFIG_FILEPATH,"Measure01","LineRowEnd",\QVariant(MeasureParam01.LineRowEnd));//AmpThreSaveSetting(CONFIG_FILEPATH,"Measure01","LineColumnEnd",\QVariant(MeasureParam01.LineColumnEnd));//AmpThre}

14.加载参数

构造函数里面

 // //把界面的参数 赋值 给局部作用域的变量//double AmpThre=ui->SpinBox_AmpThre->value();//再通过qsetting的方法 把参数保存到qt 本地的 文件中去//SaveSetting(CONFIG_FILEPATH,"Measure01","AmplitudeThreshold",QVariant(AmpThre));//AmpThreQVariant 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);//AmpThreLoadSetting(CONFIG_FILEPATH,"Measure01","RoiWidthLen",ValueRoiWidthLen);//AmpThreLoadSetting(CONFIG_FILEPATH,"Measure01","LineRowStart",ValueRowStart);//AmpThreLoadSetting(CONFIG_FILEPATH,"Measure01","LineColumnStart",ValueColumnStart);//AmpThreLoadSetting(CONFIG_FILEPATH,"Measure01","LineRowEnd",ValueRowEnd);//AmpThreLoadSetting(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<QString>
#include <QTextBrowser>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 <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QTextBrowser>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 << "\r\n";file.flush();file.close();g_pTb->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 <QString>
#include <QVariant>#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;                      ///校正PoseKD_POINT_SELECT potSelc;                ///范围限定
} KD_3D_CTRL;                               ///三维控制参数/*** 三维物体参数*/
typedef struct {KD_POSE * pObjChangePose;               ///偏移poseunsigned 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口IDQString key2Do;									//io口IDQString key3Do;									//io口IDQString keySDo;									//io口IDQString keyUpDo;								//io口IDQString keyDownDo;								//io口IDQString keyBuzzerDo;                            //io口IDQString keyStartDi;								//io口IDQString keyResetDi;								//io口IDQString 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;   // =1HTuple 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);//保存pose
void SavePose(QString group, KD_POSE pose);//加载pose
void LoadPose(QString group, KD_POSE &pose);class paramsConfig
{
public:paramsConfig();
};#endif // PARAMSCONFIG_H

.cpp

#include "paramsconfig.h"
#include <QSettings>
#include <QDebug>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,相机以及机器人的二次开发)等系统化学习文章。

相关文章:

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

思路&#xff1a; 1.定义带UI界面的主函数类 1.1在主函数中包含其它所有类头文件&#xff0c;进行声明和实例化&#xff1b;使用相机时&#xff0c;是用公共相机的接口在某一个具体函数中去实例化具体的海康相机对象。 1.2设计界面&#xff1a;连接相机&#xff0c;单次采集&a…...

【前后端分离项目】Vue+Springboot+MySQL

文章目录 1.安装 Node.js2.配置 Node.js 环境3.安装 Node.js 国内镜像4.创建 Vue 项目5.运行 Vue 项目6.访问 Vue 项目7.创建 Spring Boot 项目8.运行 Spring Boot 项目9.访问 Spring Boot 项目10.实现 Vue 与 Spring Boot 联动11.安装 axios12.编写请求13.调用函数请求接口14.…...

数据结构和算法(八)--2-3查找树

目录 一、平衡树 1、2-3查找树 1.1、定义 1.2、查找 1.3、插入 1.3.1、向2-结点中插入新键 1.3.2、向一棵只含有一个3-结点的树中插入新键 1.3.3、向一个父结点为2-结点的3-结点中插入新键 1.3.4、向一个父结点为3-结点的3-结点中插入新键 1.3.5、分解根结点 1.4、2…...

Java爬虫入门:从网页抓取到数据提取(正则表达式篇)

在当今信息爆炸的时代&#xff0c;如何从浩瀚的互联网中快速、准确地获取所需数据成为了一个重要的技能。网络爬虫技术应运而生&#xff0c;它允许我们自动化地访问网页并提取其中的信息。Java作为一门功能强大且拥有丰富生态的编程语言&#xff0c;在构建网络爬虫方面也表现出…...

Unity-Shader详解-其二

前向渲染和延迟渲染 前向渲染和延迟渲染总的来说是我们的两种主要的渲染方式。 我们在Unity的Project Settings中的Graphic界面能够找到渲染队列的设定&#xff1a; 我们也可以在Main Camera这里进行设置&#xff1a; 那这里我们首先介绍一下两种渲染&#xff08;Forward R…...

深入浅出理解并应用自然语言处理(NLP)中的 Transformer 模型

1 引言 随着信息技术的飞速发展&#xff0c;自然语言处理&#xff08;Natural Language Processing, NLP&#xff09;作为人工智能领域的一个重要分支&#xff0c;已经取得了长足的进步。从早期基于规则的方法到如今的深度学习技术&#xff0c;NLP 正在以前所未有的速度改变着我…...

当自动驾驶遇上“安全驾校”:NVIDIA如何用技术给无人驾驶赋能?

自动驾驶技术的商业化落地&#xff0c;核心在于能否通过严苛的安全验证。国内的汽车企业其实也在做自动驾驶&#xff0c;但是吧&#xff0c;基本都在L2级别。换句话说就是在应急时刻内&#xff0c;还是需要人来辅助驾驶&#xff0c;AI驾驶只是决策层&#xff0c;并不能完全掌握…...

WIN11安装Ubuntu22.04双系统,驱动cuda,配置3D GS

前言&#xff1a;看了很多基于3D GS开发的SLAM系统都默认在Ubuntu20.04-22.04中运行&#xff0c;并且WIN11不太方便安装cmake等基础编译库。所以还是在Ubuntu系统中进行咱的研究吧。 step 1. WIN11安装Ubuntu双系统 首先确认系统是否为UEFI模式。 winX进行磁盘管理&#xff…...

【OSG学习笔记】Day 9: 状态集(StateSet)与渲染优化 —— 管理混合、深度测试、雾效等渲染状态

干货开始。_ 一、StateSet核心概念与作用 StateSet 是OSG(OpenSceneGraph)中管理渲染状态的核心类,用于封装 OpenGL 渲染状态(如混合、深度测试、雾效、材质、纹理、着色器等),并将这些状态应用于节点或几何体。 通过合理组织 StateSet,可实现: 渲染状态的高效复用:…...

如何解析商品详情页面

解析商品详情页面是爬虫开发中的一个重要环节。由于商品详情页面通常包含丰富的信息&#xff0c;如商品名称、价格、描述、图片等&#xff0c;因此需要仔细分析页面结构并提取所需数据。以下是一个详细的步骤指南&#xff0c;展示如何使用 Java 和 Jsoup 解析商品详情页面。 一…...

Operating System 实验七 Linux文件系统实验

实验目标: 使用dd命令创建磁盘镜像文件ext2.img并格式化为ext2文件系统,然后通过mount命令挂载到Linux主机文件系统。查看ext2文件系统的超级块的信息,以及数据块的数量、数据块的大小、inode个数、空闲数据块的数量等信息 在文件系统中创建文件xxxxx.txt(其中xxxxx为你的学…...

使用 IntersectionObserver 实现懒加载提升网页性能的高效方案

在当今快节奏的网络环境中&#xff0c;用户对于网页加载速度的要求越来越高。对于前端开发者而言&#xff0c;优化网页性能、减少初始加载时间成为了一项至关重要的任务。懒加载&#xff08;Lazy Loading&#xff09;作为一种有效的性能优化策略&#xff0c;能够延迟非关键资源…...

Python-Django系列—部件

部件是 Django 对 HTML 输入元素的表示。部件处理 HTML 的渲染&#xff0c;以及从对应于部件的 GET&#xff0f;POST 字典中提取数据。 内置部件生成的 HTML 使用 HTML5 语法&#xff0c;目标是 <!DOCTYPE html>。例如&#xff0c;它使用布尔属性&#xff0c;如 checked…...

linux中shell脚本的编程使用

linux中shell脚本的编程使用 1.shell的初步理解1.1 怎么理解shell1.2 shell命令 2.shell编程2.1 什么是shell编程2.2 C语言编程 和 shell编程的区别 3.编写和运行第一个shell脚本程序3.1 编写时需要注意以下几点&#xff1a;3.1.1 shell脚本没有main函数&#xff0c;没有头文件…...

图像畸变-径向切向畸变实时图像RTSP推流

实验环境 注意&#xff1a;ffmpeg进程stdin写入两张图片的时间间隔不能太长&#xff0c;否则mediamtx会出现对应的推流session超时退出。 实验效果 全部代码 my_util.py #进度条 import os import sys import time import shutil import logging import time from datetime i…...

手搓雷达图(MATLAB)

看下别人做出来什么效果 话不多说&#xff0c;咱们直接开始 %% 可修改 labels {用户等级, 发帖数, 发帖频率, 点度中心度, 中介中心度, 帖子类型计分, 被列为提案数}; cluster_centers [0.8, 4.5, 3.2, 4.0, 3.8, 4.5, 4.2; % 核心用户0.2, 0.5, 0.3, 0.2, 0.1, 0.0, 0.0;…...

汽车零配件供应商如何通过EDI与主机厂生产采购流程结合

当前&#xff0c;全球汽车产业正经历深刻的数字化转型&#xff0c;供应链协同模式迎来全新变革。作为产业链核心环节&#xff0c;汽车零部件供应商与主机厂的高效对接已成为企业发展的战略要务。然而&#xff0c;面对主机厂日益严格的数字化采购要求&#xff0c;许多供应商在ED…...

闻性与空性:从耳根圆通到究竟解脱的禅修路径

一、闻性之不动&#xff1a;超越动静的觉性本质 在《楞严经》中&#xff0c;佛陀以钟声为喻揭示闻性的奥秘&#xff1a;钟声起时&#xff0c;闻性显现&#xff1b;钟声歇时&#xff0c;闻性不灭。此“不动”并非如磐石般凝固&#xff0c;而是指觉性本身超越生灭、来去的绝对性…...

第34课 常用快捷操作——按“空格键”旋转图元

概述 旋转某个图元&#xff0c;是设计过程中常需要用到的操作&#xff0c;无论是在原理图中旋转某个图形&#xff0c;还是在PCB图中旋转某个元素。 旋转操作的快捷键是空格键。下面作详细介绍。 按空格键旋转图元 当我们选中一个图元时&#xff0c;按下空格键&#xff0c;即…...

基于亚马逊云科技构建音频转文本无服务器应用程序

Amazon Transcribe是一项基于机器学习模型自动将语音转换为文本的服务。它提供了多种可以提高文本转录准确性的功能&#xff0c;例如语言自定义、内容过滤、多通道音频分析和说话人语音分割。Amazon Transcribe 可用作独立的转录服务&#xff0c;也可以集成到应用程序中提供语音…...

如何打包python程序为可执行文件

将 Python 程序打包为可执行文件是一个常见需求&#xff0c;尤其是在希望将应用程序分享给不具备 Python 环境的用户时。以下是使用 PyInstaller 工具将 Python 程序打包为可执行文件的步骤。 步骤 1&#xff1a;安装 PyInstaller 如果您还没有安装 PyInstaller&#xff0c;请…...

计算机二级MS Office第八套演示文稿

教程&#xff1a;...

K8S Service 原理、案例

一、理论介绍 1.1、3W 法则 1、是什么&#xff1f; Service 是一种为一组功能相同的 pod 提供单一不变的接入点的资源。当 Service 存在时&#xff0c;它的IP地址和端口不会改变。客户端通过IP地址和端口号与 Service 建立连接&#xff0c;这些连接会被路由到提供该 Service 的…...

实验四 进程调度实验

一、实验目的 1、了解操作系统CPU管理的主要内容。 2、加深理解操作系统管理控制进程的数据结构--PCB。 3、掌握几种常见的CPU调度算法&#xff08;FCFS、SJF、HRRF、RR&#xff09;的基本思想和实现过程。 4、用C语言模拟实现CPU调度算法。 5、掌握CPU调度算法性能评价指…...

ABAP Object Services

ABAP Object Services...

linux blueZ 第四篇:BLE GATT 编程与自动化——Python 与 C/C++ 实战

本篇聚焦 BLE(Bluetooth Low Energy)GATT 协议层的编程与自动化实践,涵盖 GATT 基础、DBus API 原理、Python(dbus-next/bleak)示例、C/C++ (BlueZ GATT API)示例,以及自动发现、读写特征、订阅通知、安全配对与脚本化测试。 目录 BLE GATT 基础概念 BlueZ DBus GATT 模…...

Linux线程与进程:探秘共享地址空间的并发实现与内

Linux系列 文章目录 Linux系列前言一、线程的概念二、线程与地址空间2.1 线程资源的分配2.2 虚拟地址到物理地址的转换 三 、线程VS进程总结 前言 在Linux操作系统中&#xff0c;线程作为CPU调度的基本单位&#xff0c;起着至关重要的作用。深入理解线程控制机制&#xff0c;是…...

ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0

在遇到这个代码时&#xff0c;大多数情况下就是两个运算的向量维度不匹配&#xff0c;此时&#xff0c;可以打印一下两个数组的维度&#xff0c; # print(“[DEBUG] a shape:”, a.shape) # print(“[DEBUG]b:”, b.shape) 假设a.shape结果为[,200],b.shape结果为[210,255],那么…...

MySQL 8.4企业版 安装和配置审计插件

在最新的MySQL 8.4.4企业版上启用审计日志功能 操作系统&#xff1a;Ubuntu 24.04 数据库:8.4.4-commercial for Linux on x86_64 (MySQL Enterprise Server - Commercial) 1.查看安装脚本 下面2个脚本位于mysql安装目录 share 下&#xff0c;一个是window一个是linux可以用…...

科学养生,开启健康生活新方式

在快节奏的现代生活中&#xff0c;健康养生已成为人们关注的焦点。科学的养生方式不仅能增强体质&#xff0c;还能有效预防疾病&#xff0c;提升生活质量。​ 合理饮食是健康养生的基础。日常饮食应遵循均衡原则&#xff0c;保证蛋白质、碳水化合物、脂肪、维生素和矿物质的合…...