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

Linux + 香橙派 + V4L2 + http 实现远程监控摄像头在网页端显示

项目场景:

项目需求,需要做一个基于边缘端的人脸识别远程监控摄像头并在网页前端展示 ,这里采用国产香橙派作为边缘计算终端,安装ubuntu系统,系统中采用v4l2接口对摄像头进行获取,当客户端通过网页进行请求时,服务器通过http服务的形式将一帧帧图像发送给客户端,只要一秒钟能够传送25帧左右,展示效果就是在网页端播放视频:


问题描述1

怎样从摄像头里面获取帧数据,这里我们将USB摄像头连接在开发板上:

 可以看到,确实是有video0这个摄像头,该摄像头就是外接的USB摄像头


解决方案1:

采用V4L2接口通过中断将内核状态读取到的数据映射到用户空间:

 以下代码是将内核空间与用户空间进行映射

for(int i = 0; i <4;i++) {mapbuffer.index = i;ret = ioctl(fd,VIDIOC_QUERYBUF,&mapbuffer); //从内核空间中查询一个空间作映射if (ret < 0){perror("查询内核空间失败");}//映射到用户空间mptr[i] = (unsigned char *)mmap(NULL,mapbuffer.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,mapbuffer.m.offset);size[i] = mapbuffer.length; //保存映射长度用于后期释放//查询后通知内核已经放回ret = ioctl(fd,VIDIOC_QBUF,&mapbuffer);if (ret < 0){perror("放回失败");}}

以下代码是通过中断获取内核态的数据,并在用户态对数据进行内存拷贝,即将数据拷贝到数组,方便其他线程进行数据处理和数据展示

struct v4l2_buffer readbuffer;readbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //每个结构体都需要设置type为这个参赛要记住ret = ioctl(fd,VIDIOC_DQBUF,&readbuffer);int read_len = mapbuffer.length;int send_len = 1024;//printf("%d \n",read_len);if (ret < 0){perror("读取数据失败");}if(1){void *ptr = mptr[readbuffer.index];memcpy(jpg_buff, ptr, readbuffer.length); 
}

问题描述2

在网页前端播放视频,首先视频是一帧帧图像组成的,这里我们每间隔一个短时间就发送一帧,同时http 客户端和服务端采用keep-live长连接形式。为了加快速度,这里我采用了两个线程,现成1读取视频,并将图像帧放在一个公共数组中,线程2将公共数组中的数据通过tcp传输发送给客户端。

同时,线程1和线程之间采用的是条件变量进行同步


解决方案2:

多线程共享全局变量加快视频读取速度和图像发送速度:

线程1

 pthread_mutex_lock(&lock);void *ptr = mptr[readbuffer.index];memcpy(jpg_buff, ptr, readbuffer.length);//将读取到的图像拷贝到字符数组       pthread_mutex_unlock(&lock);pthread_cond_signal(&hasNode);

线程2

pthread_cond_wait(&hasNode,&lock);
void *ppptr = jpg_buff;
pthread_mutex_unlock(&lock);

这里的jpg_buff是共享全局数组 


问题描述3

网页长连接设置问题

服务器端在返回报文头时,加上

"Content-Type:multipart/x-mixed-replace;

即表示当前连接是基于长连接


解决方案:

提示:这里填写该问题的具体解决方案:

下面是报文头的内容 

/*
HTTP长连接处理客户端请求
"HTTP/1.0 200 OK\r\n"
"Server: wbyq\r\n"
"Content-Type:multipart/x-mixed-replace;boundary=boundarydonotcross\r\n"
"\r\n"
"--boundarydonotcross\r\n"
*/

这是程序运行时的效果图:

需要在与开发板同一个局域网的终端上网址中键入:192.168.0.105:8080

其中192.168.0.105是开发板的ip地址 

 

最后附上总代码

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <assert.h>
#include <fcntl.h>
#include <jpeglib.h>
#include <linux/fb.h>
#include <linux/videodev2.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <pthread.h>
#include "sd_usb_pic.h"
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/types.h>          /* See NOTES */
#include <unistd.h>
#include <sys/time.h>#define HTTP_PORT 8080   //HTTP服务器端口号
pthread_mutex_t mutex;
pthread_cond_t hasNode = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
char jpg_buff[614400]; //保存从USB摄像头读取的图像矩阵
int send_html_cnt = 0 ;
/*
服务端响应客户端请求"HTTP/1.1 200 OK\r\n"
"Content-type:image/jpeg\r\n"
"Content-Length:1234\r\n"
"\r\n"形参:c_fd  --客户端套接字type  --文件类型file  --要发送的文件
返回值:0成功,其它失败
*/
void *ppp_tr = NULL;
int fd_fb;                                                    
static struct fb_var_screeninfo var; /* LCD可变参数 */
static unsigned int *fb_base = NULL; /* Framebuffer映射基地址 */                    
int lcd_w = 800 ,lcd_h= 480; //定义显示器分辨率/*
形参:c_fd  --客户端套接字type  --文件类型file  --要发送的文件
返回值:0成功,其它失败
*/
int Http_SendData(int c_fd,const char *type,const char *file)
{int fd=open(file,O_RDONLY);//打开文件if(fd<0)return -1;//打开文件失败struct stat statbuf;fstat(fd,&statbuf);if(statbuf.st_size<=0){close(fd);return -2;}char buff[1024]={0};snprintf(buff,sizeof(buff),"HTTP/1.1 200 OK\r\n""Content-type:%s\r\n""Content-Length:%ld\r\n""\r\n",type,statbuf.st_size);if(write(c_fd,buff,strlen(buff))!=strlen(buff)){close(fd);return -3;//发送数据头失败}/*发送文件内容*/int size;while(1){size=read(fd,buff,sizeof(buff));if(write(c_fd,buff,size)!=size)break;//发送失败if(size!=sizeof(buff))break;//发送完成}close(fd);return 0;
}int Http_SendPic(int c_fd,const char *type,const char *file)
{char buff[1024]={0};snprintf(buff,sizeof(buff),"HTTP/1.1 200 OK\r\n""Content-type:%s\r\n""Content-Length:%ld\r\n""\r\n",type,614400);if(write(c_fd,buff,strlen(buff))!=strlen(buff)){return -3;//发送数据头失败}/*发送文件内容*/int size;int cnt = 0 ; pthread_mutex_lock(&mutex);void *ppptr = jpg_buff;while(1){int size= 1024;int wt_len = write(c_fd,ppptr,size);//发送失败cnt += wt_len ; ppptr += wt_len ; if(cnt >= 614400  ) {break;}//发送完成}pthread_mutex_unlock(&mutex);return 0;
}int Http_SendPic1(int c_fd,const char *type,const char *file)
{char buff[1024]={0};snprintf(buff,sizeof(buff),"HTTP/1.1 200 OK\r\n""Server:LiMeng \r\n""Content-type:image/jpeg\r\n""Content-Length:%ld\r\n""\r\n",614400);if(write(c_fd,buff,strlen(buff))!=strlen(buff)){return -3;//发送数据头失败}/*发送文件内容*/int size;int cnt = 0 ; pthread_mutex_lock(&mutex);void *ppptr = jpg_buff;while(1){int size= 1024;int wt_len = write(c_fd,ppptr,size);//发送失败cnt += wt_len ; ppptr += wt_len ; if(cnt >= 614400  ) {break;}//发送完成}pthread_mutex_unlock(&mutex);return 0;
}/*
HTTP长连接处理客户端请求
"HTTP/1.0 200 OK\r\n"
"Server: wbyq\r\n"
"Content-Type:multipart/x-mixed-replace;boundary=boundarydonotcross\r\n"
"\r\n"
"--boundarydonotcross\r\n"
*/int Http_Content(int c_fd)
{char buff[1024]={0};/*建立长连接*/snprintf(buff,sizeof(buff),"HTTP/1.0 200 OK\r\n""Server: wbyq\r\n""Content-Type:multipart/x-mixed-replace;boundary=boundarydonotcross\r\n""\r\n""--boundarydonotcross\r\n");if(write(c_fd,buff,strlen(buff))!=strlen(buff))return -1;//发送报文头失败int jpe_image_size = 614400;//保存jpeg图像大小//int send_html_cnt = 0 ;clock_t t1;t1 = clock();char save_name[10];int save_idx = 0 ;struct timeval start_time, end_time;while(1){//auto beg = clock();t1 = clock();pthread_cond_wait(&hasNode,&lock);//printf("wait time is %d us \n",  (clock() - t1)   ); auto beg = clock();gettimeofday(&start_time, NULL);/*(1)响应报文头"Content-type:image/jpeg\r\n""Content-Length:666\r\n""\r\n"*/snprintf(buff,sizeof(buff),	"Content-type:image/jpeg\r\n""Content-Length:%d\r\n""\r\n",jpe_image_size);if(write(c_fd,buff,strlen(buff))!=strlen(buff)){return -2;//响应报文头失败}/*发送jpg图像数据*///pthread_mutex_lock(&mutex);//互斥锁上锁//pthread_cond_wait(&hasNode,&lock);void *ppptr = jpg_buff;//void *ppptr = ppp_tr;//sprintf(save_name,"my_%d.jpg",save_idx++);//FILE *file=fopen(save_name, "w");//fwrite(ppptr , 614400, 1,file);//close(file);int cnt = 0 ; while(1){int size= 1024 * 600;//int size= 1024 ;int wt_len = write(c_fd,ppptr,size);//发送失败cnt += wt_len ; ppptr += wt_len ; if(cnt >= 614400  ) {break;}//发送完成}  //pthread_mutex_unlock(&mutex);//互斥锁上锁//pthread_mutex_unlock(&lock);//sleep(20);/*(3)发送间隔字符串"\r\n""--boundarydonotcross\r\n"*/strcpy(buff,"\r\n--boundarydonotcross\r\n");if(write(c_fd,buff,strlen(buff))!=strlen(buff)){break;//发送间隔符失败}auto end = clock();gettimeofday(&end_time, NULL);double timeuse = (end_time.tv_sec - start_time.tv_sec) + (double)(end_time.tv_usec - start_time.tv_usec) / 1000000.0;//printf("sendtime is %d us \n",  (end - beg)   ); //printf("send cnt is %d us \n",  send_html_cnt   ); send_html_cnt++;//pthread_mutex_unlock(&lock);//usleep(40000);//auto beg = clock();//printf("sendtime is %d ms \n",  (end - beg)   ); printf("sendtime is %d ms \n",  timeuse   ); pthread_mutex_unlock(&lock);usleep(1);}return -4;//发送图像数据失败
}/*线程工作函数*/
void *pth_work(void *arg)
{int c_fd=*(int *)arg;free(arg);char buff[1024]={0};int size;size=read(c_fd,buff,sizeof(buff)-1);if(size<=0){close(c_fd);pthread_exit(NULL);}buff[size]='\0';printf("buff=%s\n",buff);if(strstr(buff,"GET / HTTP/1.1"))//请求网页文件{Http_SendData(c_fd,"text/html","./html/image.html");}else if(strstr(buff,"GET /1.bmp HTTP/1.1")){Http_SendData(c_fd,"application/x-bmp","./html/1.bmp");}else if(strstr(buff,"GET /my.jpg HTTP/1.1")){//Http_SendData(c_fd,"application/x-jpg","./html/my.jpg");//Http_SendPic(c_fd,"application/x-jpg","./html/my.jpg");Http_Content(c_fd);}else if(strstr(buff,"GET /my_32.jpg HTTP/1.1")){Http_SendData(c_fd,"application/x-bmp","./html/my_32.jpg");}else if(strstr(buff,"GET /100.bmp HTTP/1.1")){Http_SendData(c_fd,"application/x-bmp","./html/100.bmp");}else if(strstr(buff,"GET /favicon.ico HTTP/1.1")){Http_SendData(c_fd,"image/x-icon","./html/wmp.ico");}else{Http_SendData(c_fd,"application/x-jpg","./html/limeng.jpg");//Http_SendData(c_fd,"application/x-bmp","./html/my.jpg");}close(c_fd);//printf("22222222222222222222222   \n");pthread_exit(NULL);
}int generate_pic() 
{int fd = open("/dev/video0",O_RDWR); //打开摄像头设备if (fd < 0){perror("打开设备失败");return -1;}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_MJPEG; //设置视频采集格式为mjpg格式int ret = ioctl(fd,VIDIOC_S_FMT,&vfmt);if (ret < 0){perror("设置格式失败1");}//申请内核空间struct v4l2_requestbuffers reqbuffer;reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuffer.count = 4; //申请4个缓冲区reqbuffer.memory = V4L2_MEMORY_MMAP;  //映射方式ret = ioctl(fd,VIDIOC_REQBUFS,&reqbuffer);if (ret < 0){perror("申请空间失败");}//映射unsigned char *mptr[4];//保存映射后用户空间的首地址unsigned int size[4];struct v4l2_buffer mapbuffer;//初始化type和indexmapbuffer.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("查询内核空间失败");}//映射到用户空间mptr[i] = (unsigned char *)mmap(NULL,mapbuffer.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,mapbuffer.m.offset);size[i] = mapbuffer.length; //保存映射长度用于后期释放//查询后通知内核已经放回ret = ioctl(fd,VIDIOC_QBUF,&mapbuffer); if (ret < 0){perror("放回失败");}}//开始采集int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ret = ioctl(fd,VIDIOC_STREAMON,&type); if (ret < 0){ perror("开启失败");}//定义一个空间存储解码后的rgbint sum = 0;//这里是用来控制读取的帧的数量 实际场景下 可以不要这个限制int read_cnt = 0 ;//记录读取图像线程char save_name[10];int save_idx = 0 ;struct timeval start_time, end_time;while(1){struct v4l2_buffer readbuffer;readbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //每个结构体都需要设置type为这个参赛要记住ret = ioctl(fd,VIDIOC_DQBUF,&readbuffer); int read_len = mapbuffer.length;int send_len = 1024;//printf("%d \n",read_len);if (ret < 0){perror("读取数据失败");}if(1){//void *ptr = mptr[readbuffer.index];//pthread_mutex_lock(&mutex);//gettimeofday(&start_time, NULL);pthread_mutex_lock(&lock);void *ptr = mptr[readbuffer.index];///ppp_tr = mptr[readbuffer.index];//auto beg = clock();//printf("read frame %d \n",beg);//printf("read frame %d  %d  %d \n",read_cnt++,send_html_cnt,beg);//pthread_mutex_lock(&mutex);memcpy(jpg_buff, ptr, readbuffer.length);//将读取到的图像拷贝到字符数组//ppp_tr = ptr ; //auto end  = clock();//gettimeofday(&end_time, NULL);//double timeuse = (end_time.tv_sec - start_time.tv_sec) + (double)(end_time.tv_usec - start_time.tv_usec) / 1000000.0;sprintf(save_name,"my_%d.jpg",save_idx++);//int fd = open(save_name,  O_CREAT |O_WRONLY|O_TRUNC,0666);//char buf[1024*600]={0};//FILE *file=fopen(save_name, "w");//fwrite(mptr[readbuffer.index] , readbuffer.length, 1,file);//fwrite(ptr , readbuffer.length, 1,file);//close(file);//write(fd,buf,1024 * 600);//close(fd);pthread_mutex_unlock(&lock);pthread_cond_signal(&hasNode);//gettimeofday(&end_time, NULL);//pthread_mutex_unlock(&mutex);auto end  = clock();//printf("runtime is %f \n",  (end - beg) / CLOCKS_PER_SEC  ); //printf("runtime is %f \n",  (end - beg)   ); printf("runtime is %d ms \n",  timeuse   ); //sleep(20);usleep(1);}//通知内核使用完毕ret = ioctl(fd, VIDIOC_QBUF, &readbuffer);if(ret < 0){perror("放回队列失败");}}//停止采集ret = ioctl(fd,VIDIOC_STREAMOFF,&type);//释放映射for(int i=0; i<4; i)munmap(mptr[i], size[i]);close(fd); //关闭文件return 0;err1:close(fd_fb);return -1;
}void shuijiao()
{struct timeval start_time, end_time;while(1){gettimeofday(&start_time, NULL);pthread_cond_wait(&hasNode,&lock);usleep(10000);pthread_mutex_unlock(&lock);gettimeofday(&end_time, NULL);double timeuse = (end_time.tv_sec - start_time.tv_sec) + (double)(end_time.tv_usec - start_time.tv_usec) / 1000000.0;//printf("shuijiao   time is %f  ms \n",  timeuse * 1000   );}
}int main()
{int sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd==-1){printf("创建网络套接字失败\n");return 0;}/*允许绑定已使用的端口号*/int on = 1;setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));/*绑定端口号*/struct sockaddr_in s_addr={.sin_family=AF_INET,//IPV4.sin_port=htons(HTTP_PORT),.sin_addr.s_addr=INADDR_ANY};if(bind(sockfd,(const struct sockaddr *)&s_addr,sizeof(s_addr))){printf("绑定端口号失败\n");return 0;}/*设置监听数量*/listen(sockfd,100);/*等待客户端连接*/struct sockaddr_in c_addr;socklen_t len=sizeof(c_addr);int c_fd;pthread_t pthid;int *p=NULL;pthread_t pthid1;pthread_create(&pthid1,NULL,generate_pic,NULL);pthread_detach(pthid1);//设置为分离属性//shuijiao();//while(1){shuijiao();}while(1){c_fd=accept(sockfd,(struct sockaddr *)&c_addr,&len);if(c_fd==-1){printf("客户端连接失败\n");continue;}printf("套接字 : %d  连接成功,%s:%d\n",c_fd,inet_ntoa(c_addr.sin_addr),ntohs(c_addr.sin_port));p=malloc(4);*p=c_fd;pthread_create(&pthid,NULL,pth_work,p);pthread_detach(pthid);//设置为分离属性}
}

代码的编译命令是

gcc serv.c -o serv -ljpeg 

相关文章:

Linux + 香橙派 + V4L2 + http 实现远程监控摄像头在网页端显示

项目场景&#xff1a; 项目需求&#xff0c;需要做一个基于边缘端的人脸识别远程监控摄像头并在网页前端展示 &#xff0c;这里采用国产香橙派作为边缘计算终端&#xff0c;安装ubuntu系统&#xff0c;系统中采用v4l2接口对摄像头进行获取&#xff0c;当客户端通过网页进行请求…...

《编码——隐匿在计算机软硬件背后的语言》精炼——第15-16章(十六进制,RAM)

“学习如春起之苗&#xff0c;不见其增&#xff0c;日有所长。” —— 宋代朱熹 文章目录 十六进制十六进制概述十六进制表字节到十六进制 存储器特定的读功能特定的写功能RAM大型RAM阵列 十六进制 十六进制概述 十六进制是一种适用于计算机的进制法。在十进制中&#xff0c;…...

leetcode.1376 通知所有员工所需的时间 - bfs/dfs + 树

1376. 通知所有员工所需的时间 目录 一、bfs 二、dfs 题目&#xff1a; 公司里有 n 名员工&#xff0c;每个员工的 ID 都是独一无二的&#xff0c;编号从 0 到 n - 1。公司的总负责人通过 headID 进行标识。在 manager 数组中&#xff0c;每个员工都有一个直属负责人&#x…...

AtCoder Beginner Contest 300——A-G题讲解

蒟蒻来讲题&#xff0c;还望大家喜。若哪有问题&#xff0c;大家尽可提&#xff01; Hello, 大家好哇&#xff01;本初中生蒟蒻讲解一下AtCoder Beginner Contest 300这场比赛的A-G题&#xff01; A - N-choice question 原题 Problem Statement Given integers A A A and…...

Go:值与指针

1. 计算机中的值 在百万年的演化历史中&#xff0c;人类对事物的属性进行了抽象&#xff0c;有了数量、精度、信息等概念的表示&#xff0c;对应的我们称之为整数、小数、文本文字等。计算机出现后&#xff0c;我们使用计算机对真实世界的问题进行建模&#xff0c;通过计算机的…...

【Linux】进程学习(2)---理解进程操作

文章目录 查看进程通过系统目录查看通过ps命令查看 通过系统调用获取进程标识符通过系统调用创建进程初识fork函数fork函数的返回值 进程状态阻塞与运行状态Linux内核源码中的进程状态运行状态-R浅度睡眠状态-S深度睡眠状态-D暂停状态-T僵尸状态-Z死亡状态-X 查看进程 通过系统…...

基于springcloud实现的医院信息系统

访问【WRITE-BUG数字空间】_[内附完整源码和文档] 医疗信息就诊系统&#xff0c;系统主要功能按照数据流量、流向及处理过程分为临床诊疗、药品管理、财务管理、患者管理。诊疗活动由各工作站配合完成&#xff0c;并将临床信息进行整理、处理、汇总、统计、分析等。本系统包括以…...

设计模式-创建型模式-(工厂、简单工厂、抽象工厂)

一、简单工厂模式 上代码 public class FoodFactory {public static Food makeFood(String name) {if (name.equals("noodle")) {Food noodle new LanZhouNoodle();noodle.addSpicy("more");return noodle;} else if (name.equals("chicken")…...

JAVA12新特性

JAVA12新特性 概述 2019年3月19日,java12正式发布了,总共有8个新的JEP(JDK Enhancement Proposals) JDK 12 is the open-source reference implementation of version 12 of the Java SE12 Platform as specified by by JSR 386 in the Java Community Process. JDK 12 reac…...

Nginx 静态文件、反向代理、负载均衡、缓存、SSL/TLS 加密、gzip 压缩 等等

Nginx的功能 1. 静态文件服务器2. 反向代理服务器3. 负载均衡4. 缓存5. SSL/TLS 加密6. URL 重写7. HTTP/28. WebSocket9. 反向代理缓存10. 安全限制11. gzip 压缩12. 请求限速13. 日志记录14. SSL 证书续订 Nginx 是一个高性能的开源 Web 服务器和反向代理服务器&#xff0c;它…...

Linux设备驱动模型(一)

一、sysfs文件系统 sysfs是一个虚拟文件系统&#xff0c;将内核总的设备对象的链接关系&#xff0c;以文件目录的方式表示出来&#xff0c;并提对设备提供读写接口。 二、kobject kobject是内核中对象表示的基类&#xff0c;可以认为所有的内核对象都是一个kobject kobject单…...

【Python入门篇】——Python基础语法(标识符与运算符)

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; Python入门&#xff0c;本专栏主要内容为Python的基础语法&#xff0c;Python中的选择循环语句…...

扩展 VirtualBox 已分配磁盘的方法

扩展 VirtualBox 已分配磁盘的方法 第一步&#xff1a;用VirtualBox命令行调整已分配磁盘的大小第二步&#xff1a;用windows磁盘管理工具扩展磁盘空间其他无关配置如何选择虚拟机的芯片组 注意&#xff1a;扩展操作只支持 vdi 格式的磁盘&#xff0c;就是VirtualBox自己的磁盘…...

【LeetCode】646. 最长数对链

646. 最长数对链&#xff08;中等&#xff09; 思路 这道题和 300. 最长递增子序列 类似&#xff0c;我们可以定义 dp 数组&#xff0c;其中 dp[i] 表示以 i 结尾的子序列的性质。在处理好每个位置后&#xff0c;统计一遍各个位置的结果即可得到题目要求的结果。 但是题目中强…...

Makefile教程(Makefile的结构)

文章目录 前言一、Makefile的结构二、深入案例三、Makefile中的一些技巧总结 前言 一、Makefile的结构 Makefile 通常由一系列规则组成&#xff0c;每条规则定义了如何从源文件生成目标文件。每个规则又由目标、依赖和命令三部分组成。 下面是 Makefile 规则的基本结构&…...

SpringMVC(后)SSM整合

10、文件上传和下载 10.1、文件下载 ResponseEntity用于控制器方法的返回值类型&#xff0c;该控制器方法的返回值就是响应到浏览器的响应报文 使用ResponseEntity实现下载文件的功能 RequestMapping("/testDown") public ResponseEntity<byte[]> testResp…...

【博弈论】【第一章】博弈论导论

博弈论导论 【例题】选择数字【例题】巴什博弈【例题】射手博弈博弈论的基本概念&#xff1a;参与人战略行动信息支付函数【例题】分100元 课程概述&#xff1a; 【例题】选择数字 两个参与人A和B&#xff0c;轮流选择[3,4,5,6,7,8,9]中的一个整数&#xff08;可重复)。当累计…...

keil移植linux(makefile)

文章目录 运行环境&#xff1a;1.1 freeRTOS_LED工程移植1)修改cubeMX配置2)setting设置3)launch设置4)修改makefile5)修改代码6)实验效果 运行环境&#xff1a; ubuntu18.04.melodic 宏基暗影骑士笔记本 stm32f427IIH6 stlink 9-24v可调电源 robomaster A 板 1.1 freeRTOS_L…...

C++——类和对象(3)

作者&#xff1a;几冬雪来 时间&#xff1a;2023年5月6日 内容&#xff1a;C类和对象内容讲解 目录 前言&#xff1a; 1.运算符重载&#xff08;续&#xff09;&#xff1a; 2.赋值重载&#xff1a; 结尾&#xff1a; 前言&#xff1a; 在上一篇博客中我们再一次讲解了…...

itop-3568开发板驱动学习笔记(24)设备树(三)时钟实例分析

《【北京迅为】itop-3568开发板驱动开发指南.pdf》 学习笔记 文章目录 生产者属性#clock-cells 属性clock-output-namesclock-frequencyassigned-clockclock-indicesassigned-clock-parents 消费者属性 设备树中的时钟信息以时钟树形式体现&#xff0c;时钟树包括时钟的属性和结…...

linux中使用docker部署微服务

目录 一、制作jar包&#xff08;如果看一眼很简单&#xff0c;可以直接使用结尾的jar&#xff09; 1.首先创建一个微服务 demo2 2.启动微服务&#xff08;在DemoApplication上右键执行启动就行&#xff09; 注意&#xff1a;其他操作导致的 可能遇到的报错 3.修改端口 4.新…...

操作系统考试复习—第三章 优先级倒置 死锁问题

当前OS广泛采用优先级调度算法和抢占方式&#xff0c;然而在系统中存在着影响进程运行的资源从而可能产生"优先级倒置"现象 具体解释为&#xff1a;在原本的调度算法设计中&#xff0c;高优先级进程可以抢占低优先级的CPU资源&#xff0c;先执行高优先级任务。但是存…...

OpenHarmony送显流程分析

OpenHarmony送显流程分析 引言 本文档主要记录OpenHarmony在渲染完成之后如何进行合成和送显流程的。这个过程牵涉的代码很多&#xff0c;而且流程也是比较繁琐的。所以我一定要坚持下来。千万不能半途而废&#xff0c;也不要想着一口气吃出一个胖子&#xff0c;路漫漫其修远兮…...

Java面试题字节流字符流

String 编码UTF-8 和GBK的区别 GBK编码&#xff1a;是指中国的中文字符&#xff0c;其实它包含了简体中文与繁体中文字符&#xff0c;另外还有一种字符 “gb2312”&#xff0c;这种字符仅能存储简体中文字符。 UTF-8编码&#xff1a;它是一种全国家通过的一种编码&#x…...

Self-Attention结构细节及计算过程

一、结构 上面那个图其实不是那么重要&#xff0c;只要知道将输入的x矩阵转换成三个矩阵进行计算即可。自注意力结构的输入为 输入矩阵的三个变形 Q&#xff08;query矩阵&#xff09;、K&#xff08;key矩阵&#xff09;、V&#xff08;value矩阵&#xff09;构成&#xff0c;…...

在Ubuntu18.04中安装uWebSockets库

目录 1.下载uWebSockets库2.下载uSockets3.安装openssl开发包4.编译首先说明这里使用的Ubuntu版本为18.04。 1.下载uWebSockets库 下载uWebSockets库有两种方式,一是终端,从Github中克隆uWebSockets库到Ubuntu本地文件夹,二是打开uWebSockets库下载链接自己下载到Windows,然…...

【Fluent】接着上一次计算的结果继续计算,利用计算过程中得到的物理场(温度、速度、压力等)插值Interpolate文件初始化模型的方法

一、问题背景 因为fluent中支持的初始化无非三种类型。 1、Standard initialization 标准初始化 2、Hybridinitialization 混合初始化 3、FMG initialization FMG初始化 另外&#xff0c;还可以用UDF通过坐标判断的方式予以初始化。 但是这些初始化方法都没办法利用以前计算过…...

第二十九章 使用消息订阅发布实现组件通信

PubSubJS库介绍 如果你想在React中使用第三方库来实现Pub/Sub机制&#xff0c;PubSubJS是一个不错的选择。它是一个轻量级的库&#xff0c;可以在浏览器和Node.js环境中使用。 PubSubJS提供了一个简单的API&#xff0c;可以让你在应用程序中订阅和发布消息。你可以使用npm来安…...

Transformer的位置编码

1. 什么是位置编码&#xff0c;为什么要使用位置编码 简单来说位置编码就是给一个句子中的每个token一个位置信息&#xff0c;通过位置编码可以明确token的前后顺序关系。 对任何语言来说&#xff0c;句子中词汇的顺序和位置都是非常重要的。它们定义了语法&#xff0c;从而定…...

Python学习简记

做题时遇到的不知道的知识点会更新在此&#xff1a; python中的int()函数可以用于进制转换 该函数最为常见的使用是用于强制类型转换&#xff0c;实际上&#xff0c;它可以有两个参数 值得强调的是当传入两个参数时第一个参数一定要是字符串类型 字符串方法&#xff1a; lower(…...

打开网站显示404/热门职业培训班

题目大意&#xff1a;有N个矿井 &#xff0c;由一些隧道连接起来&#xff0c;现在要修建尽量少的安全通道&#xff0c;使得无论哪个矿井发生事故&#xff0c;所有人均能逃出&#xff08;其实就是问每个点相互到达至少有两条点不重复的路径&#xff09;&#xff0c;求建的最少的…...

张家界seo网站优化/自己建网站

运算符1.算数运算 运算符 描述 实例 a10&#xff0c;b20 加&#xff0c;两个对象相加 ab输出30 - 减&#xff0c;一个数减去另一个数 a-b输出-10 * 乘&#xff0c;两个数相乘或是返回一个被重复若干次的字符串 a*b输出200 / 除&am…...

在阿里巴巴做网站多少钱2019/企业网站首页

通常我们定义一个基本数据类型的变量&#xff0c;函数调用的现场保存&#xff0c;一个对象的引用&#xff0c;都使用JVM中的栈空间&#xff1b; 通过new关键字和构造器创建的对象放在堆空间&#xff0c;堆是垃圾收集器管理的主要区域&#xff0c;由于现在的垃圾收集器都采用分…...

网上商城网站系统/公关公司

给表新增字段时&#xff0c;可能经常遇到错误&#xff1a;ORA-00054:资源正忙但指定以NOWAIT方式获取资源或者超时失效这种错误出现的情景在oracle 11.1 和 11.2 的版本中有点区别以下实验中 表 &#xff1a;create table hlb (id int); &#xff0c;表中有数据&#xff0c;ddl…...

wordpress 不能自定义主题/自己如何建立网站

android8.1启动过程(七) SystemServer_we1less的博客-CSDN博客 这篇文章说道SystemServer进程主要用于创建系统服务&#xff0c;同时初始化Zygote 调用gCurRuntime->onZygoteInit();本文从这继续解析binder的启动过程。 onZygoteInit AOSP/frameworks/base/cmds/app_pr…...

做网站和做网页/软文发布平台

要快速学会Python&#xff0c;谨记3456这四个数字就可以了。鉴于大多数书籍在编写上都结构混乱&#xff0c;无法体现出知识的系统性、逻辑性和层次性。特整理出学Python最基础的知识学习框架&#xff0c;希望帮助大家快速入门。下面我来描述这四个数字的含义&#xff01;我是按…...