Funpack3-5 BeagleBone® Black 物体识别无线图传
该项目使用了BeagleBone® Black,实现了物体识别无线图传的设计,它的主要功能为:查看摄像头画面,保存识别图像。
标签
Funpack活动
OpenCV
BeagleBone Black
debian系统
数字识别
鲍飞.
更新2025-01-14
41

项目介绍

本项目完成的是板卡一:BeagleBone® Black的任务三 - 自命题。

在BBB板卡上实现了以下功能:

  • WIFI图传
  • Opencv数字识别
  • 按键1:保存当前的图片
  • 按键2:进行识别,并且在用四个LED以二进制的方式显示当前识别的数字

硬件平台

首先就是本次活动的核心:BeagleBone Black板卡,使用的是TI的处理器AM3358,虽然年级比较大,但是还是很能打的,并且官方提供长时间的出货

image.png

image.png

BBB对外使用的接口资源还是挺齐全的,如下:

  • 1个microHDMI
  • 1个以太网
  • 1个microSD卡座
  • 1个USB Hose,1个USB Client
  • 4个用户LED,1个电源指示LED
  • 1个复位按键,1个电源按键,1个Boot按键
  • Debug串口排针
  • DC母座-5V


除了活动所使用的板卡,我还使用到了其他的东西:

  • Type-A 转 Type-C
  • USB-HUB
  • USB-Camera
  • USB-WIFI


如下是所用到硬件的组合体。为了防止板子放在桌上发生短路以及固定摄像头等意外,打印了个外壳。

环境搭建

下载烧入新镜像

拿到板子的时候,肯定是要先给板子刷入最新的镜像啦,官方镜像网站:Latest Software Images,我下载的镜像是AM335x 12.2 2023-10-07 4GB microSD IoT。里面有Image【开发板镜像文件】、sha256【开发板镜像校验文件】

image.png

下载下来为了访问因为网络等其他因素导致下载数据丢失等问题,所以最好校验一下。

在windows下面进行校验流程,在命令行窗口(CMD)中输入:Get-FileHash -Path "需要校验的文件",既可以看到校验值,如果输出的sha256中的校验值和《am335x-debian-12.2-iot-armhf-2023-10-07-4gb.img.xz.sha256sum》这个文件中的值不一样的话,则说明有问题最好重新下载校验

image.png

烧入镜像工具下载地址:balenaEtcher,SD卡最好是新的或者以及格式化过了,且容量最好大于等于8GB,我是用的SD卡是32GB的。在balenaEtcher中先选择镜像文件,然后在选择SD卡的盘符,最后点击Finish等待镜像的烧写。

将SD卡烧入BBB的SD卡槽中,在上电之前按住按键S2(uSD BOOT),一开始四颗LED全亮,等待读取SD内容完成后,就会根据镜像中设置的状态进行闪烁,状态如下

  • USR0 通常在启动时配置为以心跳模式闪烁
  • USR1 通常在启动时配置为在 SD (microSD) 卡访问期间亮起
  • USR2 通常在启动时配置为在 CPU 活动期间亮起
  • USR3 通常在启动时配置为在 eMMC 访问期间亮起

稍等一会,就会电脑上就会出现一个盘符,上面有一些介绍的文档和内容。在网络连接中会看到多了一个USB的以太网设备,根据以下连接方式和操作系统来分配网络,我是在Windows下使用USB连接,所以我的网络连接的那个新的设备的ip:192.168.7.1

IP Address

Connection Type

Operating System(s)

Status

192.168.7.2

USB

Windows

Inactive

192.168.6.2

USB

Mac OS X, Linux

Inactive

192.168.8.1

WiFi

all

Inactive

beaglebone.local

all

mDNS enabled

Inactive

beaglebone-2.local

all

mDNS enabled

Inactive

这样就可以通过SSH就可以访问BBB板卡了,我使用的连接工具是MobaXterm,新建ssh,输入正确的ip和用户名,进去之后输入密码,默认密码为:temppwd

image.pngimage.png

先在命令行中查看一下镜像是否烧写成功

debian@BeagleBone:~$ sudo su
[sudo] password for debian:
root@BeagleBone:/home/debian# cat /etc/dogtag
BeagleBoard.org Debian Bookworm IoT Image 2023-10-07

通过查看文件夹中的内容“BeagleBoard.org Debian Bookworm IoT Image 2023-10-07”,可以看到是IoT的2023-10-07的镜像。ok,完成了第一大步-镜像的烧写!!!

安装USB-WiFi驱动

将USB-Wifi插到USB-Host接口,输入lsusb看设备的型号

 root@BeagleBone:/home/debian# lsusb
 Bus 001 Device 081: ID 0bda:0179 Realtek Semiconductor Corp. RTL8188ETV Wireless LAN 802.11n Network Adapter
 Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

可以看到型号为:RTL8188ETV,ID为:0bda:8179,GitHub驱动下载链接:quickreflex/rtl8188eus: Wifi driver support for rtl8188eu, rtl8188eus and rtl8188etv chips and working under the new linux kernel (5.1.x). (github.com)

按照Github中的Readme提示进行安装:
image.png

  • 安装内核源代码【否则make all报错:/lib/modules/5.10.168-ti-r72/build不存在】:apt-get install linux-headers-$(uname -r)
  • 编译:make all
  • 安装【会将.bin进行复制,若没有手动cp一下:cp ./rtl8188eufw.bin /lib/firmware/rtlwifi/】:make install
  • 安装WiFi工具:network-manager
     # 安装
     apt-get update
     apt-get install network-manager
     ​
     # 启用并启动服务
     systemctl enable NetworkManager
     systemctl start NetworkManager
     ​
     # 扫描周围的WIFI
     nmcli dev wifi list
     ​
     # 根据上面扫描出来的进行连接WIFI
     nmcli dev wifi connect "your_network_ssid" password "your_password"
     ​
     # 获取IP地址
     ip a show wlan0
     ​
     # 查看ip
     ifconfig

摄像头配置

将摄像头插到USB-Host接口,输入lsusb查看设备的型号,一般摄像头都是免驱的,所以并不用安装什么驱动就能直接使用,并且在/dev目录下面应该会多出来两个video设备,其中/dev/video0是图像/视频集,/dev/video1是metadata采集,没特殊需求一般都是用video0就可。

root@BeagleBone:/home/debian# lsusb
Bus 001 Device 002: ID 0c45:6368 Microdia USB 2.0 Camera
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
root@BeagleBone:/home/debian#
root@BeagleBone:/home/debian# ls /dev/video*
/dev/video0 /dev/video1

安装V4L2,它是Linux内核中用于处理视频捕捉和输出设备的一个API(应用程序接口)

sudo apt update
sudo apt install v4l-utils

然后就可以使用V4L2查看摄像头的参数了,不同的视频格式,分辨率以及帧率等

root@BeagleBone:/home/debian# v4l2-ctl --list-formats-ext -d /dev/video0
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture

[0]: 'MJPG' (Motion-JPEG, compressed)
Size: Discrete 1920x1080
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 1280x720
Interval: Discrete 0.017s (60.000 fps)
Size: Discrete 1280x1024
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 640x480
Interval: Discrete 0.008s (120.101 fps)
Size: Discrete 800x600
Interval: Discrete 0.017s (60.000 fps)
Size: Discrete 1024x768
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 320x240
Interval: Discrete 0.008s (120.501 fps)
[1]: 'YUYV' (YUYV 4:2:2)
Size: Discrete 1920x1080
Interval: Discrete 0.167s (6.000 fps)
Size: Discrete 640x480
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 320x240
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 800x600
Interval: Discrete 0.050s (20.000 fps)
Size: Discrete 1280x720
Interval: Discrete 0.111s (9.000 fps)
Size: Discrete 1024x768
Interval: Discrete 0.167s (6.000 fps)
Size: Discrete 1280x1024
Interval: Discrete 0.167s (6.000 fps)

查看画面

因为烧入的是Debian无图形化界面,所以接入到Hdmi显示屏上也只能敲敲命令行跟ssh连接过去一样,这就有点麻烦了,不能直接通过opencv的cv2.imshow等相关显示图片或视频的函数来显示直观的展示了,那就只能通过网络传输到电脑上查来了,最后发现一个开源工具:mjpg-streamer,需要将源代码下载下来进行安装,下面是具体步骤:

  1. 下载mjpg-streamer
  2. apt-get install cmake
  3. cd mjpg-streamer-experimental
  4. make
  5. make install
  6. 启动(注意以下几个参数)
    1. 摄像头设备名:/dev/video0
    2. 打开的分辨率:640x480
    3. 打开的帧率:30
root@BeagleBone:/home/debian/linux/mjpg-streamer# cd mjpg-streamer-experimental/
root@BeagleBone:/home/debian/linux/mjpg-streamer/mjpg-streamer-experimental# ls
CMakeLists.txt LICENSE README.md cmake makedeb.sh mjpg_streamer.h plugins scripts utils.c www
Dockerfile Makefile TODO docker-start.sh mjpg_streamer.c mjpg_streamer@.service postinstall.sh start.sh utils.h
root@BeagleBone:/home/debian/linux/mjpg-streamer/mjpg-streamer-experimental# make
[ -d _build ] || mkdir _build
[ -f _build/Makefile ] || (cd _build && cmake -DCMAKE_BUILD_TYPE=Release ..)
CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
Compatibility with CMake < 2.8.12 will be removed from a future version of
CMake.

Update the VERSION argument <min> value or use a ...<max> suffix to tell
CMake that the project does not need compatibility with older versions.


-- The C compiler identification is GNU 12.2.0
-- Detecting C compiler ABI info
…………


root@BeagleBone:/home/debian/linux/mjpg-streamer/mjpg-streamer-experimental# make install
make -C _build install
make[1]: Entering directory '/home/debian/linux/mjpg-streamer/mjpg-streamer-experimental/_build'
make[2]: Entering directory '/home/debian/linux/mjpg-streamer/mjpg-streamer-experimental/_build'
make[3]: Entering directory '/home/debian/linux/mjpg-streamer/mjpg-streamer-experimental/_build'
make[3]: Leaving directory '/home/debian/linux/mjpg-streamer/mjpg-streamer-experimental/_build'
[ 13%] Built target mjpg_streamer
make[3]: Entering directory '/home/debian/linux/mjpg-streamer/mjpg-streamer-experimental/_build'
make[3]: Leaving directory '/home/debian/linux/mjpg-streamer/mjpg-streamer-experimental/_build'
[ 21%] Built target input_file
make[3]: Entering directory '/home/debian/linux/mjpg-streamer/mjpg-streamer-experimental/_build'
make[3]: Leaving directory '/home/debian/linux/mjpg-streamer/mjpg-streamer-experimental/_build'
[ 39%] Built target input_http
…………


root@BeagleBone:/home/debian/linux/mjpg-streamer/mjpg-streamer-experimental# mjpg_streamer -i "input_uvc.so -d /dev/video0 -r 640x480 -f 30" -o "output_http.so -p 8080 -w ./www"
MJPG Streamer Version.: 2.0
i: Using V4L2 device.: /dev/video0
i: Desired Resolution: 640 x 480
i: Frames Per Second.: 30
i: Format............: JPEG
i: TV-Norm...........: DEFAULT
i: FPS coerced ......: from 30 to 61612
UVCIOC_CTRL_ADD - Error at Pan (relative): Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Tilt (relative): Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Pan Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Tilt Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Pan/tilt Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Focus (absolute): Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Pan (relative): Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Tilt (relative): Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Pan Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Tilt Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Pan/tilt Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Focus (absolute): Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at LED1 Mode: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at LED1 Frequency: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Disable video processing: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Raw bits per pixel: Inappropriate ioctl for device (25)
o: www-folder-path......: ./www/
o: HTTP TCP port........: 8080
o: HTTP Listen Address..: (null)
o: username:password....: disabled
o: commands.............: enabled

可以看到HTTP TCP port是8080,所以在浏览器中输入http://192.168.7.2:8080就进入到M-JPEG stream页面中了,在右侧中选择相应的选项就可以看到图片或者视频了

image-20241101153649659.png

功能实现

要完成这个大功能,需要逐步实现每一个小功能,最终形成一个完整的项目

  1. GPIO
    1. 点灯
    2. 检测按键
  2. OpenCV识别

GPIO

点灯

在BBB硬件介绍中,我们可以发现以下信息:

  • USR0 通常在启动时配置为以心跳模式闪烁
  • USR1 通常在启动时配置为在 SD (microSD) 卡访问期间亮起
  • USR2 通常在启动时配置为在 CPU 活动期间亮起
  • USR3 通常在启动时配置为在 eMMC 访问期间亮起
  • USR4/WIFI 通常在启动时配置为使用 WiFi(客户端)网络关联(仅限 BeagleBone Blue 和 BeagleBone AI))
    当我们修改Led的状态的时候,就会改变原本的指示含义,不过问题不大,我们自己清楚它处于什么运行状态就好。
  1. 在命令行中,输入cd /sys/class/leds就可以进入到指定目录下,`ls `可以查看当前目录下的问题,可以看到有四个绿色的用户指示灯,对应到开发板就是右上角那四盏灯。
    image.png
  2. 进入其中一个LED的目录,cd beaglebone\:green\:usr0,可以看到有以下内容
    image.png
  • brightness:用来设置或获取LED的亮度值。写入0表示关闭LED
  • device:这是一个指向LED设备所在设备目录的符号链接
  • max_brightness:这个文件显示了该LED支持的最大亮度值。这通常是255
  • power:电源管理相关的东西。
  • subsystem:这个文件是一个指向LED子系统的符号链接
  • trigger:这个文件用于设置或查询触发LED亮起的事件类型【none,heartbeat等】
  1. 查看LED可配置的模式和当前模式:more trigger。被 [ ] 框住的表示当前状态,可以看到是心跳模式。板子的这个LED默认配置的就是这个,所以上电的时候就会USR0会Blingbling的闪
    image.png
  2. 让LED受控于我们!
debian@beaglebone:/sys/class/leds/beaglebone:green:usr0$ echo none > trigger   #设置
debian@beaglebone:/sys/class/leds/beaglebone:green:usr0$ echo 1 > brightness #打开
debian@beaglebone:/sys/class/leds/beaglebone:green:usr0$ echo 0 > brightness #关闭
  1. 通过命令行可以控制LED的状态,那么通过程序点灯也要差不多的原理
#!/usr/bin/python 
import sys

LED0 = "/sys/class/leds/beaglebone:green:usr0"
LED1 = "/sys/class/leds/beaglebone:green:usr1"
LED2 = "/sys/class/leds/beaglebone:green:usr2"
LED3 = "/sys/class/leds/beaglebone:green:usr3"

def writeLED ( filename, value, path):
fo = open( path + filename,"w")
fo.write(value)
fo.close()
return

def removeTrigger(path):
writeLED ("/trigger", "none", path)
return

def LED_ON(ledPath):
removeTrigger(ledPath)
writeLED("/brightness", "1", ledPath)
return

def LED_OFF(ledPath):
removeTrigger(ledPath)
writeLED("/brightness", "0", ledPath)
return

# while true:
# LED_OFF(LED0)
# LED_OFF(LED1)
# LED_OFF(LED2)
# LED_OFF(LED3)
# time.sleep(5)
# LED_ON(LED0)
# LED_ON(LED1)
# LED_ON(LED2)
# LED_ON(LED3)
# time.sleep(5)

将控制LED的操作放在LED.py文件中,到时候在主程序中调用即可。

按键

按键操作其实就是读取GPIO的平台状态,所以只需要将GPIO设置为输入,然后获取对应的高低电平即可。
先进入GPIO这个目录下面cd /sys/class/gpio,通过ls发现了很多GPIO端口

image.png
那如何跟原理图上面的管教对应起来呢?以排座P9中GPIO3_19GPIO1_16为例子,后面使用的按键也是接到这两个管教上面的。
在BBB这个板卡所用芯片中,会有GPIOx_0——GPIOx_31,一共32个为一组。
所以GPIO3_19GPIO1_16分别为:32×3+19=115,32×1+16=48,对应到上面目录中就是gpio115gpio48

image.png

  1. 进入其中一个GPIO的目录,cd gpio115,可以看到有以下内容
    image.png
  • active_low:1:表示该GPIO是低电平有效的。0:表示高电平有效
  • device:这是一个指向GPIO控制器所在设备目录的符号链接
  • direction:设置或获取GPIO的方向,in(输入)或out(输出)
  • edge:设置或获取触发中断的边沿类型,none(无触发)、rising(上升沿触发)、falling(下降沿触发)和both(双边沿触发)
  • label:这是一个GPIO的描述性标签
  • power:电源管理相关的东西
  • subsystem:指向gpio子系统的符号链接
  • value:当前GPIO的状态,当direction=in时,用于读取,当direction=out时,用于设置输出电平
  1. 读取按键KEY的状态
debian@BeagleBone:/sys/class/gpio/gpio115$ echo in > direction
debian@BeagleBone:/sys/class/gpio/gpio115$ echo 0 > active_low
debian@BeagleBone:/sys/class/gpio/gpio115$ echo none > edge
debian@BeagleBone:/sys/class/gpio/gpio115$ cat value
0
debian@BeagleBone:/sys/class/gpio/gpio115$ cat value
1
  1. 通过命令行可以读取KEY的状态,那么通过程序读取也是差不多的原理
#!/usr/bin/python 
import sys

KEY1 = "/sys/class/gpio/gpio48"
KEY2 = "/sys/class/gpio/gpio115"

def KeyInit(path):
fo = open( path + "/direction","w")
fo.write("in")
fo.close()

fo = open( path + "/active_low","w")
fo.write("0")
fo.close()

fo = open( path + "/edge","w")
fo.write("none")
fo.close()
return

# 低电平按下
def readKey1():
fo = open( KEY1 + "/value","r")
value = fo.read()
fo.close()
if value=="0\n":
return 1;
else:
return 0

# 高电平按下
def readKey2():
fo = open( KEY2 + "/value","r")
value = fo.read()
fo.close()
if value=="1\n":
return 1;
else:
return 0

# KeyInit(KEY1)
# KeyInit(KEY2)

# while True:
# if(readKey1()):
# print("key1")
# if(readKey2()):
# print("key2")

OpenCV

因为使用的不是图形化界面,并不能通过直接在命令行中查看图像,所以只能通过保存下一帧图片或者视频在电脑上查看

import cv2

# 打开视频流(默认摄像头),并设置格式为MJPG
cap = cv2.VideoCapture(0)

# 设置分辨率为640x480
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

# 设置格式为MJPG
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
cap.set(cv2.CAP_PROP_FOURCC, fourcc)

# 设置帧率为30fps
cap.set(cv2.CAP_PROP_FPS, 30)

if not cap.isOpened():
print("无法打开摄像头")
exit()

ret, frame = cap.read()
if ret:
cv2.imwrite('captured_image.jpg', frame)
print("图片已保存为 'captured_image.jpg'")
else:
print("无法读取帧")

cap.release()

在上面环境搭建中,使用了网页中查看摄像头页面占用了/dev/video0,而且/dev/video0不能同时被多个应用打开,因此上面那段代码就不能正常运行了,所以想要在网页实时显示,并且运行opencv的话,可以将/dev/video0流到网页中,在opencv中打开网页流

import cv2

# 用网络摄像头流的URL代替默认摄像头设备
stream_url = 'http://192.168.7.2:8080/?action=stream'

# 打开视频流
cap = cv2.VideoCapture(stream_url)

# 设置分辨率为640x480
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

# 设置格式为MJPG
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
cap.set(cv2.CAP_PROP_FOURCC, fourcc)

# 设置帧率为30fps
cap.set(cv2.CAP_PROP_FPS, 30)

# 检查是否成功打开流
if not cap.isOpened():
print("无法打开网络摄像头流")
exit()

# 读取一帧
ret, frame = cap.read()

# 如果成功读取帧
if ret:
# 保存图像到文件
cv2.imwrite('captured_image.jpg', frame)
print("图片已保存为 'captured_image.jpg'")
else:
print("无法读取帧")

# 释放资源
cap.release()

OK,图像或者视频可以获取到了,后面就需要进行识别了。
数字识别大致可以分为三种方式(第一种方式和第二钟方式比较方便简单,第三种比较准确但是更加复杂):

  1. 使用OCR(比如:Tesseract OCR)
    1. 安装对应的库
sudo apt-get update
sudo apt-get install tesseract-ocr
pip install pytesseract --break-system-packages
    • 简单代码示例
import cv2
import pytesseract

image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# OCR
text = pytesseract.image_to_string(gray, config='--psm 10 --oem 3 -c tessedit_char_whitelist=0123456789')

print("Recognized digit:", text.strip())
  1. 使用模板匹配(只需要使用OpenCV内置的库即可)
    1. 简单代码示例
import cv2
import numpy as np

image = cv2.imread('5.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 读取模板
templates = []
for i in range(10):
template = cv2.imread(f'{i}.png', 0)
templates.append(template)

# 匹配模板
results = []
for template in templates:
res = cv2.matchTemplate(gray, template, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
results.append(max_val)

# 获取最高匹配值对应的数字
recognized_digit = np.argmax(results)
print("Recognized digit:", recognized_digit)
  1. 使用 TensorFlow 或 PyTorch
    1. 功能代码:悲!没有调出来。在安装部署的时候报错了各种各样的错误[晕了],最后好不容易部署好,从网上下载了训练好的数字识别模型,发现无论传0-9的数字都只识别1和6,也不知道为啥,后来将原始图片转后保存下载查看看数字也很精确啊,试了好多模型后还是没有成功,先就搁置一旁了

功能展示

import sys
import cv2
import numpy as np
import led
import key
from led import LED0, LED1, LED2, LED3
from key import KEY1, KEY2


# 用网络摄像头流的URL代替默认摄像头设备
# stream_url = 'http://192.168.7.2:8080/?action=stream'
# cap = cv2.VideoCapture(stream_url)
# 用USB直接打开摄像头
cap = cv2.VideoCapture(0,cv2.CAP_V4L2)

# 设置分辨率为640x480
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

# 设置格式为MJPG
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
cap.set(cv2.CAP_PROP_FOURCC, fourcc)

# 设置帧率为30fps
cap.set(cv2.CAP_PROP_FPS, 30)

if not cap.isOpened():
print("无法打开摄像头")
exit()
else:
print("Open OK")

key.KeyInit(KEY1)
key.KeyInit(KEY2)

while True:
if key.readKey1():
print('key1')
# 读取一帧
ret, frame = cap.read()

# 如果成功读取帧
if ret:
# 保存图像到文件
cv2.imwrite('captured_image.jpg', frame)
print("图片已保存为 'captured_image.jpg'")
else:
print("无法读取帧")
if key.readKey2():
print('key2')
image = cv2.imread('captured_image.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 读取模板
templates = []
for i in range(10):
template = cv2.imread(f'{i}.png', 0)
templates.append(template)

# 匹配模板
results = []
for template in templates:
res = cv2.matchTemplate(gray, template, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
results.append(max_val)

# 获取最高匹配值对应的数字
predicted_digit = np.argmax(results)
print("Recognized digit:", predicted_digit)

if predicted_digit == 0:
led.LED_OFF(LED0)
led.LED_OFF(LED1)
led.LED_OFF(LED2)
led.LED_OFF(LED3)
elif predicted_digit == 1:
led.LED_ON(LED0)
led.LED_OFF(LED1)
led.LED_OFF(LED2)
led.LED_OFF(LED3)
elif predicted_digit == 2:
led.LED_OFF(LED0)
led.LED_ON(LED1)
led.LED_OFF(LED2)
led.LED_OFF(LED3)
elif predicted_digit == 3:
led.LED_ON(LED0)
led.LED_ON(LED1)
led.LED_OFF(LED2)
led.LED_OFF(LED3)
elif predicted_digit == 4:
led.LED_OFF(LED0)
led.LED_OFF(LED1)
led.LED_ON(LED2)
led.LED_OFF(LED3)
elif predicted_digit == 5:
led.LED_ON(LED0)
led.LED_OFF(LED1)
led.LED_ON(LED2)
led.LED_OFF(LED3)
elif predicted_digit == 6:
led.LED_OFF(LED0)
led.LED_ON(LED1)
led.LED_ON(LED2)
led.LED_OFF(LED3)
elif predicted_digit == 7:
led.LED_ON(LED0)
led.LED_ON(LED1)
led.LED_ON(LED2)
led.LED_OFF(LED3)
elif predicted_digit == 8:
led.LED_OFF(LED0)
led.LED_OFF(LED1)
led.LED_OFF(LED2)
led.LED_ON(LED3)
elif predicted_digit == 9:
led.LED_ON(LED0)
led.LED_OFF(LED1)
led.LED_OFF(LED2)
led.LED_ON(LED3)



# 释放资源
cap.release()

上面有两种方式来打开摄像头,1.使用网络;2.使用USB。第一种方式有一丢丢延迟

一个按键用于拍照保存视频,另一个按键按下的时候就会识别图片的数字,并且通过四个LED以二进制的方式显示出来。

实物展示

哈哈哈哈没想到吧,使用的按键时机械键盘里的,方便且好用!

总结

当整体程序运行的时候非常非常的慢,特别是保存视频的时候或者网页中查看到的和保存下来的是N秒之前图像等等等,通过不断的排查和寻找问题,我在以下方面进行测试

  1. 尝试提高芯片的运行的频率(没有尝试超频hhhh,没有散热器和风扇这些)
 debian@BeagleBone:~$ cpufreq-info
 cpufrequtils 008: cpufreq-info (C) Dominik Brodowski 2004-2009
 Report errors and bugs to cpufreq@vger.kernel.org, please.
 analyzing CPU 0:
  driver: cpufreq-dt
  CPUs which run at the same hardware frequency: 0
  CPUs which need to have their frequency coordinated by software: 0
  maximum transition latency: 300 us.
  hardware limits: 300 MHz - 1000 MHz
  available frequency steps: 300 MHz, 600 MHz, 720 MHz, 800 MHz, 1000 MHz
  available cpufreq governors: performance
  current policy: frequency should be within 300 MHz and 1000 MHz.
                  The governor "performance" may decide which speed to use
                  within this range.
  current CPU frequency is 1000 MHz.
  cpufreq stats: 300 MHz:0.00%, 600 MHz:0.00%, 720 MHz:0.00%, 800 MHz:0.00%, 1000 MHz:100.00%

在最后一行可以看到当前的 CPU 频率为 1000MHz了,已经是最大了

  1. 是不是我图像的分辨率设置太高了,应该不会默认使用摄像头的最高分辨率(1920x1080 30fps)吧?经过不断测试后并且权衡后使用了640x480 30fps,再低下去那个像素都糊到太糊了
  2. 因为板卡的EMMC只有4GB,当系统刷进去之后并且安装了一些应用之后,发现就没有空间安装新的应用了[悲],所以整了一张稍微大一点SD卡,将系统刷到SD卡上,这就出现了可能的问题,SD卡的读写读取受限,a安装hdparm进行测试:
root@BeagleBone:/home/debian/linux/Code# sudo apt-get install hdparm
…………
root@BeagleBone:/home/debian/linux/Code# fdisk -l
Disk /dev/mmcblk1: 3.53 GiB, 3791650816 bytes, 7405568 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2833793b

Device Boot Start End Sectors Size Id Type
/dev/mmcblk1p1 * 8192 7405567 7397376 3.5G 83 Linux


Disk /dev/mmcblk0: 29.12 GiB, 31266439168 bytes, 61067264 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x6adf174b

Device Boot Start End Sectors Size Id Type
/dev/mmcblk0p1 * 8192 61067230 61059039 29.1G 83 Linux
root@BeagleBone:/home/debian/linux/Code# hdparm -Tt /dev/mmcblk0p1

/dev/mmcblk0p1:
Timing cached reads: 364 MB in 2.00 seconds = 181.92 MB/sec
Timing buffered disk reads: 38 MB in 3.12 seconds = 12.17 MB/sec

可以看到:

  • 缓存读取速度为 181.92 MB/s
  • 实际磁盘读取速度为 12.17 MB/s


附件下载
mjpg-streamer-master.zip
驱动
rtl8188eu.zip
驱动
main.zip
程序
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号