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,相机以及机器人的二次开发)等系统化学习文章。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/77268.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于大模型底座重构司法信息系统

前置篇章&#xff1a;法律智能体所需的基础知识 构建一个高效的法律智能体&#xff0c;特别是在基于RAG&#xff08;Retrieval-Augmented Generation&#xff09;架构的背景下&#xff0c;需要融合多种学科和领域的知识。以下是对法律智能体开发和应用所需核心基础知识的简要介…

类《双人成行》3D动作益智冒险类双人控制游戏开发

服务器端采用了基于开源Kbengine&#xff08;引擎使用C和Python编写&#xff09;的多人在线游戏服务器&#xff0c;客户端采用Unity3D。游戏支持线上的双人联机房间功能。 资源地址&#xff1a;类《双人成行》3D动作益智冒险类双人控制游戏开发教程 | Unity 中文课堂 一、游戏…

Spark--基本介绍

Spark是基于内存的快速&#xff0c;通农用&#xff0c;可拓展的大数据分析计算引擎&#xff0c;Hadoop是一个分布式系统基础架构 Spark和Hadoop之间的对比和联系 架构与组件&#xff1a; Hadoop&#xff1a; ■ HDFS&#xff1a;分布式文件系统&#xff0c;负责海量数据存储。…

05-GPIO原理

一、概述 1、GPIO,即通用I/O(输入/输出)端口&#xff0c;是STM32可控制的引脚。STM32芯片的GPIO引脚与外部设备连接起来&#xff0c;可实现与外部通讯、控制外部硬件或者采集外部硬件数据的功能。 2、GPIO的复用:引脚复用是指将单个引脚配置为多个功能的能力。在 STM32 中&…

基于LangChain4J的AI Services实践:用声明式接口重构LLM应用开发

基于LangChain4J的AI Services实践&#xff1a;用声明式接口重构LLM应用开发 前言&#xff1a;当Java开发遇上LLM编程困境 在LLM应用开发领域&#xff0c;Java开发者常面临两大痛点&#xff1a;一是需要手动编排Prompt工程、记忆管理和结果解析等底层组件&#xff0c;二是复杂…

深入解析 Docker 容器进程的 cgroup 和命名空间信息

深入解析 Docker 容器进程的 cgroup 和命名空间信息 在现代 Linux 系统中&#xff0c;控制组&#xff08;cgroup&#xff09;和命名空间&#xff08;namespace&#xff09;是实现容器化技术的核心机制。cgroup 用于管理和限制进程的资源使用&#xff08;如 CPU、内存、I/O&…

【汽车ECU电控数据管理篇】S19文件格式解析篇章

一、S19格式是啥 在电控文件管理的初期阶段&#xff0c;我首次接触到的是 A2L 和 HEX 文件。其中&#xff0c;A2L 文件主要承担着描述性功能&#xff0c;它详细地描述了各种参数和配置等相关信息。而 HEX 文件则是一种刷写文件&#xff0c;其内部明确记录了具体的地址以及对应的…

python编程相关的单词

the: 在编程中&#xff0c;“the” 是一个常见的英语单词&#xff0c;用于指定特定的对象或变量。例如&#xff0c;“the function” 指的是某个特定的函数。 the的拼写是t,h,e.再读一次t,h,e and: 在编程中&#xff0c;“and” 是一个逻辑运算符&#xff0c;用于连接两个条件&…

网络原理 - 4(TCP - 1)

目录 TCP 协议 TCP 协议段格式 可靠传输 几个 TCP 协议中的机制 1. 确认应答 2. 超时重传 完&#xff01; TCP 协议 TCP 全称为 “传输控制协议”&#xff08;Transmission Control Protocol&#xff09;&#xff0c;要对数据的传输进行一个详细的控制。 TCP 协议段格…

python博客爬虫列表

我希望对指定网页的&#xff0c;博客列表&#xff0c;获取url&#xff0c;然后保存成本地文件&#xff0c;用python实现 step1: import requests from bs4 import BeautifulSoup import jsondef get_blog_links(url):headers {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win6…

软件测试入门学习笔记

今天学习新知识&#xff0c;软件测试。 什么是软件测试&#xff1f; 使用人工和自动手段来运行或测试某个系统的过程&#xff0c;目的在于检验它是否满足规定的需求或弄清实际结果与预期结果之间的差别。 软件测试的目的&#xff1f; 1&#xff09;为了发现程序&#xff0…

uniapp开发2--uniapp中的条件编译总结

以下是对 uni-app 中条件编译的总结&#xff1a; 概念&#xff1a; 条件编译是一种技术&#xff0c;允许你根据不同的平台或环境&#xff0c;编译不同的代码。 在 uni-app 中&#xff0c;这意味着你可以编写一套代码&#xff0c;然后根据要编译到的平台&#xff08;例如微信小…

【k8s】sidecar边车容器

一、Sidecar 模式简介 Sidecar 模式是一种常见的微服务架构设计模式。它通过将附加功能或服务与主应用程序部署在同一容器或主机上&#xff0c;从而实现对主应用程序的增强和扩展。Sidecar 的名称来源于摩托车的边车&#xff0c;它与摩托车紧密相连&#xff0c;为主车提供额外…

MySQL索引使用一定有效吗?如何排查索引效果?

MySQL索引使用一定有效吗&#xff1f;如何排查索引效果&#xff1f; 1. 索引一定有效吗&#xff1f; 不一定&#xff01; 即使你创建了索引&#xff0c;MySQL 也可能因为以下原因 不使用索引 或 索引效果不佳&#xff1a; 索引选择错误&#xff1a;MySQL 优化器可能选择了错…

漏洞管理体系:从扫描评估到修复验证的全生命周期实践

漏洞管理体系&#xff1a;从扫描评估到修复验证的全生命周期实践 在网络安全防御体系中&#xff0c;漏洞管理是“攻防博弈”的核心战场。据NVD&#xff08;国家漏洞数据库&#xff09;统计&#xff0c;2023年新增漏洞超21万个&#xff0c;平均每天披露575个&#xff0c;其中32…

cdh平台管理与运维最佳实践

一、容量规划:构建可持续扩展的数据湖底座 1.1 资源评估三维模型 #mermaid-svg-4Fd5JDKTgwqF1BUd {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-4Fd5JDKTgwqF1BUd .error-icon{fill:#552222;}#mermaid-svg-4Fd5J…

力扣347:前K个高频元素

给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 示例 1: 输入: nums [1,1,1,2,2,3], k 2 输出: [1,2]示例 2: 输入: nums [1], k 1 输出: [1]题解&#xff1a; 一、思路&#xff1a; 1.我希望将nu…

前馈神经网络层

FeedForward Network 论文地址 https://arxiv.org/pdf/1706.03762 前馈网络介绍 前馈网络是Transformer模型中的关键组件&#xff0c;每个Transformer层包含一个多头注意力模块和一个前馈网络模块。该模块通过两次线性变换和激活函数&#xff0c;为模型提供非线性建模能力。其核…

如何将 sNp 文件导入并绘制到 AEDT (HFSS)

导入 sNp 文件 打开您的项目&#xff0c;右键单击 “Result” 绘制结果 导入后&#xff0c;用户可以选择它进行打印。请参阅下面的示例。要点&#xff1a;确保从 Solution 中选择它。

es-核心储存原理介绍

原始数据 idusernamegradedescription1ahua87i like study2xiaowang92i like es3zhaoyun63i like java 倒排索引 description使用的text分词&#xff0c;使用倒排索引 termidi1,2,3like1,2,3study1es2java3 分词后&#xff0c;如果匹配 es&#xff0c;则需要逐行匹配&…