Jetson 18 基于 DNN(深度神经网络)的物体识别
基于 DNN(深度神经网络)的物体识别
本章节介绍如何使用 DNN(深度神经网络)+ OpenCV 来实现常见的物体识别。
准备工作
由于产品开机默认会自动运行主程序,主程序会占用摄像头资源,这种情况下是不能使用本教程的,需要结束主程序或禁止主程序自动运行后再重新启动机器人。
这里需要注意的是,由于机器人主程序中使用了多线程且由 crontab 配置开机自动运行,所以常规的 sudo killall python 的方法通常是不起作用的,所以我们这里介绍禁用主程序自动运行的方法。
如果你已经禁用了机器人主程序的开机自动运行,则不需要执行下面的结束主程序章节。
结束主程序
1. 点击上方本页面选项卡旁边的 “+”号,会打开一个新的名为 Launcher 的选项卡。
2. 点击 Other 内的 Terminal,打开终端窗口。
3. 在终端窗口内输入 bash 后按回车。
4. 现在你可以使用 Bash Shell 来控制机器人了。
5. 输入命令: sudo killall -9 python
例程
以下代码块可以直接运行:
1. 选中下面的代码块
2. 按 Shift + Enter 运行代码块
3. 观看实时视频窗口
4. 按 STOP 关闭实时视频,释放摄像头资源
如果运行时不能看到摄像头实时画面
- 需要点击上方的 Kernel - Shut down all kernels
- 关闭本章节选项卡,再次打开
- 点击 STOP 释放摄像头资源后重新运行代码块
- 重启设备
本章节特性
deploy.prototxt 文件与 mobilenet_iter_73000.caffemodel 文件与本 .ipynb 处于同一路径内。
当代码块正常运行时,你可以让机器人的摄像头对准一些常见物体例如:"background", "aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable" "dog", "horse", "motorbike", "person", "pottedplant", "sheep "sofa", "train", "tvmonitor"
画面中会标记出它识别出来的物体,并标记这个物体的名称。
import cv2 # 导入 OpenCV 库,用于图像处理
import numpy as np # 用于数学计算的库
from IPython.display import display, Image # 用于在 Jupyter Notebook 中显示图像
import ipywidgets as widgets # 用于创建交互式界面的小部件,如按钮
import threading # 用于创建新线程,以便异步执行任务
# 预定义的分类名,根据 Caffe 模型进行设置
class_names = ["background", "aeroplane", "bicycle", "bird", "boat",
"bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
"dog", "horse", "motorbike", "person", "pottedplant", "sheep",
"sofa", "train", "tvmonitor"]
# 加载 Caffe 模型
net = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'mobilenet_iter_73000.caffemodel')
# 创建一个“停止”按钮,用户可以通过点击它来停止视频流
# ================
stopButton = widgets.ToggleButton(
value=False,
description='Stop',
disabled=False,
button_style='danger', # 'success', 'info', 'warning', 'danger' or ''
tooltip='Description',
icon='square' # (FontAwesome names without the `fa-` prefix)
)
# 定义显示函数,用于处理视频帧并进行物体检测
# ================
def view(button):
camera = cv2.VideoCapture(-1) # 创建摄像头实例
#设置分辨率
camera.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
display_handle=display(None, display_id=True) # 创建显示句柄用于更新显示的图像
i = 0
avg = None
while True:
# frame = picam2.capture_array() # 从摄像头捕获一帧图像
_, frame = camera.read() # 从摄像头捕获一帧图像
# frame = cv2.flip(frame, 1) # if your camera reverses your image
img = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) # 将图像从 RGB 转换为 BGR,因为 OpenCV 默认使用 BGR
(h, w) = img.shape[:2] # 获取图像的高度和宽度
# 生成网络的输入 blob
blob = cv2.dnn.blobFromImage(cv2.resize(img, (300, 300)), 0.007843, (300, 300), 127.5)
net.setInput(blob) # 将 blob 设置为网络的输入
detections = net.forward() # 进行前向传播,得到检测结果
# 遍历检测到的物体
for i in range(0, detections.shape[2]):
confidence = detections[0, 0, i, 2] # 获取检测到的物体的置信度
if confidence > 0.2: # 如果置信度高于阈值,则处理检测到的物体
idx = int(detections[0, 0, i, 1]) # 获取分类索引
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h]) # 获取物体的边界框
(startX, startY, endX, endY) = box.astype("int") # 转换边界框为整数
# 在图像上标记物体和置信度
label = "{}: {:.2f}%".format(class_names[idx], confidence * 100)
cv2.rectangle(frame, (startX, startY), (endX, endY), (0, 255, 0), 2)
y = startY - 15 if startY - 15 > 15 else startY + 15
cv2.putText(frame, label, (startX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
_, frame = cv2.imencode('.jpeg', frame) # 将帧编码为 JPEG 格式
display_handle.update(Image(data=frame.tobytes())) # 更新显示的图像
if stopButton.value==True: # 检查“停止”按钮是否被按下
# picam2.close() # 如果是,则关闭摄像头
cv2.release() # 如果是,则关闭摄像头
display_handle.update(None) # 清空显示的内容
# 显示“停止”按钮并启动显示函数的线程
# ================
display(stopButton)
thread = threading.Thread(target=view, args=(stopButton,))
thread.start()