本项目在开发和实现过程中,引用并基于github上的Kevincoooool(酷世DIY)开发者所公开的源码,经过内测用户-黄才英的二次编辑加工完成的本项目。在此,我们特别指出,该源码的原始著作权归属于Kevincoooool,文章的原始著作权归属于黄才英。我们对开发者Kevincoooool和用户黄才英的开放分享精神和对开源社区所做的贡献表示深深的敬意和感谢。
开源文化为技术创新和知识共享提供了一片肥沃的土壤,促进了全球开发者之间的合作与进步。Kevincoooool通过将其作品开源,不仅展示了个人的技术能力,也体现了对促进技术发展与知识共享的贡献。在此基础上,我们严格遵守了相关的开源许可协议,对Kevincoooool的源码进行了必要的引用与应用,并在此过程中确保了所有使用行为均符合开源协议的规定。该文章是在基于原作之上,进行进一步的研究和探索,以期为相关领域的知识积累和技术进步贡献自己的力量。
我们再次对Kevincoooool与用户黄才英表达最诚挚的感谢。是你们的开放与分享,为我们提供了宝贵的学习和发展机会,也让技术社区成为一个充满合作与创新精神的环境。
MIT License
Copyright (c) 2022 Kevincoooool
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ESP32S3介绍
ESP32-S3是乐鑫(Espressif Systems)推出的一款高度集成的单片机(SoC),专为物联网(IoT)应用而设计。它基于Xtensa LX7内核,采用了高性能的CPU和丰富的外设,并具有低功耗和高可靠性的特点。
以下是ESP32-S3的一些主要特性和功能:
高性能处理器:ESP32-S3搭载了高性能的Xtensa双核32位 LX7处理器,主频高达240 MHz,能够处理复杂的计算任务。
内存和存储:ESP32-S3具有320 KB的SRAM和8 MB的PSRAM,可为应用程序和数据提供充足的存储空间。
丰富的外设:ESP32-S3提供了多种外设和接口,包括GPIO、SPI、I2C、UART、I2S、PWM、ADC等,可以与各种传感器、显示器、外部设备等进行连接和通信。
Wi-Fi和蓝牙:ESP32-S3内置了Wi-Fi和蓝牙功能,支持IEEE 802.11b/g/n无线标准和蓝牙4.2 LE(低功耗)协议,可用于建立与互联网和其他设备的无线连接。
安全性:ESP32-S3支持各种安全功能,包括SSL/TLS加密、数字签名、加密存储等,可以提供保护用户数据和应用程序安全的功能。
低功耗:ESP32-S3通过优化的功耗管理机制和睡眠模式,以低功耗运行,延长电池寿命。
开发生态系统:ESP32-S3基于ESP-IDF(ESP32 IoT Development Framework)进行开发,开发者可以使用C语言或MicroPython编程语言进行开发,可以利用丰富的开发工具和资源进行开发。
总之,ESP32-S3是一款功能强大、高度集成和低功耗的单片机,适用于各种物联网应用,包括智能家居、工业自动化、传感器网络、物联网网关等。
OpenMV介绍
OpenMV IDE是一款独特的集成开发环境,可以跨平台使用,支持Windows、Mac OS、Linux和Raspian等操作系统。
OpenMV IDE的界面布局简洁明了,易于使用。左侧是常用的文档编辑操作和代码编写工具,类似于Qt Creator,具有代码高亮和自动补全等功能。右上角是图像区,显示OpenMV镜头捕捉到的图像,可以保存和截图。右下角是图像的三色RGB直方图,可以进行特征提取、阈值处理等图像操作。
OpenMV IDE提供了一个方便易用的开发环境,可以满足开发者的需求。开发者可以通过串口连接、代码执行等功能进行开发和调试。在IDE中,可以通过点击运行按钮,将Python代码复制给OpenMV,并由OpenMV解析运行。同时,IDE还提供了帧缓冲查看器和直方图显示等功能,方便开发者实时查看图像数据和调试程序。
它还拥有强大的图像处理功能。OpenMV IDE提供了丰富的图像处理功能,包括图像采集、预览、保存、截图等。此外,它还支持各种图像处理算法,如特征提取、阈值处理、边缘检测等,这使得开发者可以轻松地实现各种机器视觉任务。
总的来说,OpenMV IDE是一个功能强大、易于使用的开发环境,为开发者提供了方便快捷的机器视觉开发体验。
软件部分准备
- ESP32S3的OpenMV固件源码:
github版:https://github.com/Kevincoooool/esp32s3_openmv_lvgl (大家可以支持一下这一位大佬,K佬)
gitee版:https://gitee.com/Reimages/esp32s3_openmv?_from=gitee_search (我在国内的gitee上看到了跟上面大佬一样的开源版本,是克隆版,通用的)
- ESP32的烧录工具:flash_download_tool
- OpenMV IDE:下载地址:https://singtown.com/openmv-download/
- 虚拟机Ubuntu环境:在ubuntu系统中,安装git、python3、gcc、esp-idf、micropython;
硬件部分准备
- ESP32S3开发板
- OV2640-FPC式摄像头(或者OV5640也可以)
购买链接:https://item.taobao.com/item.htm?_u=12t4uge5eba8&id=614238777052&spm=a1z09.2.0.0.56392e8d5FuZIw
- 开发板和摄像头进行连接的扩展板
固件修改编译
在Windows下使用 VMware Workstation Pro 创建一个 ubuntu虚拟机。
虚拟机的创建参考链接:https://zhuanlan.zhihu.com/p/569274366
环境配置
打开终端,在终端中输入以下命令配置环境:
安装git:需要输入密码
sudo apt-get install git
安装python3还有python2:
sudo apt install python3
sudo apt install python2.7
2
安装pip
sudo apt install python3-pip
安装GCC
sudo apt-get build-dep gcc
在使用sudo apt-get build-dep gcc时出现 "您必须在 sources.list 中指定代码源(deb-src)URI" 报错
解决方法:
终端输入software-properties-gtk 打开软件和更新窗口
勾选最下方源代码,则不会报错
安装cmake:
sudo apt-get install cmake
安装基于arm内核编译的工具链:
sudo apt-get install gcc-arm-none-eabi
下载esp-idf
git clone -b v4.4 --recursive https://github.com/espressif/esp-idf.git
更新esp-idf,如果执行闪退,请确保安装了pip。通过“pip --version”命令检查是否安装pip
. install.sh
如果遇到python和python3不兼容问题,参考:https://blog.csdn.net/Simulink_/article/details/134043709
下载micropython:
git clone --recursive https://github.com/micropython/micropython.git
配置esp-idf环境变量。
source export.sh
下载ESP32S3_OpenMV固件源码:
git clone https://github.com/Kevincoooool/esp32s3_openmv_lvgl/
如果以上失败,也可以尝试以下方法:
git clone https://gitee.com/Reimages/esp32s3_openmv
配置idf的环境变量:执行esp-idf下的export.sh,例如我用户名是 win,我将esp-idf放置在win处。注意点和/之间有空格。
. /home/win/esp-idf/export.sh
去到ESP32S3_OPENMV固件下, esp32s3_openmv_lvgl/project/ksdiy 执行
make
如果编译没有出错,在目录 project/ksdiy/ 中应该可以看到新创建的 build-GENERIC_S3文件夹。我们需要这个目录下的micropython.bin文件,以及/bootloader目录下的bootloader.bin,和/partition_table目录下的partition_table.bin文件。
如果要重新修改固件源码,则需要先清除之前编译的内容(idf.py clean),再make。
idf.py clean
make
2
固件烧录
在目录 project/ksdiy/ 中应该可以看到新创建的 build-GENERIC_S3文件夹。我们需要这个目录下的micropython.bin文件,以及/bootloader目录下的bootloader.bin,和/partition_table目录下的partition_table.bin文件。
提取出这三个文件到主机win系统,使用USB,或是使用串口连接(windows)电脑,二者选一即可。
电脑端打开乐鑫的flash_download_tool软件,先擦除内存,然后再从上到下分别勾选bootloader.bin,partition_table.bin,micropython.bin三个文件,地址分别设置为0x0,0x8000,0x10000,点击开始即可烧录。
基于摄像头扩展板引脚连接方式的固件:
【Camera_expansion_board-ESP32S3_OpenMV.bin】下载
📌 在 下载中心
->【入门手册资料】百度网盘链接
->第08章.【立创·ESP32S3R8N8】项目案例
->ESP32S3运行OpenMV进行图像识别资料
中。
如果实在编译失败,可以使用这个固件。
固件测试
IDE显示
源码
import sensor, image, time
sensor.reset() #摄像头
sensor.set_pixformat(sensor.JPEG)#JPEG格式
sensor.set_framesize(sensor.QVGA)#640x480
sensor.skip_frames(time = 5)
sensor.set_vflip(True) #设置图像垂直翻转
clock = time.clock() #开启帧率
sensor.skip_frames(time = 2000) #延时
while(True):
clock.tick()
img = sensor.snapshot()
print(clock.fps())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
验证
如果帧率很低,请将电脑识别到的开发板,按照默认格式,进行格式化。
线识别
源码
# 识别直线例程
#
# 这个例子展示了如何在图像中查找线条。对于在图像中找到的每个线对象,
# 都会返回一个包含线条旋转的线对象。
# 注意:线条检测是通过使用霍夫变换完成的:
# http://en.wikipedia.org/wiki/Hough_transform
# 请阅读以上关于“theta”和“rho”的更多信息。
# find_lines()找到无限长度的线。使用find_line_segments()
# 来查找非无限线。
enable_lens_corr = False # turn on for straighter lines...打开以获得更直的线条…
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE) #灰度更快
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 5)
sensor.set_vflip(True) #设置图像垂直翻转
sensor.skip_frames(time = 2000)
clock = time.clock()
# 所有的线对象都有一个`theta()`方法来获取它们的旋转角度。
# 您可以根据旋转角度来过滤线条。
min_degree = 0
max_degree = 179
# 所有线段都有 `x1()`, `y1()`, `x2()`, and `y2()` 方法来获得他们的终点
# 一个 `line()` 方法来获得所有上述的四个元组值,可用于 `draw_line()`.
while(True):
clock.tick()
img = sensor.snapshot()
if enable_lens_corr: img.lens_corr(1.8) # for 2.8mm lens...
# `threshold` controls how many lines in the image are found. Only lines with
# edge difference magnitude sums greater than `threshold` are detected...
# `threshold`控制从霍夫变换中监测到的直线。只返回大于或等于阈值的
# 直线。应用程序的阈值正确值取决于图像。注意:一条直线的大小是组成
# 直线所有索贝尔滤波像素大小的总和。
# `theta_margin`和`rho_margin`控件合并相似的直线。如果两直线的
# theta和ρ值差异小于边际,则它们合并。
for l in img.find_lines(threshold = 1000, theta_margin = 25, rho_margin = 25):
if (min_degree <= l.theta()) and (l.theta() <= max_degree):
img.draw_line(l.line(), color = (255, 0, 0))
# print(l)
print("FPS %f" % clock.fps())
# About negative rho values:
# 关于负rho值:
#
# A [theta+0:-rho] tuple is the same as [theta+180:+rho].
# A [theta+0:-rho]元组与[theta+180:+rho]相同。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
验证
灰度色块识别
源码
# 自动灰度颜色追踪例程
#
# 这个例子展示了使用OpenMV的单色自动灰度色彩跟踪。
import sensor, image, time
print("Letting auto algorithms run. Don't put anything in front of the camera!")
sensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 5)
sensor.set_vflip(True) #设置图像垂直翻转
sensor.skip_frames(time = 2000)
#sensor.set_auto_gain(False) # 颜色跟踪必须自动增益
#sensor.set_auto_whitebal(False) # 颜色跟踪必须关闭白平衡
clock = time.clock()
# 捕捉图像中心的颜色阈值。
r = [(320//2)-(50//2), (240//2)-(50//2), 50, 50] # 50x50 center of QVGA.
print("Auto algorithms done. Hold the object you want to track in front of the camera in the box.")
print("MAKE SURE THE COLOR OF THE OBJECT YOU WANT TO TRACK IS FULLY ENCLOSED BY THE BOX!")
for i in range(60):
img = sensor.snapshot()
img.draw_rectangle(r)
print("Learning thresholds...")
threshold = [128, 128] # Middle grayscale values.中间灰度值。
for i in range(60):
img = sensor.snapshot()
hist = img.get_histogram(roi=r)
lo = hist.get_percentile(0.01) # 获取1%范围的直方图的CDF(根据需要调整)!
hi = hist.get_percentile(0.99) # 获取99%范围的直方图的CDF(根据需要调整)!
# 平均百分位值。
threshold[0] = (threshold[0] + lo.value()) // 2
threshold[1] = (threshold[1] + hi.value()) // 2
for blob in img.find_blobs([threshold], pixels_threshold=100, area_threshold=100, merge=True, margin=10):
img.draw_rectangle(blob.rect())
img.draw_cross(blob.cx(), blob.cy())
img.draw_rectangle(r)
print("Thresholds learned...")
print("Tracking colors...")
while(True):
clock.tick()
img = sensor.snapshot()
for blob in img.find_blobs([threshold], pixels_threshold=100, area_threshold=100, merge=True, margin=10):
img.draw_rectangle(blob.rect())
img.draw_cross(blob.cx(), blob.cy())
print(clock.fps())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
验证
二维码识别
源码
import sensor, image
sensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_framesize(sensor.QVGA) # can be QVGA on M7...
sensor.skip_frames(time = 5)
sensor.set_vflip(True) #设置图像垂直翻转
sensor.skip_frames(30)
#sensor.set_auto_gain(False) # must turn this off to prevent image washout...
while(True):
img = sensor.snapshot()
img.lens_corr(1.8) # strength of 1.8 is good for the 2.8mm lens.
for code in img.find_qrcodes():
print(code)
2
3
4
5
6
7
8
9
10
11
12
13
14
验证
人脸识别
源码
# 人脸识别例程
#
# 这个例子展示了OpenMV Cam的内置人脸检测功能。
#
# 人脸检测通过在图像上使用Haar Cascade特征检测器来工作。 haar级联是
# 一系列简单的区域对比检查。 对于内置的前表面探测器,有25个阶段的检查,
# 每个阶段有数百个检查一块。 Haar Cascades运行速度很快,因为只有在
# 以前的阶段过去后才会评估后期阶段。 此外,您的OpenMV使用称为
# 整体图像的数据结构来在恒定时间内快速执行每个区域对比度检查
#(特征检测仅为灰度的原因是因为整体图像的空间需求)。
import sensor, time, image
# 重置感光元件
sensor.reset()
# 感光元件设置
sensor.set_contrast(3)
sensor.set_gainceiling(16)
# HQVGA and GRAYSCALE are the best for face tracking.
# HQVGA和灰度对于人脸识别效果最好
sensor.set_framesize(sensor.HQVGA)
sensor.set_pixformat(sensor.GRAYSCALE)
#注意人脸识别只能用灰度图哦
sensor.skip_frames(time = 5)
sensor.set_vflip(True) #设置图像垂直翻转
# 加载Haar算子
# 默认情况下,这将使用所有阶段,更低的satges更快,但不太准确。
face_cascade = image.HaarCascade("frontalface", stages=25)
#image.HaarCascade(path, stages=Auto)加载一个haar模型。haar模型是二进制文件,
#这个模型如果是自定义的,则引号内为模型文件的路径;也可以使用内置的haar模型,
#比如“frontalface” 人脸模型或者“eye”人眼模型。
#stages值未传入时使用默认的stages。stages值设置的小一些可以加速匹配,但会降低准确率。
print(face_cascade)
# FPS clock
clock = time.clock()
while (True):
clock.tick()
# 拍摄一张照片
img = sensor.snapshot()
# Find objects.
# Note: Lower scale factor scales-down the image more and detects smaller objects.
# Higher threshold results in a higher detection rate, with more false positives.
objects = img.find_features(face_cascade, threshold=0.75, scale=1.35)
#image.find_features(cascade, threshold=0.5, scale=1.5),thresholds越大,
#匹配速度越快,错误率也会上升。scale可以缩放被匹配特征的大小。
#在找到的目标上画框,标记出来
for r in objects:
img.draw_rectangle(r)
# 打印FPS。
# 注:实际FPS更高,流FB使它更慢。
print(clock.fps())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59