今天这个项目来自 Dimiter Kendri,是NVIDIA Jetson 社区项目里的一个
项目细节可以点击:
https://www.hackster.io/dhq/descriptive-ai-camera-41481e
项目故事
在此项目中,我们将构建一个相机,该相机自动描述其观察到的内容。主要目的是构建系统的AI部分,该系统可使用诸如Jetson Nano之类的边缘设备进行自动监视。
早在2016年,Google在一篇名为“ Show and Tell”的论文中就展示了如何将卷积神经网络(CNN)与长期短期记忆(LSTM)网络结合使用,以提供图像的自动字幕(文字描述)。在这个项目中,我们将把这个想法扩展到实时视频中。将部署在诸如Jetson Nano之类的边缘设备上运行的AI网络,以使其不断提供所获取帧的文本描述。文字描述将用于基于描述的对象触发动作。
所有这些操作都不需要网络连接,因此可以将此类系统安装在需要AI监视周围环境的偏远地区。
项目介绍
整个设计在Jetson NANO边缘计算设备上实现了一个应用于实时视频的自动图像字幕神经网络。为了保持实现简单,虽然可以将诸如attention之类的高级功能添加到网络中,但是没有实现,因为主脚本是相当模块化的。
主机训练
首先,我们将在主机笔记本电脑上定义和训练网络。该项目将使用Tensorflow 2.01,Keras 2.1和OpenCV 4.1。前提是必须安装Cuda10.0和Visual Studio Express 17.0以利用GPU速度的提高。
我们将用于训练的数据集是Flickr8K图像数据集。这是一个相对较小的数据集,它允许人们在笔记本电脑级GPU上训练完整的AI管道。人们还可以使用更大的数据集,从而以更高的训练时间为代价。
下一个数据集是Glove数据集,它是根据大量文本集构建的一组单词嵌入。该数据集实质上是AI用来从中提取词汇的词典。字幕文本清除完成后,下一步是加载手套嵌入。嵌入是神经网络使用的单词的编码。基本上,单词被投影为高维空间中的向量,然后表示为向量。从此处下载数据集:
https://nlp.stanford.edu/projects/glove/
然后创建一个名为/ Captioning的顶级目录,并在其中提取两个压缩文件。
另外,创建一个名为/ data的文件夹,用于保存在培训阶段生成的文件。接下来,我们将定义网络并对网络进行训练。
从高级角度看,图像字幕深度学习网络由链接在一起的深度CNN(InceptionV3)和LSTM递归神经网络组成。CNN的输出是代表图像类别的x维向量。输出被发送到LSTM,该LSTM生成图像中对象的文本描述。LSTM基本上接收x维矢量流。基于此,它将实时的场景描述链接在一起。
在Github上可以找到用于训练网络的Ipython笔记本。主网络的设计基于Jeff Heaton的工作。它由一个InceptionV3 CNN和一个LSTM递归神经网络组成。
下一步是从Flickr字幕构建数据集,并通过标记和预处理文本来清理所有描述。然后,我们将Flickr8K数据集分为测试和训练图像数据集。然后,我们加载训练数据集描述并训练网络。
如前所述,Inception网络被用作网络的第一阶段。删除最后一个完全连接的层,以便从第一级CNN出来的数据是一维向量。空间只能接受分辨率为299x299像素的图像,因此必须对相机图像进行格式化。
上面的代码段显示了与LSTM串联在一起的经过编辑的InceptionV3 CNN。这实现了编码器-解码器体系结构。
完成此操作后,我们必须遍历训练和测试图像文件夹,并对每个图像进行预处理。
网络的最后一部分是循环的长期短期记忆神经网络(LSTM)。该网络获取序列,并尝试预测序列中的下一个单词。Standford的A. Karpathy完成了关于这些类型网络的工作,他指出它们足够满足此类任务。
最后一步是训练网络。对于该项目,最初使用了6个时期,最初的损失为2.6%。为了获得可接受的结果,损失必须小于1,因此必须训练至少10-15个纪元。
训练完网络后,我们将加载训练后的权重并在来自数据集的测试图像以及不属于原始数据集的图像上测试网络。
如果图像的样式和内容与Flickr9K数据集中的图像非常相似,则说明相对准确。如果内容风格不同,则网络可能会给出无意义的描述。
训练阶段包括项目的第一阶段。至此,您已经导出了带有权重的Keras模型以及用于测试和训练的pickle文件。/ Captioning文件夹下的所有数据都可以使用WinSCP上传到Jetson Nano上。
Jetson NANO相机设定
第二阶段包括使用相机设置Jetson Nano。此项目使用了USB摄像机。
为了避免兼容性问题,需要在Jetson Nano上安装相同版本的Tensorflow 2.0,Python和Keras。
sudo pip3 install --extra-index-url https://developer.download.nvidia.com/compute/redist/jp/v42 tensorflow-gpu==2.0.0+nv19.11
OpenCv用于以连续循环从相机捕获帧。为了演示视频的实时图像字幕,我们必须将文本覆盖在实时视频源的顶部。也可以使用OpenCV API来完成。首先,我们需要安装正确的版本。
安装OpenCV
OpenCv4.1是从源代码编译的。这可能需要一段时间。要安装版本4.1,我使用以下脚本:
curl -L https://github.com/opencv/opencv/archive/4.1.1.zip -o opencv-4.1.1.zipcurl -L https://github.com/opencv/opencv_contrib/archive/4.1.1.zip -o opencv_contrib-4.1.1.zipunzip opencv-4.1.1.zipunzip opencv_contrib-4.1.1.zipcd opencv-4.1.1/echo "** Building..."mkdir releasecd release/cmake -D WITH_CUDA=ON -D ENABLE_PRECOMPILED_HEADERS=OFF -D CUDA_ARCH_BIN="5.3" -D CUDA_ARCH_PTX="" -D WITH_GTK=OFF -D WITH_QT=ON -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-4.1.1/modules -D WITH_GSTREAMER=ON -D WITH_LIBV4L=ON -D BUILD_opencv_python2=ON -D BUILD_opencv_python3=ON -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..make -j3sudo make install
请注意,GTK已关闭,以避免在使用默认设置进行编译时发现库问题。
一旦安装了OpenCV,就使用下面附带的文件test_openCV.py对程序进行了测试。USB摄像头在/ dev下显示为/ video0。
捕获框架后,可以使用以下功能将文本覆盖在每个框架的顶部:
def __draw_label(img, text, pos, bg_color): font_face = cv2.FONT_HERSHEY_TRIPLEX scale = 1 color = (255, 255, 255) thickness = cv2.FILLED margin = 5 txt_size = cv2.getTextSize(text, font_face, scale, thickness) end_x = pos[0] + txt_size[0][0] + margin end_y = pos[1] - txt_size[0][1] - margin cv2.rectangle(img, pos, (end_x, end_y), bg_color, thickness) cv2.putText(img, text, pos, font_face, scale, color, 2, cv2.LINE_AA)
下图显示了从相机拍摄的一帧,日期重叠在该帧的顶部。
通过OpenCv API从相机拍摄的所有图像都是numpy数组。因此,必须将阵列转换为图像,调整大小以匹配InceptionV3 CNN要求,然后再转换回图像并进一步进行预处理。使用具有多种可编程分辨率的相机可以避免这种情况。
与最新的RTX类GPU相比,Jetson Nano没有特别强大的GPU,因此,训练网络绝对应该在笔记本电脑上进行。
AI视频字幕
现在,我们已经在Nano上运行了基本的图像管线,我们将复制已编码的pickle文件和Jetson Nano上的 Glove,并加载经过图像说明的训练的网络权重。
基本图像管道将通过图像字幕网络进行扩充。一旦捕获到帧,该帧将从Numpy数组编码为图像,调整大小,然后转换回Numpy数组。然后将对图像进行预处理,并将其通过初始网络以获取编码矢量。最后一步是对其进行整形,以便针对LSTM网络对矢量进行重新格式化。
while(cap.isOpened()):ret, frame = cap.read()framenc = encodeImageArray(frame).reshape((1,OUTPUT_DIM))capstr = generateCaption(framenc)print("Caption:",capstr)print("_____________________________________")__draw_label(frame, capstr, (0,150), (50,125,50))cv2.imshow('Frame',frame)if cv2.waitKey(25) & 0xFF == ord('q'):break
然后,每个获取的视频帧都通过字幕网络。然后,文字说明会实时叠加在视频源的顶部,以进行演示。
由于网络读取并解析所有编码,因此需要2-3分钟的时间来加载。然后,它读取图像帧并将其通过网络。推理的速度非常快。
最初,网络将提出内存不足发出一些警告。请记住,它并未使用TensorRT进行优化,因此通过这样做并用更好的CNN(例如Xception)替换InceptionV3可以进一步提高速度。
进一步改进
实施这种系统的主要途径是海岸监视,公园安全监视以及任何此类情况,其中自动监视可用于产生积极影响,从而挽救生命并确保环境安全的应用。
下一步是将NVIDIA的Tensorflow模式转换为TensorRT,以获得更多的加速。
由于这是一个模块化系统,因此网络的输出可以传递到通知系统,该通知系统每当感兴趣的单词出现在图像描述中时就发送一封电子邮件。
进一步的发展是将其与会话式AI系统耦合在一起,以构建“询问并描述”系统。
总结
可以看出,网络仅在图像内容与训练图像相似的情况下执行OK。
为了改善描述,需要使用更大的文本语料库和更大的带注释的数据集。尽管Flickr30K几乎是当前数据集的4倍,但如果使用MSCoCO数据集,则可以获得更好的结果。问题是您需要功能强大的GPU或利用云。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。