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 实现远程监控摄像头在网页端显示
项目场景: 项目需求,需要做一个基于边缘端的人脸识别远程监控摄像头并在网页前端展示 ,这里采用国产香橙派作为边缘计算终端,安装ubuntu系统,系统中采用v4l2接口对摄像头进行获取,当客户端通过网页进行请求…...
《编码——隐匿在计算机软硬件背后的语言》精炼——第15-16章(十六进制,RAM)
“学习如春起之苗,不见其增,日有所长。” —— 宋代朱熹 文章目录 十六进制十六进制概述十六进制表字节到十六进制 存储器特定的读功能特定的写功能RAM大型RAM阵列 十六进制 十六进制概述 十六进制是一种适用于计算机的进制法。在十进制中,…...
leetcode.1376 通知所有员工所需的时间 - bfs/dfs + 树
1376. 通知所有员工所需的时间 目录 一、bfs 二、dfs 题目: 公司里有 n 名员工,每个员工的 ID 都是独一无二的,编号从 0 到 n - 1。公司的总负责人通过 headID 进行标识。在 manager 数组中,每个员工都有一个直属负责人&#x…...
AtCoder Beginner Contest 300——A-G题讲解
蒟蒻来讲题,还望大家喜。若哪有问题,大家尽可提! Hello, 大家好哇!本初中生蒟蒻讲解一下AtCoder Beginner Contest 300这场比赛的A-G题! A - N-choice question 原题 Problem Statement Given integers A A A and…...
Go:值与指针
1. 计算机中的值 在百万年的演化历史中,人类对事物的属性进行了抽象,有了数量、精度、信息等概念的表示,对应的我们称之为整数、小数、文本文字等。计算机出现后,我们使用计算机对真实世界的问题进行建模,通过计算机的…...
【Linux】进程学习(2)---理解进程操作
文章目录 查看进程通过系统目录查看通过ps命令查看 通过系统调用获取进程标识符通过系统调用创建进程初识fork函数fork函数的返回值 进程状态阻塞与运行状态Linux内核源码中的进程状态运行状态-R浅度睡眠状态-S深度睡眠状态-D暂停状态-T僵尸状态-Z死亡状态-X 查看进程 通过系统…...
基于springcloud实现的医院信息系统
访问【WRITE-BUG数字空间】_[内附完整源码和文档] 医疗信息就诊系统,系统主要功能按照数据流量、流向及处理过程分为临床诊疗、药品管理、财务管理、患者管理。诊疗活动由各工作站配合完成,并将临床信息进行整理、处理、汇总、统计、分析等。本系统包括以…...
设计模式-创建型模式-(工厂、简单工厂、抽象工厂)
一、简单工厂模式 上代码 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 服务器和反向代理服务器,它…...
Linux设备驱动模型(一)
一、sysfs文件系统 sysfs是一个虚拟文件系统,将内核总的设备对象的链接关系,以文件目录的方式表示出来,并提对设备提供读写接口。 二、kobject kobject是内核中对象表示的基类,可以认为所有的内核对象都是一个kobject kobject单…...
【Python入门篇】——Python基础语法(标识符与运算符)
作者简介: 辭七七,目前大一,正在学习C/C,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: Python入门,本专栏主要内容为Python的基础语法,Python中的选择循环语句…...
扩展 VirtualBox 已分配磁盘的方法
扩展 VirtualBox 已分配磁盘的方法 第一步:用VirtualBox命令行调整已分配磁盘的大小第二步:用windows磁盘管理工具扩展磁盘空间其他无关配置如何选择虚拟机的芯片组 注意:扩展操作只支持 vdi 格式的磁盘,就是VirtualBox自己的磁盘…...
【LeetCode】646. 最长数对链
646. 最长数对链(中等) 思路 这道题和 300. 最长递增子序列 类似,我们可以定义 dp 数组,其中 dp[i] 表示以 i 结尾的子序列的性质。在处理好每个位置后,统计一遍各个位置的结果即可得到题目要求的结果。 但是题目中强…...
Makefile教程(Makefile的结构)
文章目录 前言一、Makefile的结构二、深入案例三、Makefile中的一些技巧总结 前言 一、Makefile的结构 Makefile 通常由一系列规则组成,每条规则定义了如何从源文件生成目标文件。每个规则又由目标、依赖和命令三部分组成。 下面是 Makefile 规则的基本结构&…...
SpringMVC(后)SSM整合
10、文件上传和下载 10.1、文件下载 ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文 使用ResponseEntity实现下载文件的功能 RequestMapping("/testDown") public ResponseEntity<byte[]> testResp…...
【博弈论】【第一章】博弈论导论
博弈论导论 【例题】选择数字【例题】巴什博弈【例题】射手博弈博弈论的基本概念:参与人战略行动信息支付函数【例题】分100元 课程概述: 【例题】选择数字 两个参与人A和B,轮流选择[3,4,5,6,7,8,9]中的一个整数(可重复)。当累计…...
keil移植linux(makefile)
文章目录 运行环境:1.1 freeRTOS_LED工程移植1)修改cubeMX配置2)setting设置3)launch设置4)修改makefile5)修改代码6)实验效果 运行环境: ubuntu18.04.melodic 宏基暗影骑士笔记本 stm32f427IIH6 stlink 9-24v可调电源 robomaster A 板 1.1 freeRTOS_L…...
C++——类和对象(3)
作者:几冬雪来 时间:2023年5月6日 内容:C类和对象内容讲解 目录 前言: 1.运算符重载(续): 2.赋值重载: 结尾: 前言: 在上一篇博客中我们再一次讲解了…...
itop-3568开发板驱动学习笔记(24)设备树(三)时钟实例分析
《【北京迅为】itop-3568开发板驱动开发指南.pdf》 学习笔记 文章目录 生产者属性#clock-cells 属性clock-output-namesclock-frequencyassigned-clockclock-indicesassigned-clock-parents 消费者属性 设备树中的时钟信息以时钟树形式体现,时钟树包括时钟的属性和结…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
