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

ESP32CAM人工智能教学15

ESP32CAM人工智能教学15

Flask服务器TCP连接

小智利用Flask在计算机中创建一个虚拟的网页服务器服务器,让ESP32Cam通过WiFi连接,把摄像头拍摄到的图片发送到电脑中,并在电脑中保存成图片文件。

Flask是用Python编写的网页服务程序WebServer。这个程序首先在电脑端用Python编写一个服务器端的程序,并创建一个指向5000端口的网页服务,用于接收ESP32CAM上传的图片数据,并保存成图片文件。

本来这个程序挺简单的,但是在测试程序时一直都过不了。测试程序耗了我三天时间,最后我采用“蚂蚁啃大象”的方法,采用由简及繁的方法,终于攻下难关。本文的测试主要参考博客内容https://blog.51cto.com/u_16213596/7788901

  • 第一轮给在线网站发信息

首先我们在计算机中,用Python编写一个客户端的测试程序,然后利用requests驱动库,给网上的一个测试网站发送字符信息,http://httpbin.org/post是网上为我们提供的一个学习测试的网站。

我们在测试程序中,创建一个字典d={‘jpg’,’tupian’},然后把信息发送到测试网页。点击菜单上的Run运行,结果在IDLE Shell窗口中,可以看到(第六行)返回了用户发送给网站的信息”jpg”:  ”tupian”。这样表面这个程序的requests的驱动库运行成功了。(当然,运行程序之前,需要在Python中先安装requests的驱动库,安装方法看前一课,可以到清华大学的镜像网站去下载)

  • 第二轮给本地Flask服务器发文字、图片信息

我们在Python中安装Flask驱动库,然后编写服务器端的程序test.py。在程序中创建一个一个网页服务,开放计算机的5000端口,并提供一个上传网页,用于接收客户端发送过来的消息。如图所示:客户端访问http://192.168.1.162:5000/updata可以给服务器端发送消息了。

修改客户端程序test02.py,把上传的地址改成本地的Flask服务器的上传网页地址,然后还是给服务器发送消息”jpg”:  “tupian”。

接下来是运行测试程序,先运行服务器端的程序test.py,可以看到Flask服务器开启了http://192.168.1.162:5000/。接着运行客户端程序test02.py,可以看到服务器端的IDLE Shell窗口显示一条消息,表示接收到了一条来自客户端的消息,并读取消息字典中名为“jpg”的内容,并组成字符串返回给客户端。在客户端的IDLE Shell窗口中看到了服务器返回的字符串”user”:  “tupian”。

接下来这个测试就简单了,首先把客户端中发送的消息“jpg”的内容,更改为一张图片的内容。我们先准备一张图片,命名为333.jpg,和test.py、test02.py一起,都保存在同一个文件夹中(Python的安装目录,我这里是D:\Python312\)。接着,更改服务器端的程序,返回客户端的消息为接收到的数据长度值。

接下来,先运行服务器端的程序,在运行客户端的程序,可以看到在服务器端的Shell看到接收到了数据,在客户端的Shell看到返回的图片文件大小了。这样,这张图片就上传成功了,可以在D:\Python312\中看到两个图片文件:333.jpg是被上传的原图; 555.jpg是上传后保存下的图片, 这个上传过程,就像是左手换右手一样,这两张图的内容是一模一样的。

  • 第三轮ESP32Cam读取内存图片发送给Flask

接下来,我们进行的是跨设备之间的传递,我们让ESP32Cam开发板读取内存中的一张图片的数据,然后通过WiFi连接,把图片数据发送到计算机中的Flask服务器中保存下来。

首先,我们在Thonny中连接ESP32Cam,并且下载一个urequests.py文件(如果没有可以复制后面的相关代码内容,然后在这里粘贴上传),上传到ESP32Cam中。

编写ESP32Cam客户端的程序,先连接WiFi,然后连接到服务器上传网页,读取图片内容,上传数据。需要注意的是,这个urequests.py驱动库文件只能传递二进制的数据,无法传递JSON的字符消息,所以在客户端和服务器端的程序,都有相应的小修改。

我们先在Thonny中上传一张图片到ESP32Cam中。打开服务器端的程序,再运行Thonny中的程序,这样就可以看到ESP32Cam内存中的那张图片,上传到了计算机D:\Python312\文件夹中了,在Thonny的Shell窗口中,看到了服务器程序返回来的图片文件大小的数字了。

  • 第三轮ESP32Cam摄像头拍摄图片发送给Flask

在这个测试中,我们把发送的图片改为摄像头拍摄到了图片,经过运行程序测试,可以看到摄像头拍摄到的图片,发送到了计算机中的D:\Python312\的文件夹中了。

避坑笔迹:之前一直测试的程序也是这个程序,但是就是一直不成功,一直找不到失败的原因,不知道传送的过程中究竟是哪个环节出现了问题,这个问题一直困扰了我三天时间,经过反反复复的测试,就是不成功。

后来我就采用“蚂蚁啃大象”的办法,从最简单的测试开始,尽可能地砍掉了所有的环节,保留最简单的连接通道(第一轮测试:本地客户端程序发送数据到线上的测试网站,保留最简单、最短传输路径的测试,因为网上的测试网站,基本可以忽略存在问题的可能,绝大的概率是正确的)。等第一轮测试通过后,就慢慢增加测试的传输路径长度,一点一点的向着最终的目标慢慢前进,经过几轮的测试,最终完成了ESP32Cam拍摄照片,利用TCP连接,发送到Flask服务器中的程序。

最后的测试成果,与网上的程序(之前一直不通过的)相比,我在摄像头初始化完成的后面,增加了一个0.2秒的延时,等待摄像头拍摄图片,然后在获取图片的数据,这样程序测试就通过了。

这个就是三天摸索的结果,不过最终还是找到了一个解决问题的办法:当程序出现问题的时候,如何化繁为简地进行测试,从最简单开始,一直到实现全部的预定功能。

如果在测试的时候,我们点击Thonny中的运行按钮,可以成功发送一张照片。第二次运行的时候,出现了错误信息,可以拔下ESP32Cam,重新插如电脑中,重新运行程序右可以了。说明这个程序还是有缺陷的,还需要改进。


第一轮测试,Python编写客户端程序,给在线HTTP服务网站发送信息import requests
import binascii, jsondef send_image():url = 'http://httpbin.org/post'd = {'jpg': 'tupian'}r = requests.post(url, data=d)print(r.text)send_image()/
第二轮测试    在电脑中创建两个Python程序,一个做服务器,一个做客户端,
在Python安装目录中,客服端读取333.jpg发送, 服务器端接收保存成555.jpgtest.py   服务器端:from flask import Flask, request
import binasciiapp = Flask(__name__)@app.route("/updata", methods=["POST","GET"])
def updata():print("保存图片1")a = request.form.get('jpg')with open('555.jpg','wb') as f:val = binascii.a2b_base64(a)f.write(val)return ('user:%d' %len(a))if __name__ == "__main__":app.run('0.0.0.0', 5000)test02.py   客户端import requests
import binascii, jsondef send_image():url = 'http://192.168.1.162:5000/updata'with open('333.jpg','rb') as f:img = f.read()img = binascii.b2a_base64(img)d = {'jpg': img}r = requests.post(url, data=d)print(r.text)send_image()/
第三轮测试    ESP32CAM读取内存中的一张照片,发送到Python创建的Flask服务器端from flask import Flask, request
import binasciiapp = Flask(__name__)@app.route("/updata", methods=["POST","GET"])
def updata():print("保存图片1")a = request.get_data()  #直接接收二进制with open('555.jpg','wb') as f:f.write(a)return ('user:%d' %len(a))if __name__ == "__main__":app.run('0.0.0.0', 5000)   ESP32Cam  设备作为客户端import time, networkdef connectWiFi():wlan = network.WLAN(network.STA_IF)if wlan.isconnected():wlan.disconnect()wlan.active(True)wlan.connect('ChinaNet-xxVP', '123456789')while not wlan.isconnected():passprint('network config: ', wlan.ifconfig())connectWiFi()import urequests as requestsdef send_image():url = 'http://192.168.1.162:5000/updata'with open('333.jpg', 'rb') as f:img = f.read()r = requests.post(url, data = img)print(r.text)r.closesend_image()第四轮测试    ESP32CAM拍下一张照片,发送到Python创建的Flask服务器端Python服务器端from flask import Flask, request
import binasciiapp = Flask(__name__)@app.route("/updata", methods=["POST","GET"])
def updata():print("保存图片1")a = request.get_data()  #直接接收二进制with open('555.jpg','wb') as f:f.write(a)return ('user:%d' %len(a))if __name__ == "__main__":app.run('0.0.0.0', 5000)  ESP32Cam客户端  import time, networkdef connectWiFi():wlan = network.WLAN(network.STA_IF)if wlan.isconnected():wlan.disconnect()wlan.active(True)wlan.connect('ChinaNet-xxVP', '123456789')while not wlan.isconnected():passprint('network config: ', wlan.ifconfig())connectWiFi()import camera
import time
import urequests as requestsdef send_image():url = 'http://192.168.1.162:5000/updata'while not camera.init(0):time.sleep(0.2)camera.deinit()time.sleep(0.2)time.sleep(0.2)  #稍作延时,等待拍照img = camera.capture()  # 获取照片camera.deinit()r = requests.post(url, data = img)print(r.text)r.closesend_image()//
/
保存到ESP32Cam中的 urequests.py 驱动库源代码import usocketclass Response:def __init__(self, f):self.raw = fself.encoding = "utf-8"self._cached = Nonedef close(self):if self.raw:self.raw.close()self.raw = Noneself._cached = None@propertydef content(self):if self._cached is None:self._cached = self.raw.read()self.raw.close()self.raw = Nonereturn self._cached@propertydef text(self):return str(self.content, self.encoding)def json(self):import ujsonreturn ujson.loads(self.content)def request(method, url, data=None, json=None, headers={}, stream=None,params=None):try:proto, dummy, host, path = url.split("/", 3)except ValueError:proto, dummy, host = url.split("/", 2)path = ""if proto == "http:":port = 80elif proto == "https:":import usslport = 443else:raise ValueError("Unsupported protocol: " + proto)if ":" in host:host, port = host.split(":", 1)port = int(port)if params:path = path + "?"for k in params:path = path + '&'+k+'='+params[k]ai = usocket.getaddrinfo(host, port)addr = ai[0][4]s = usocket.socket()s.connect(addr)if proto == "https:":s = ussl.wrap_socket(s)s.write(b"%s /%s HTTP/1.0\r\n" % (method, path))if not "Host" in headers:s.write(b"Host: %s\r\n" % host)# Iterate over keys to avoid tuple allocfor k in headers:s.write(k)s.write(b": ")s.write(headers[k])s.write(b"\r\n")if json is not None:assert data is Noneimport ujsondata = ujson.dumps(json)if data:s.write(b"Content-Length: %d\r\n" % len(data))s.write(b"\r\n")if data:s.write(data)l = s.readline()protover, status, msg = l.split(None, 2)status = int(status)#print(protover, status, msg)while True:l = s.readline()if not l or l == b"\r\n":break#print(l)if l.startswith(b"Transfer-Encoding:"):if b"chunked" in l:raise ValueError("Unsupported " + l)elif l.startswith(b"Location:") and not 200 <= status <= 299:raise NotImplementedError("Redirects not yet supported")resp = Response(s)resp.status_code = statusresp.reason = msg.rstrip()return respdef head(url, **kw):return request("HEAD", url, **kw)def get(url, **kw):return request("GET", url, **kw)def post(url, **kw):return request("POST", url, **kw)def put(url, **kw):return request("PUT", url, **kw)def patch(url, **kw):return request("PATCH", url, **kw)def delete(url, **kw):return request("DELETE", url, **kw)

相关文章:

ESP32CAM人工智能教学15

ESP32CAM人工智能教学15 Flask服务器TCP连接 小智利用Flask在计算机中创建一个虚拟的网页服务器服务器&#xff0c;让ESP32Cam通过WiFi连接&#xff0c;把摄像头拍摄到的图片发送到电脑中&#xff0c;并在电脑中保存成图片文件。 Flask是用Python编写的网页服务程序WebServer。…...

Pandas 33个冷知识 0721

Pandas 33个冷知识 从Excel读取数据: 使用 pd.read_excel(file.xlsx) 来读取Excel文件。 写入Excel: 使用 df.to_excel(file.xlsx, indexFalse) 将DataFrame写入Excel文件。 创建日期索引: 使用 df.set_index(pd.to_datetime(df[date])) 创建日期索引。 向后填充缺失值: 使用…...

C++ map和set的使用

目录 0.前言 1.关联式容器 2.键值对 3.树形结构的关联式容器 3.1树形结构的特点 3.2树形结构在关联式容器中的应用 4.set 4.1概念与性质 4.2使用 5.multiset 5.1概念与性质 5.2使用 6.map 6.1概念与性质 6.2使用 7.multimap 7.1概念与性质 7.2使用 8.小结 &a…...

yarn的安装和配置以及更新总结,npm的对照使用差异

1. Yarn简介 Yarn 是一个由 Facebook 开发的现代 JavaScript 包管理器&#xff0c;旨在提供更快、更安全、更可靠的包管理体验。 1.1 什么是Yarn Yarn 是一个快速、可靠和安全的 JavaScript 包管理器&#xff0c;它通过并行化操作和智能缓存机制&#xff0c;显著提升了依赖安…...

【Git命令】git rebase之合并提交记录

使用场景 在本地提交了两个commit&#xff0c;但是发现根本没有没必要分为两次&#xff0c;需要想办法把两次提交合并成一个提交&#xff1b;这个时候可以使用如下命令启动交互式变基会话&#xff1a; git rebase -i HEAD~N这里 N 是你想要重新调整的最近的提交数。 如下在本地…...

为什么品牌需要做 IP 形象?

品牌做IP形象的原因有多方面&#xff0c;这些原因共同构成了IP形象在品牌建设中的重要性和价值&#xff0c;主要原因有以下几个方面&#xff1a; 增强品牌识别度与记忆点&#xff1a; IP形象作为品牌的视觉符号&#xff0c;具有独特性和辨识性&#xff0c;能够在消费者心中留…...

Kubernetes 1.24 版弃用 Dockershim 后如何迁移到 containerd 和 CRI-O

在本系列的上一篇文章中&#xff0c;我们讨论了什么是 CRI 和 OCI&#xff0c;Docker、containerd、CRI-O 之间的区别以及它们的架构等。最近&#xff0c;我们得知 Docker 即将从 kubernetes 中弃用&#xff01;&#xff08;查看 kubernetes 官方的这篇文章&#xff09;那么让我…...

70. 爬楼梯【 力扣(LeetCode) 】

一、题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 二、测试用例 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。 1. 1 阶…...

R语言优雅的把数据基线表(表一)导出到word

基线表&#xff08;Baseline Table&#xff09;是医学研究中常用的一种数据表格&#xff0c;用于在研究开始时呈现参与者的初始特征和状态。这些特征通常包括人口统计学数据、健康状况和疾病史、临床指标、实验室检测、生活方式、社会经济等。 本人在既往文章《scitb包1.6版本发…...

XMl基本操作

引言 使⽤Mybatis的注解⽅式&#xff0c;主要是来完成⼀些简单的增删改查功能. 如果需要实现复杂的SQL功能&#xff0c;建议使⽤XML来配置映射语句&#xff0c;也就是将SQL语句写在XML配置⽂件中. 之前&#xff0c;我们学习了&#xff0c;用注解的方式来实现MyBatis 接下来我们…...

Linux——Shell脚本和Nginx反向代理服务器

1. Linux中的shell脚本【了解】 1.1 什么是shell Shell是一个用C语言编写的程序&#xff0c;它是用户使用Linux的桥梁 Shell 既是一种命令语言&#xff0c;有是一种程序设计语言 Shell是指一种应用程序&#xff0c;这个应用程序提供了一个界面&#xff0c;用户通过这个界面访问…...

pyspark使用 graphframes创建和查询图的方法

1、安装graphframes的步骤 1.1 查看 spark 和 scala版本 在终端输入&#xff1a; spark-shell --version 查看spark 和scala版本 1.2 在maven库中下载对应版本的graphframes https://mvnrepository.com/artifact/graphframes/graphframes 我这里需要的是spark 2.4 scala 2.…...

【web】-flask-简单的计算题(不简单)

打开页面是这样的 初步思路&#xff0c;打开F12&#xff0c;查看头&#xff0c;都发现了这个表达式的base64加密字符串。编写脚本提交答案&#xff0c;发现不对&#xff1b; 无奈点开source发现源代码&#xff0c;是flask,初始化表达式&#xff0c;获取提交的表达式&#xff0…...

Apache Sqoop

Apache Sqoop是一个开源工具&#xff0c;用于在Apache Hadoop和关系型数据库&#xff08;如MySQL、Oracle、PostgreSQL等&#xff09;之间进行数据的批量传输。其主要功能包括&#xff1a; 1. 数据导入&#xff1a;从关系型数据库&#xff08;如MySQL、Oracle等&#xff09;中将…...

【Python】TensorFlow介绍与实战

TensorFlow介绍与使用 1. 前言 在人工智能领域的快速发展中&#xff0c;深度学习框架的选择至关重要。TensorFlow 以其灵活性和强大的社区支持&#xff0c;成为了许多研究者和开发者的首选。本文将进一步扩展对 TensorFlow 的介绍&#xff0c;包括其优势、应用场景以及在最新…...

第100+16步 ChatGPT学习:R实现Xgboost分类

基于R 4.2.2版本演示 一、写在前面 有不少大佬问做机器学习分类能不能用R语言&#xff0c;不想学Python咯。 答曰&#xff1a;可&#xff01;用GPT或者Kimi转一下就得了呗。 加上最近也没啥内容写了&#xff0c;就帮各位搬运一下吧。 二、R代码实现Xgboost分类 &#xff08…...

【操作系统】定时器(Timer)的实现

这里写目录标题 定时器一、定时器是什么二、标准库中的定时器三、实现定时器 定时器 一、定时器是什么 定时器也是软件开发中的⼀个重要组件.类似于⼀个"闹钟".达到⼀个设定的时间之后,就执行某个指定 好的代码. 定时器是⼀种实际开发中⾮常常用的组件. ⽐如⽹络通…...

鸿蒙Navigation路由能力汇总

基本使用步骤&#xff1a; 1、新增配置文件router_map&#xff1a; 2、在moudle.json5中添加刚才新增的router_map配置&#xff1a; 3、使用方法&#xff1a; 属性汇总&#xff1a; https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-compone…...

​1:1公有云能力整体输出,腾讯云“七剑”下云端

【全球云观察 &#xff5c; 科技热点关注】 曾几何时&#xff0c;云计算技术的兴起&#xff0c;为千行万业的数字化创新带来了诸多新机遇&#xff0c;同时也催生了新产业新业态新模式&#xff0c;激发出高质量发展的科技新动能。很显然&#xff0c;如今的云创新已成为高质量发…...

【iOS】APP仿写——网易云音乐

网易云音乐 启动页发现定时器控制轮播图UIButtonConfiguration 发现换头像 我的总结 启动页 这里我的启动页是使用Xcode自带的启动功能&#xff0c;将图片放置在LaunchScreen中即可。这里也可以通过定时器控制&#xff0c;来实现启动的效果 效果图&#xff1a; 这里放一篇大…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...