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

qt学习:arm摄像头+c调用v412框架驱动+qt调用v412框架驱动 显示摄像头画面

目录

跟内核进行数据通信的函数

编程步骤

c代码

头文件

打开摄像头文件 /dev/videox

获取当前主机上(开发板)摄像头列表信息

设置当前摄像头的画面格式  比如说 设置 采集图像的宽度为640  高度 480

在内核空间中,申请一个缓冲区队列(队列中有4块缓冲区)

将申请好的缓冲区队列 映射到 用户空间中

开启摄像头 

采集数据 yuyv

将采集出来的yuyv格式的数据---转换成 rgb

将c代码移植到qt代码中,在qt的界面显示摄像头画面

MCamera摄像头类添加头文件,成员,函数接口

实现MCamera摄像头类函数接口

在主ui界面类加入头文件,成员,函数接口

在构造函数中初始化摄像头类和定时器类,并关联定时器的槽函数

开启摄像头按钮点击事件

关闭摄像头按钮点击事件

拍照按钮点击事件

定时器槽函数实现


qt由于在arm qt版本下,没有多媒体库,所以,arm qt程序要访问摄像头,那么必须要使用linux操作系统v412(video for linux 2)机制

简单来说就是要在arm上安装v412框架就可以使用摄像头

跟内核进行数据通信的函数

#include <stropts.h>

int ioctl(int fildes,int request,.../* arg */);

  • 第一个参数:fd文件描述符
  • 第二个参数:要发送的命令
    • VIDIOC_REQBUFS:分配内存
    • VIDIOC_QUERYBUF:把 VIDIOC_REQBUFS 中分配的数据缓存转换成物理地址
    • VIDIOC_QUERYCAP:查询驱动功能
    • VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式
    • VIDIOC_S_FMT:设置当前驱动的频捕获格式
    • VIDIOC_G_FMT:读取当前驱动的频捕获格式
    • VIDIOC_TRY_FMT:验证当前驱动的显示格式
    • VIDIOC_CROPCAP:查询驱动的修剪能力
    • VIDIOC_S_CROP:设置视频信号的边框
    • VIDIOC_G_CROP:读取视频信号的边框
    • VIDIOC _QBUF:把数据放回缓存队列
    • VIDIOC_DQBUF:把数据从缓存中读取出来
    • VIDIOC_$TREAMON:开始视频显示函数
    • VIDIOC_STREAMOFF:结束视频显示函数
    • VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如 PAL或NTSC。
  • ....:变参接口,根据第二个参数来决定

编程步骤

  • 打开摄像头文件 /dev/videox
  • 获取当前主机上的摄像头列表信息
    • #define VIDIOC_ENUM_FMT _IOWR('V',2,struct v412_fmtdesc)
      • struct v412_fmtdesc fmt;
      • ioctl(fd,VIDIOC_ENUM_FMT,&fmt);
  • 设置当前视频捕捉格式
    • 也就是设置摄像头采集画面的宽度、高度、格式
    • VIDIOC_S_FMT:设置当前驱动的视频捕捉格式
    • #define VIDIOC_S_FMT _IOWR('V',5,struct v412_format)
      • struct v412_format format;
      • format.宽度 = 640;
      • format.高度 = 400;
      • ioctl(fd,VIDIOC_S_FMT,&format);
  • 申请内核缓冲区队列VIDIOC_REQBUFS
    • 一般会将摄像头获取到的数据放到4块内存空间---一次性存储4帧画面数据
  • 将申请的内核缓冲区队列映射到用户空间VIDIOC_QUERYBUF
  • 开启摄像头VIDIOC_STREAMON  
    • 将开启摄像头的命令从应用层发送到内核层中,内核层就会驱动这个摄像头开始工作
  • while(1)
    • 采集数据  --yuyv格式
      • 注意;摄像头采集出来的图像数据格式组成是yuyv
    • 将采集出来的一帧画面yuyv格式的数据转为rgb格式
    • 将转换好rgb格式数据显示到ui控件上

c代码

头文件

#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#include <linux/videodev2.h> //v4l2视频开发框架
#include <sys/mman.h>

打开摄像头文件 /dev/videox

    //打开摄像头文件返回文件描述符int fd = open("/dev/video7",O_RDWR);if(fd == -1){perror("open camera error");return -1;}

获取当前主机上(开发板)摄像头列表信息

    //2、获取当前主机上(开发板)摄像头列表信息//#define VIDIOC_ENUM_FMT         _IOWR('V',  2, struct v4l2_fmtdesc)struct v4l2_fmtdesc v4fmt; //定义一个结构体v4fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //视频捕捉类型int i = 0;while(1){v4fmt.index = i++;int ret = ioctl(fd,VIDIOC_ENUM_FMT,&v4fmt);if(ret < 0){//perror("获取失败");break;}printf("index = %d\n",v4fmt.index);printf("flags = %d\n",v4fmt.flags);printf("description = %s\n",v4fmt.description);unsigned char*p =  (unsigned char*)&v4fmt.pixelformat;printf("pixelformat = %c%c%c%c\n",p[0],p[1],p[2],p[3]);printf("reserved = %d\n",v4fmt.reserved[0]);}

设置当前摄像头的画面格式  比如说 设置 采集图像的宽度为640  高度 480

    //3、设置当前摄像头的画面格式  比如说 设置 采集图像的宽度为640  高度 480//#define VIDIOC_S_FMT		_IOWR('V',  5, struct v4l2_format)//发送VIDIOC_S_FMT命令需要定义struct v4l2_format结构体,//该结构体存放摄像头的画面格式,将摄像头设置为视频捕捉模式需要用到struct v4l2_format结构体struct v4l2_format vfmt;//设置为视频捕捉模式vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;vfmt.fmt.pix.width = 640;// 设置宽(因为底层驱动已固定大小,不能任意改)vfmt.fmt.pix.height = 480;//设置高度vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; //设置视频采集格式//将设置好的格式发送到摄像头ioctl(fd,VIDIOC_S_FMT,&vfmt);//设置完通过VIDIOC_G_FMT这个命令来查看格式有没有设置成功//#define VIDIOC_G_FMT        _IOWR('V',  4, struct v4l2_format) //获取格式memset(&vfmt,0,sizeof(vfmt)); //清空结构体//设置为视频捕捉模式vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//获取的格式信息存放在该结构体中int ret = ioctl(fd,VIDIOC_G_FMT,&vfmt);if(ret < 0){perror("获取格式失败");return -1;}//获取成功判断它的宽和高和模式if(vfmt.fmt.pix.width == 640 && vfmt.fmt.pix.height == 480 && vfmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV ){printf("设置成功\n");}else{printf("设置失败\n");}

在内核空间中,申请一个缓冲区队列(队列中有4块缓冲区)

    //4、在内核空间中,申请一个缓冲区队列(队列中有4块缓冲区)//发送VIDIOC_REQBUFS命令需要struct v4l2_requestbuffers结构体struct v4l2_requestbuffers reqbuffers;reqbuffers.count = 4; //申请4个缓冲区reqbuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;// 摄像头采集模式reqbuffers.memory = V4L2_MEMORY_MMAP; // mmap内存映射//向内核空间打一个报告,向你申请4个缓冲区队列,申请的方式为内存映射ret = ioctl(fd,VIDIOC_REQBUFS,&reqbuffers); //获取的信息存放在该结构体if(ret < 0){perror("申请队列空间失败");return -1;}

将申请好的缓冲区队列 映射到 用户空间中

    //5、将申请好的缓冲区队列映射到用户空间中//#define VIDIOC_QUERYBUF _IOWR('v',9,struct v4l2_buffer)//这个数组有4个元素,每个元素存储的是地址,存储的地址就是映射成功之后的地址unsigned char* mptr[4];unsigned int size[4];//发送VIDIOC_QUERYBUF命令需要struct v4l2_buffer结构体struct v4l2_buffer mapbuffer;mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;// 摄像头采集模式for(int i=0;i<4;i++){mapbuffer.index = i; //申请的缓冲区编号//发送VIDIOC_QUERYBUF命令来查询内核空间队列ret = ioctl(fd,VIDIOC_QUERYBUF,&mapbuffer);    if(ret < 0) {perror("查询内核空间队列失败\n");return -1;}    //mmap真正来实现内存映射 ,该函数的返回值是一个内存的首地址mptr[i] = (unsigned char*)mmap(NULL,mapbuffer.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,mapbuffer.m.offset);    size[i] = mapbuffer.length;//通知使用完毕,----放回内核//#define VIDIOC_QBUF        _IOWR('V', 15, struct v4l2_buffer)ret = ioctl(fd,VIDIOC_QBUF,&mapbuffer);if(ret < 0){perror("放回失败\n");return -1;}}

开启摄像头 

    //6、开启摄像头 //#define VIDIOC_STREAMON		 _IOW('V', 18, int)int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;// 摄像头采集模式//发送VIDIOC_QUERYBUF命令来开启摄像头ioctl(fd,VIDIOC_STREAMON,&type);

采集数据 yuyv

        unsigned char buffer[640*480*3] = {0};//采集后的数据int size;//发送命令采集数据函数get_frame(buffer,&size);//获取图片
void get_frame(unsigned char*buffer,int *size)
{ //1、先查询 当前帧数据 到底 在哪个 缓冲区中//采集数据 --VIDIOC_DQBUF:把数据从缓存中读取出来//#define VIDIOC_DQBUF        _IOWR('V', 17, struct v4l2_buffer)//发送VIDIOC_DQBUF需要struct v4l2_buffer结构体struct v4l2_buffer readbuffer;readbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//采集模式//发送VIDIOC_DQBUF采集数据放到结构体里int ret = ioctl(fd,VIDIOC_DQBUF,&readbuffer);if(ret < 0){perror("提取数据失败");return -1 ;}//使用内存拷贝 -- void *memcpy(void *dest, const void *src, size_t n);memcpy(buffer,mptr[readbuffer.index],readbuffer.length);*size = readbuffer.length;//VIDIOC_QBUF:把数据放回缓存队列//通知内核已使用完毕//#define VIDIOC_QBUF        _IOWR('V', 15, struct v4l2_buffer)ret = ioctl(fd,VIDIOC_QBUF,&readbuffer);if(ret < 0){perror("放回队列失败");return -1 ;}
}

将采集出来的yuyv格式的数据---转换成 rgb

        unsigned char rgb[640*480*3] = {0};//转换后的数据//8、将采集出来的yuyv格式的数据---转换成 rgbyuyv2rgb0(buffer, rgb, 640, 480);
//将yuyv格式转为rgb格式
int yuyv2rgb0(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
{unsigned int in, out;int y0, u, y1, v;unsigned int pixel24;unsigned char *pixel = (unsigned char *)&pixel24;unsigned int size = width*height*2;for(in = 0, out = 0; in < size; in += 4, out += 6){y0 = yuv[in+0];u  = yuv[in+1];y1 = yuv[in+2];v  = yuv[in+3];sign3 = 1;pixel24 = yuyv2rgb(y0, u, v);rgb[out+0] = pixel[0];rgb[out+1] = pixel[1];rgb[out+2] = pixel[2];pixel24 = yuyv2rgb(y1, u, v);rgb[out+3] = pixel[0];rgb[out+4] = pixel[1];rgb[out+5] = pixel[2];}return 0;
}

将c代码移植到qt代码中,在qt的界面显示摄像头画面

新建一个ui界面,布局一个两个按钮用于开启,停止,一个QLabel显示画面

通过定时器来调整帧数

新建一个MCamera摄像头类,将c代码移植进去

MCamera摄像头类添加头文件,成员,函数接口

extern "C"{#include<stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include <string.h>#include <linux/videodev2.h> //v4l2视频开发框架#include <sys/mman.h>#include <unistd.h>
}
class MCamera
{
public:MCamera(const char*deviceName = "/dev/video7");void start();//启动摄像头void stop();//关闭摄像头void get_frame(unsigned char*buffer,int *size);//获取图像数据int yuyv2rgb0(unsigned char *buffer, unsigned char *rgbdata, int w, int h);//yuyv转为rgb
private:int fd;//摄像头文件描述符unsigned char* mptr[4];//这个数组有4个元素,每个元素存储的是地址,存储的地址就是映射成功之后的地址unsigned int size[4];//图像的大小bool captrueFlag;//拍照标志位
};

实现MCamera摄像头类函数接口

MCamera::MCamera(const char*deviceName )
{//1、打开摄像头文件//打开摄像头文件返回文件描述符fd = open(deviceName,O_RDWR);if(fd == -1){perror("open camera error");return ;}//2、获取当前主机上(开发板)摄像头列表信息//#define VIDIOC_ENUM_FMT         _IOWR('V',  2, struct v4l2_fmtdesc)struct v4l2_fmtdesc v4fmt; //定义一个结构体v4fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //视频捕捉类型int i = 0;while(1){v4fmt.index = i++;int ret = ioctl(fd,VIDIOC_ENUM_FMT,&v4fmt);if(ret < 0){//perror("获取失败");break;}printf("index = %d\n",v4fmt.index);printf("flags = %d\n",v4fmt.flags);printf("description = %s\n",v4fmt.description);unsigned char*p =  (unsigned char*)&v4fmt.pixelformat;printf("pixelformat = %c%c%c%c\n",p[0],p[1],p[2],p[3]);printf("reserved = %d\n",v4fmt.reserved[0]);}//3、设置当前摄像头的画面格式  比如说 设置 采集图像的宽度为640  高度 480//#define VIDIOC_S_FMT		_IOWR('V',  5, struct v4l2_format)struct v4l2_format vfmt;vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;vfmt.fmt.pix.width = 640;// 设置宽(因为底层驱动已固定大小,不能任意改)vfmt.fmt.pix.height = 480;//设置高度vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; //设置视频采集格式ioctl(fd,VIDIOC_S_FMT,&vfmt);//#define VIDIOC_G_FMT        _IOWR('V',  4, struct v4l2_format) //获取格式memset(&vfmt,0,sizeof(vfmt)); //清 零结构体vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;int ret = ioctl(fd,VIDIOC_G_FMT,&vfmt); //获取的    信息存 放在该结构体if(ret < 0){perror("获取格式失败");return ;}if(vfmt.fmt.pix.width == 640 && vfmt.fmt.pix.height == 480 && vfmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV ){printf("设置成功\n");}else{printf("设置失败\n");}//4、在内核空间中,申请一个缓冲区队列(队列中有4块缓冲区)struct v4l2_requestbuffers reqbuffers;reqbuffers.count = 4; //申请4个缓冲区reqbuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;// 摄像头采集reqbuffers.memory = V4L2_MEMORY_MMAP; // mmap//向内核空间打一个报告,向你申请4个缓冲区队列,申请的方式为内存映射ret = ioctl(fd,VIDIOC_REQBUFS,&reqbuffers); //获取的    信息存 放在该结构体if(ret < 0){perror("申请队列空间失败");return ;}//5、将申请好的缓冲区队列 映射到 用户空间中struct v4l2_buffer mapbuffer;mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;for(int i=0;i<4;i++){mapbuffer.index = i; //申请的缓冲区编号ret = ioctl(fd,VIDIOC_QUERYBUF,&mapbuffer);if(ret < 0) {perror("查询内核空间队列失败\n");return ;}//真正来实现内存映射 ,该函数的返回值是一个内存的首地址mptr[i] = (unsigned char*)mmap(NULL,mapbuffer.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,mapbuffer.m.offset);size[i] = mapbuffer.length;//通知使用完毕,----放回内核//#define VIDIOC_QBUF        _IOWR('V', 15, struct v4l2_buffer)ret = ioctl(fd,VIDIOC_QBUF,&mapbuffer);if(ret < 0){perror("放回失败\n");return ;}}
}void MCamera::start()
{//6、开启摄像头//#define VIDIOC_STREAMON		 _IOW('V', 18, int)int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ioctl(fd,VIDIOC_STREAMON,&type);
}void MCamera::stop()
{//[8] 停止采集int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;int ret = ioctl(fd,VIDIOC_STREAMOFF,&type);//释放内存 int munmap(void *addr, size_t length);for(int i=0;i<4;i++){munmap(mptr[i],size[i]);}//[9] 关闭设备::close(fd);
}void MCamera::get_frame(unsigned char *buffer, int *size)
{//采集数据 --VIDIOC_DQBUF:把数据从缓存中读取出来//#define VIDIOC_DQBUF        _IOWR('V', 17, struct v4l2_buffer)//1、先查询 当前帧数据 到底 在哪个 缓冲区中struct v4l2_buffer readbuffer;readbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;int ret = ioctl(fd,VIDIOC_DQBUF,&readbuffer);if(ret < 0){perror("提取数据失败");return  ;}//使用内存拷贝 -- void *memcpy(void *dest, const void *src, size_t n);memcpy(buffer,mptr[readbuffer.index],readbuffer.length);*size = readbuffer.length;//VIDIOC_QBUF:把数据放回缓存队列//通知内核已使用完毕//#define VIDIOC_QBUF        _IOWR('V', 15, struct v4l2_buffer)ret = ioctl(fd,VIDIOC_QBUF,&readbuffer);if(ret < 0){perror("放回队列失败");return  ;}
}int MCamera::yuyv2rgb0(unsigned char *buffer, unsigned char *rgbdata, int w, int h)
{int r1, g1, b1;int r2, g2, b2;for(int i=0; i<w*h/2; i++){char data[4];memcpy(data, buffer+i*4, 4);//Y0U0Y1V1  -->[Y0 U0 V1] [Y1 U0 V1]unsigned char Y0=data[0];unsigned char U0=data[1];unsigned char Y1=data[2];unsigned char V1=data[3];r1 = Y0+1.4075*(V1-128); if(r1>255)r1=255; if(r1<0)r1=0;g1 =Y0- 0.3455 * (U0-128) - 0.7169*(V1-128); if(g1>255)g1=255; if(g1<0)g1=0;b1 = Y0 + 1.779 * (U0-128);  if(b1>255)b1=255; if(b1<0)b1=0;r2 = Y1+1.4075*(V1-128);if(r2>255)r2=255; if(r2<0)r2=0;g2 = Y1- 0.3455 * (U0-128) - 0.7169*(V1-128); if(g2>255)g2=255; if(g2<0)g2=0;b2 = Y1 + 1.779 * (U0-128);  if(b2>255)b2=255; if(b2<0)b2=0;rgbdata[i*6+0]=r1;rgbdata[i*6+1]=g1;rgbdata[i*6+2]=b1;rgbdata[i*6+3]=r2;rgbdata[i*6+4]=g2;rgbdata[i*6+5]=b2;}
}

在主ui界面类加入头文件,成员,函数接口

#include <QTimer>
#include "mcamera.h"private slots:void onUpdateCameraUi();private:MCamera *m_camera;//自定义摄像头类QTimer *m_timer;//定时器类

在构造函数中初始化摄像头类和定时器类,并关联定时器的槽函数

    m_camera = NULL;m_timer = new QTimer;connect(m_timer,&QTimer::timeout,this,&Widget::onUpdateCameraUi);

开启摄像头按钮点击事件

    if(m_camera == NULL){m_camera = new MCamera;m_camera->start();//启动定时器,间隔时间采集图像数据m_timer->start(1); //1秒钟采集 一张画面(一帧画面)}

关闭摄像头按钮点击事件

    if(m_camera != NULL){m_timer->stop();m_camera->stop();delete  m_camera;m_camera = NULL;}

拍照按钮点击事件

captrueFlag=true;

定时器槽函数实现

    //  采集数据unsigned char buffer[640*480*3] = {0};unsigned char rgb[640*480*3] = {0};int size;m_camera->get_frame(buffer,&size);//yuyv转换rgbm_camera->yuyv2rgb0(buffer,rgb,640,480);//显示   源图像rgb --->pic对象QImage img = QImage(rgb,640,480,QImage::Format_RGB888);//保存为图片if(captrueFlag){img.save("1.bmp");captrueFlag = false;}QPixmap pic = QPixmap::fromImage(img);ui->label->setPixmap(pic);

在linux中交叉编译放到开发板上运行

相关文章:

qt学习:arm摄像头+c调用v412框架驱动+qt调用v412框架驱动 显示摄像头画面

目录 跟内核进行数据通信的函数 编程步骤 c代码 头文件 打开摄像头文件 /dev/videox 获取当前主机上&#xff08;开发板&#xff09;摄像头列表信息 设置当前摄像头的画面格式 比如说 设置 采集图像的宽度为640 高度 480 在内核空间中&#xff0c;申请一个缓冲区队列…...

Linux 36.2@Jetson Orin Nano基础环境构建

Linux 36.2Jetson Orin Nano基础环境构建 1. 源由2. 步骤2.1 安装NVIDIA Jetson Linux 36.2系统2.2 必备软件安装2.3 基本远程环境2.3.1 远程ssh登录2.3.2 samba局域网2.3.3 VNC远程登录 2.4 开发环境安装 3. 总结 1. 源由 现在流行什么&#xff0c;也跟风来么一个一篇。当然&…...

牛客网SQL264:查询每个日期新用户的次日留存率

官网链接&#xff1a; 牛客每个人最近的登录日期(五)_牛客题霸_牛客网牛客每天有很多人登录&#xff0c;请你统计一下牛客每个日期新用户的次日留存率。 有一个登录(login。题目来自【牛客题霸】https://www.nowcoder.com/practice/ea0c56cd700344b590182aad03cc61b8?tpId82 …...

echarts 曲线图自定义提示框

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>曲线图</title><!-- 引入 ECharts 库 -->…...

幻兽帕鲁服务器怎么搭建?Palworld多人联机教程

玩转幻兽帕鲁服务器&#xff0c;阿里云推出新手0基础一键部署幻兽帕鲁服务器教程&#xff0c;傻瓜式一键部署&#xff0c;3分钟即可成功创建一台Palworld专属服务器&#xff0c;成本仅需26元&#xff0c;阿里云服务器网aliyunfuwuqi.com分享2024年新版基于阿里云搭建幻兽帕鲁服…...

DAY39: 动态规划不同路径问题62

Leetcode: 62 不同路径 机器人从(0 , 0) 位置出发&#xff0c;到(m - 1, n - 1)终点。 基本思路 1、确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j] &#xff1a;表示从&#xff08;0 &#xff0c;0&#xff09;出发&#xff0c;到(i, j) 有dp[i][j]条…...

idea开发工具的简单使用与常见问题

1、配置git 选择左上角目录file->setting 打开&#xff0c;Version Control 目录下Git&#xff0c;选择git安装目录下的git.exe文件&#xff1b; 点击test&#xff0c;出现git版本&#xff0c;则表示git识别成功&#xff0c;点击右下角确认即可生效。 2、配置node.js 选…...

使用 WMI 查询安全软件信息

在这篇文章中&#xff0c;我们将详细介绍如何使用 Windows Management Instrumentation (WMI) API 来查询当前计算机上安装的安全软件的基本信息。我们将分析代码的各个部分&#xff0c;并解释每个步骤所涉及的技术和原理。 一、什么是 WMI&#xff1f; WMI 是 Windows Manag…...

创建TextMeshPro字体文件

相比于Unity的Text组件&#xff0c;TextMesh Pro提供了更强大的文本格式和布局控制&#xff0c;更高级的文本渲染技术&#xff0c;更灵活的文本样式和纹理支持&#xff0c;更好的性能以及更易于使用的优点。但unity自带TextMeshPro字体不支持中文。这里使用普通字体文件生成Tex…...

信创ARM架构QT应用开发环境搭建

Linux ARM架构QT应用开发环境搭建 前言交叉工具链Ubuntu上安装 32 位 ARM 交叉工具链Ubuntu上安装 64 位 ARM 交叉工具链 交叉编译 QT 库下载 QT 源码交叉编译 QT 源码 Qt Creator交叉编译配置配置 Qt Creator Kits创建一个测试项目 小结 前言 有没有碰到过这种情况&#xff1…...

使用SPM_batch进行批量跑脚本(matlab.m)

软件&#xff1a;spm8matlab2023bwin11 数据格式&#xff1a; F:\ASL\HC\CBF\HC_caishaoqing\CBF.nii F:\ASL\HC\CBF\HC_caishaoqing\T1.nii F:\ASL\HC\CBF\HC_wangdonga\CBF.nii F:\ASL\HC\CBF\HC_wangdonga\T1.nii clear spmdirD:\AnalysisApps\spm8; datadirF:\ASL\HC\CBF…...

力扣0124——二叉树的最大路径和

二叉树的最大路径和 难度&#xff1a;困难 题目描述 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点…...

c# 字符串帮助类

public class StringHelper { #region 全角半角互相转换 /// <summary> /// 转全角的函数(SBC case) /// </summary> /// <param name"str">任意字符串</param> /// <returns>全…...

LabVIEW双光子荧光显微成像系统开发

双光子显微成像是一种高级荧光显微技术&#xff0c;广泛用于生物学和医学研究&#xff0c;尤其是用于活体组织的深层成像。在双光子成像过程中&#xff0c;振镜&#xff08;Galvo镜&#xff09;扮演了非常关键的角色&#xff0c;它负责精确控制激光束在样本上的扫描路径。以下是…...

Prim模板

通过代码探索Prim算法&#xff1a;最小生成树之旅 在计算机科学领域&#xff0c;图算法占据了至关重要的位置&#xff0c;尤其是在设计高效的网络&#xff08;无论是社交网络、计算机网络还是交通网&#xff09;时。在这些算法中&#xff0c;寻找最小生成树&#xff08;MST&am…...

CSS之盒子模型

盒子模型 01-选择器 结构伪类选择器 基本使用 作用&#xff1a;根据元素的结构关系查找元素。 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IE…...

Linux系统安装(CentOS Vmware)

学习环境安装 VMware安装 VMware下载&安装 访问官网&#xff1a;https://www.vmware.com 在此处可以选择语言 点击China&#xff08;简体中文&#xff09; 点击产品&#xff0c;点击Workstation Pro 下滑&#xff0c;点击下载试用版 下滑找到Workstation 17 Pro for Wi…...

STM32 硬件随机数发生器(RNG)

STM32 硬件随机数发生器 文章目录 STM32 硬件随机数发生器前言第1章 随机数发生器简介1.1 RNG主要特性1.2.RNG应用 第2章 RNG原理框图第3章 RNG相关寄存器3.1 RNG 控制寄存器 (RNG_CR)3.2 RNG 状态寄存器 (RNG_SR)3.3 RNG 数据寄存器 (RNG_DR) 第3章 RNG代码部分第4章 STM32F1 …...

Window环境下使用go编译grpc最新教程

网上的grpc教程都或多或少有些老或者有些问题&#xff0c;导致最后执行生成文件时会报很多错。这里给出个人实践出可执行的编译命令与碰到的报错与解决方法。&#xff08;ps:本文代码按照煎鱼的教程编写&#xff1a;4.2 gRPC Client and Server - 跟煎鱼学 Go (gitbook.io)&…...

STM32——FLASH(1)简单介绍、分类、读写流程及注意事项

文章目录 FLASH的特点Nor flash和nand flashflash的读写flash 的存储单位 flash的读写过程 FLASH的特点 可擦写数据可修改可重写访问速度<ROM Nor flash和nand flash Nor flash 1、与SDRAM相似&#xff0c;用户可以直接运行装载到NORFLASH里面的代码&#xff0c;减少SRAM…...

MySQL的DML语言

DML&#xff1a;Data Manipulation Language&#xff08;数据操作语言&#xff09; DML语言用来对数据库中表的数据记录进行增、删、改操作。 一、添加数据命令 注意&#xff1a; 插入数据时&#xff0c;指定的字段顺序需要与值的顺序是一一对应的。 字符串和日期型数据应该包…...

Vivado-IP核

Vivado-IP核 主程序 timescale 1ns / 1ps ////module ip_clk_wiz(input sys_clk,input sys_rst_n,output clk_out1,output clk_out2,output clk_out3,output clk_out4,output locked);clk_wiz_0 instance_name(// Clock out ports.clk_out1(clk_out1), // output clk_out…...

品牌如何营造生活感氛围?媒介盒子分享

「生活感」简而言之是指人们对生活的感受和意义&#xff0c;它往往没有充斥在各种重要的场合和事件中&#xff0c;而是更隐藏在细碎平凡的生活场景中。在营销越来越同质化的当下&#xff0c;品牌应该如何打破常规模式&#xff0c;洞察消费情绪&#xff0c;找到更能打动消费者心…...

Java 学习和实践笔记(2)

今天的学习进度&#xff1a; 注册并下载安装好了Java 8&#xff0c;之后进行以下配置。 1&#xff09;path 是一个常见的环境变量&#xff0c;它告诉系统除了在当前的目标下妹寻找此程序外&#xff0c;还可以到path指定的目录下找。这句话是什么意思呢&#xff1f;以下举报例…...

Python:批量url链接保存为PDF

我的数据是先把url链接获取到存入excel中&#xff0c;后续对excel做的处理&#xff0c;各位也可以直接在程序中做处理&#xff0c;下面就是针对excel中的链接做批量处理 excel内容格式如下&#xff08;涉及具体数据做了隐藏&#xff09; 标题文件链接文件日期网页标题1http://…...

【LeetCode每日一题】525连续数组 303区域和检索(前缀和的基本概念和3个简单案例)

前缀和 // 构造prefix let prefix [0] arr.forEach(num > {prefix.push(prefix.at(-1) num); })如果想要计算某个区间 i 到 j 这个子数组的和时&#xff0c;可以根据 prefix[j1] - prefix[i] 获得。 例题1&#xff1a;303.区域和检索 - 数组不可变 给定一个整数数组 num…...

形态学算法应用之连通分量提取的python实现——图像处理

原理 连通分量提取是图像处理和计算机视觉中的一项基本任务&#xff0c;旨在识别图像中所有连通区域&#xff0c;并将它们作为独立对象处理。在二值图像中&#xff0c;连通分量通常指的是所有连接在一起的前景像素集合。这里的“连接”可以根据四连通或八连通的邻接关系来定义…...

Kafka系列之:Kafka集群同时设置基于时间和日志大小两种方式保存Topic的数据

Kafka系列之:Kafka集群同时设置基于时间和日志大小两种方式保存Topic的数据 一、基于日志大小二、基于时间大小三、参数设置四、设置命令一、基于日志大小 "log.retention.bytes"是Apache Kafka中的一项配置参数,用于指定每个日志段文件的最大大小。当日志段文件的…...

pytest+allure批量执行测试用例

在 Pytest 中,可以使用装饰器 `@pytest.fixture` 来定义用例级别的前置和后置操作。下面是一个示例代码,演示了如何使用 Pytest 的前置和后置操作: ```python import pytest @pytest.fixture(scope="function") def setup_function(): print("Setup fu…...

SpringBoot和SpringMVC

目录 一、springboot项目 &#xff08;1&#xff09;创建springboot项目 &#xff08;2&#xff09;目录介绍 &#xff08;3&#xff09;项目启动 &#xff08;4&#xff09;运行一个程序 &#xff08;5&#xff09;通过其他方式创建和运行springboot项目 二、SpringMVC…...

免费搭建幻兽帕鲁服务器,白嫖阿里云游戏服务器

阿里云幻兽帕鲁服务器免费搭建方案&#xff0c;先在阿里云高校计划「云工开物」活动领取学生专享300元无门槛代金券&#xff0c;幻兽帕鲁专用服务器4核16G配置26元1个月、149元半年&#xff0c;直接使用这个无门槛300元代金券抵扣即可免费搭建幻兽帕鲁服务器。阿里云服务器网al…...

[技术杂谈]如何下载vscode历史版本

网站模板&#xff1a; https://code.visualstudio.com/updates/v1_85 如果你想下载1.84系列可以访问https://code.visualstudio.com/updates/v1_84​​​​​​ 然后看到&#xff1a; 选择对应版本下载即可&#xff0c;我是windows x64系统选择x64即可开始下载...

nginx slice模块的使用和源码分析

文章目录 1. 为什么需要ngx_http_slice_module2. 配置指令3. 加载模块4. 源码分析4.1 指令分析4.2 模块初始化4.3 slice模块的上下文4.2 $slice_range字段值获取4.3 http header过滤处理4.4 http body过滤处理5 测试和验证 1. 为什么需要ngx_http_slice_module 顾名思义&#…...

AI应用开发-python实现redis数据存储

AI应用开发相关目录 本专栏包括AI应用开发相关内容分享&#xff0c;包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 AI应用开发流程概…...

2024年Java架构篇之设计模式

2024年Java实战面试题_java 5 年 面试-CSDN博客 1、单例模式...

搭建macOS开发环境-1:准备工作

请记住&#xff1a; 最重要的准备工作永远是&#xff1a;备份数据 !!! 通过图形界面检查 Mac 的 CPU 类型&#xff1a; 在搭载 Apple 芯片的 Mac 电脑上&#xff0c;“关于本机”会显示一个标有“芯片”的项目并跟有相应芯片的名称&#xff1a; 通过命令行检查Mac的CPU类型 …...

【Makefile语法 02】Makefile语法基础

目录 一、Makefile概述 二、Makefile变量 三、Makefile符号 一、Makefile格式 1. 基本格式&#xff1a; targets : prerequisties [tab键]command target&#xff1a;目标文件&#xff0c;可以是 OjectFile&#xff0c;也可以是执行文件&#xff0c;还可以是一个标签&…...

如何写一个其他人可以使用的GitHub Action

前言 在GitHub中&#xff0c;你肯定会使用GitHub Actions自动部署一个项目到GitHub Page上&#xff0c;在这个过程中总要使用workflows工作流&#xff0c;并在其中使用action&#xff0c;在这个使用的过程中&#xff0c;总会好奇怎么去写一个action呢&#xff0c;所以&#xff…...

排序算法的时间复杂度存在下界问题

对于几种常用的排序算法&#xff0c;无论是归并排序、快速排序、以及更加常见的冒泡排序等&#xff0c;这些排序算法的时间复杂度都是大于等于O(n*lg(n))的&#xff0c;而这些排序算法存在一个共同的行为&#xff0c;那就是这些算法在对元素进行排序的时候&#xff0c;都会进行…...

详解洛谷P2016 战略游戏/BZOJ0495. 树的最小点覆盖之战略游戏(贪心/树形DP)

Description Bob喜欢玩电脑游戏&#xff0c;特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。 他要建立一个古城堡&#xff0c;城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵&#xff0c;使得这些士兵能了望到所有的路。 注意&…...

解决The Tomcat connector configured to listen on port 8080 failed to start

问题 启动javar报错&#xff0c;提示如下 Description: The Tomcat connector configured to listen on port 8080 failed to start. The port may already be in use or the connector may be misconfigured. Action: Verify the connector’s configuration, identify a…...

深度学习自然语言处理(NLP)模型BERT:从理论到Pytorch实战

文章目录 深度学习自然语言处理&#xff08;NLP&#xff09;模型BERT&#xff1a;从理论到Pytorch实战一、引言传统NLP技术概览规则和模式匹配基于统计的方法词嵌入和分布式表示循环神经网络&#xff08;RNN&#xff09;与长短时记忆网络&#xff08;LSTM&#xff09;Transform…...

C语言的循环结构

目录 前言 1.三种循环语句 1.while循环 2.for循环 2.1缺少表达式的情况 3.do while循环 2.break语句和continue语句 2.1在while循环中 2.2在for循环中 2.3在do while 循环中 3.循环的嵌套 4.go to语句 前言 C语⾔是结构化的程序设计语⾔&#xff0c;这⾥的结构指的是…...

C#用Array类的FindAll方法和List<T>类的Add方法按关键词在数组中检索元素并输出

目录 一、使用的方法 1. Array.FindAll(T[], Predicate) 方法 &#xff08;1&#xff09;定义 &#xff08;2&#xff09;示例 2.List类的常用方法 &#xff08;1&#xff09;List.Add(T) 方法 &#xff08;2&#xff09;List.RemoveAt(Int32) 方法 &#xff08;3&…...

【前后端接口AES+RSA混合加解密详解(vue+SpringBoot)附完整源码】

前后端接口AES+RSA混合加解密详解(vue+SpringBoot) 前后端接口AES+RSA混合加解密一、AES加密原理和为什么不使用AES加密二、RSA加密原理和为什么不使用rsa加密三、AES和RSA混合加密的原理四、代码样例前端1. 请求增加加密标识2. 前端加密工具类3.前端axios请求统一封装,和返…...

React环境配置

1.安装Node.js Node.js官网&#xff1a;https://nodejs.org/en/ 下载之后按默认选项安装好 重启电脑即可自动完成配置 2.安装React 国内使用 npm 速度很慢&#xff0c;可以使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm。 ①使用 winR 输入 cmd 打开终端 ②依…...

Pandas 数据处理-排序与排名的深度探索【第69篇—python:文本数据处理】

文章目录 Pandas 数据处理-排序与排名的深度探索1. sort_index方法2. sort_values方法3. rank方法4. 多列排序5. 排名方法的参数详解6. 处理重复值7. 对索引进行排名8. 多级索引排序与排名9. 更高级的排序自定义10. 性能优化技巧10.1 使用nsmallest和nlargest10.2 使用sort_val…...

第8节、双电机多段直线运动【51单片机+L298N步进电机系列教程】

↑↑↑点击上方【目录】&#xff0c;查看本系列全部文章 摘要&#xff1a;前面章节主要介绍了bresenham直线插值运动&#xff0c;本节内容介绍让两个电机完成连续的直线运动,目标是画一个正五角星 一、五角星图介绍 五角星总共10条直线&#xff0c;10个顶点。设定左下角为原点…...

Elasticsearch:基本 CRUD 操作 - Python

在我之前的文章 “Elasticsearch&#xff1a;关于在 Python 中使用 Elasticsearch 你需要知道的一切 - 8.x”&#xff0c;我详细讲述了如何建立 Elasticsearch 的客户端连接。我们也详述了如何对数据的写入及一些基本操作。在今天的文章中&#xff0c;我们针对数据的 CRUD (cre…...

1992-2022年全国及31省对外开放度测算数据(含原始数据+计算结果)(无缺失)

1992-2022年全国及31省对外开放度测算数据&#xff08;含原始数据计算结果&#xff09;&#xff08;无缺失&#xff09; 1、时间&#xff1a;1992-2022年 2、来源&#xff1a;各省年鉴、国家统计局、统计公报、 3、指标&#xff1a;进出口总额&#xff08;万美元&#xff09…...