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中交叉编译放到开发板上运行

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

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

相关文章

【 buuctf-面具下的 flag】

直接 binwalk 提取图片内容其中 zip 为伪加密&#xff08;如下图&#xff09;&#xff0c;在 macOS 上当我运行 binwalk -e 指令来提取图片中内容是&#xff0c;zip可以自动解压出来 flag.vmdk&#xff0c;不需要修改压缩源文件目录区的全局方式位标记值。 在 kali Linux 下&am…

RabbitMQ-4.MQ的可靠性

MQ的可靠性 4.MQ的可靠性4.1.数据持久化4.1.1.交换机持久化4.1.2.队列持久化4.1.3.消息持久化 4.2.LazyQueue4.2.1.控制台配置Lazy模式4.2.2.代码配置Lazy模式4.2.3.更新已有队列为lazy模式 4.MQ的可靠性 消息到达MQ以后&#xff0c;如果MQ不能及时保存&#xff0c;也会导致消…

论文阅读-Automated Repair of Programs from Large Language Models

文章主旨&#xff1a;研究了Codex自动生成的程序中的错误&#xff0c;并探讨了现有的程序修复&#xff08;APR&#xff09;工具以及新发布的Codex-e是否能够修复自动生成的有缺陷的程序。 现在基于大语言模型&#xff0c;输入自然语言&#xff0c;生成代码的应用非常普遍。但是…

golang 中间件使用

1、自定义中间件函数 func CustomMiddleware() gin.HandlerFunc {return func(c *gin.Context) {// 在请求之前执行的逻辑fmt.Println("执行自定义中间件 - 请求之前")// 调用链中的下一个处理程序c.Next()// 在请求之后执行的逻辑fmt.Println("执行自定义中间…

立足智能存取解决方案|HEGERLS智能托盘四向车储存制动能量 实现能源回收

对于商业配送和工业生产的企业而言&#xff0c;如何能高效率、低成本进行低分拣、运输、码垛、入库&#xff0c;用以提升仓库空间的利用效率&#xff0c;是现在大多企业急需要解决的行业痛点。对此&#xff0c;为了解决上述痛点&#xff0c;近年来&#xff0c;物流仓储集成商、…

常用TS总结

基本用法 普通 const num: number 10const isStop: boolean falseconst title: string 常用TS总结const curName: null nullconst curType: undefined undefinedconst birthday: Date new Date() 对象 // typetype LoginParams {account: string}// interfaceinterfac…

docker常用10条容器操作命令

Docker 中一些常用的容器操作命令&#xff0c;我们可以根据需要使用这些命令来管理和操作 Docker 容器。我们这次以Hell-world这个镜像为例来说明&#xff1a; 1. docker pull hello-world #拉取hell-world镜像 2. docker images # 查看本地拉取的镜像 3. docker run hello…

Maven:项目无法产生Maven Dependencies且无法update project报cannot nest错误

找自己出错项目的.classpath文件&#xff0c;打开&#xff0c;ctrlf&#xff0c;找是否有以下文件&#xff0c;如果没有在末尾加进去&#xff0c;再refresh项目即可&#xff1a; <classpathentry kind"con" path"org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINE…

【python】绘制爱心图案

以下是一个简单的Python代码示例&#xff0c;它使用turtle模块绘制一个代表爱和情人节的心形图案。 首先&#xff0c;请确保计算机上安装了Python和turtle模块。然后&#xff0c;将以下代码保存到一个.py文件中&#xff0c;运行它就可以看到爱心图案的绘制过程。 import turt…

20240203在Ubuntu20.04.6下配置stable-diffusion-webui.git

20240203在Ubuntu20.04.6下配置stable-diffusion-webui.git 2024/2/3 11:55 【结论&#xff1a;在Ubuntu20.04.6下&#xff0c;生成512x512分辨率的图像&#xff0c;大概需要11秒钟&#xff01;】 前提条件&#xff0c;可以通过技术手段上外网&#xff01;^_首先你要有一张NVID…

2024清洁能源、环境与智慧城市国际研讨会(ISCEESC2024)

2024清洁能源、环境与智慧城市国际研讨会(ISCEESC2024) 会议简介 2024年清洁能源、环境与智慧城市国际研讨会&#xff08;ISCEESC2024&#xff09;将在中国丽江举行。本次会议主要围绕清洁能源、环境和智慧城市等研究领域&#xff0c;旨在为该研究领域的专家学者提供一个国际…

用云手机打造tiktok账号需要注意些什么?

随着tiktok平台的火热&#xff0c;越来越多的商家开始尝试更高效的tiktok运营方法。其中&#xff0c;tiktok云手机作为一种新科技引起了很多人的注意&#xff0c;那么用云手机运营tiktok需要注意些什么&#xff1f;下文将对此进行详细解析。 1. 不是所有的云手机都适合做tiktok…

【分享】如何运用数字I/O来保护继电器

1.简述 在开关系统中&#xff0c;短路或者是开路的情况下&#xff0c;由于存在着额外的电流或者是电压&#xff0c;继电器往往会过载。所有的继电器都有一个最大的承载电流和热切换功率&#xff0c;如果超出了这个范围&#xff0c;会增加继电器焊接在一起的风险&#xff0c;从…

项目02《游戏-10-开发》Unity3D

【完成本集功能后共享1-10集整套代码】 基于 项目02《游戏-09-开发》Unity3D &#xff0c; 任务&#xff1a;传送至其他场景&#xff0c; 首先在场景中加入传送门&#xff0c; 设置人物标签&#xff0c; using UnityEngine; using UnityEngine.SceneManagement; u…

代码随想录算法训练营第三十七天|1049. 最后一块石头的重量 II ,494. 目标和 , 474.一和零

1049. 最后一块石头的重量 II 视频讲解&#xff1a;https://www.bilibili.com/video/BV14M411C7oV https://programmercarl.com/1049.%E6%9C%80%E5%90%8E%E4%B8%80%E5%9D%97%E7%9F%B3%E5%A4%B4%E7%9A%84%E9%87%8D%E9%87%8FII.html 本题其实就是尽量让石头分成重量相同的两堆&a…

2024-02-05(Hive)

1.Hive中抽样表数据 对表进行随机抽样是非常有必要的。 大数据体系下&#xff0c;在真正的企业环境中&#xff0c;很容易出现很大的表&#xff0c;比如体积达到TB级别的。 对这种表一个简单的SELECT * 都会非常的慢&#xff0c;哪怕LIMIT 10想要看10条数据&#xff0c;也会走…

树莓派4b连接WQ9201外置无线网卡命令行配置详解

树莓派4B连接WQ9201无线网卡 接线方式 蓝色的线来连接树莓派和WQ9201demo板&#xff0c;USB接树莓派的USB接口&#xff0c;microUSB一端接demo板靠近天线部分的microUSB口。 驱动和固件准备 驱动直接放在树莓派系统的任意目录&#xff0c;目前配置则是将驱动放在树莓派的主目…

使用PaddleNLP识别垃圾邮件:用BERT做中文邮件内容分类,验证集准确率高达99.6%以上(附公开数据集)

使用PaddleNLP识别垃圾邮件:用BERT做中文邮件内容分类,验证集准确率高达99.6%以上(附公开数据集)。 要使用PaddleNLP和BERT来识别垃圾邮件并做中文邮件内容分类,可以按照以下步骤进行操作: 安装PaddlePaddle和PaddleNLP:首先,确保在你的环境中已经安装了PaddlePaddle和…

《Git 简易速速上手小册》第1章:Git 基础(2024 最新版)

文章目录 1.1 Git 简介&#xff1a;版本控制的演变1.1.1 基础知识讲解1.1.2 重点案例&#xff1a;协作开发流程优化案例&#xff1a;功能开发与分支策略 1.1.3 拓展案例 1&#xff1a;代码审查与合并1.1.4 拓展案例 2&#xff1a;冲突解决 1.2 安装和配置 Git&#xff1a;首次设…

代码随想录算法训练营第41天 | 343.整数拆分 96.不同的二叉搜索树

整数拆分 dp数组的含义&#xff1a;dp[i] 表示将 i 拆分所能得到的最大乘积。递推公式&#xff1a;dp[i] max(dp[i], max(j * (i - j), j * dp[i - j]))。我们对 j 从1开始遍历&#xff0c;检验不同的拆分方式能产生的最大乘积。对于拆分方式的选择&#xff0c;要么拆成 j 和 …