赞
踩
我想基于yolov5模型完成一个目标检测任务,其中摄像头应该搭载在无人机上,我的机载电脑是树莓派,这意味着我有两种选择:
我购买的是USB免驱摄像头,因为我的树莓派是有壳子的,我暂时还不想拆了,所以没买CSI的摄像头,CSI的摄像头好像便宜些。
为了完成我的远程传输任务,首先我得配置好树莓派的环境,这个不再赘述,烧录好系统之后,配置好国内镜像源,然后固定IP地址,通过FinalShell和VNC远程连接树莓派,同时在enable摄像头和VNC以及SSH。友情提示,如果你是新手且想使用Ubuntu mate或其他Linux发行版,我劝你慎重,直接使用树莓派原生系统可以免去你90%的麻烦,而且原生系统网上资料多,出了问题好解决。另外,烧录系统时直接按照官网给的流程就好了,简单快捷,最多十分钟搞定,网络上很多资料都比较久远,很多资料都是使用Win32DiskImager等第三方工具完成的,我劝你不要这么做。
言归正传,我了解到,如果想实现实时远程传输视频的功能我可以实现树莓派的PiCamera库,你可以在网上找到他的教程,如果你配置成功了,恭喜你!,如果你跟我一样配置失败了,不要灰心,请依次做以下检查
ls /dev/video*
如果显示没有video 0那就是你的摄像头未识别,你可以检查你是否enable摄像头。如果显示有video 0vcgencmd get_camera
如果显示如下:* supported=1 detected=0, libcamera interfaces=0
你很可能遇到了跟我一样的问题。你可以在网上找找解决方法,大部分的方法我都试过,对我并不奏效。./mjpg_streamer -i "input_uvc.so -d /dev/video2 -r 640x480 -f 30" -o "output_http.so -w www"
需要注意的是,你需要使用同一局域网的电脑来打开这个网页。你可以在浏览器输入如下地址来访问网络摄像头http://树莓派ip:8080/?action=stream&type=.mjpg
我知道有的教程给的地址可能没有&type=mjpg,但是最好加上,这样opencv的VideoCapture读取不会出错。如果你可以在本地电脑看到摄像头的画面,那么恭喜你已经完成树莓派端的配置了,可以进行下一步了,当中步骤我描述的不是很详细,但是网络上资料比较多,在这一步很少会出现错误。
一开始我打算的是在python中训练读取模型一气呵成,这种最简单,不过我遇到了一些问题。虽然我可以在浏览器中看到我的画面,但是如果我使用opencv的VideoCapture来读取的话,居然失败了,网上各种答案众说纷纭,有人说在读取路径上加上&type=.mjpg会有用,但是我试了并没有用,最终我找到了问题所在,原来读取网络流opencv会依赖于ffmpeg这个dll,在python中我不知道如果操作,但是在C++中就简单了,我只需要把这个dll复制到debug目录下就可以了,很好,就这样,我在C++上测试了一下,发现已经可以看到视频了。
python环境不会配置+我想练一下我的C++代码能力,所以我将推理环境转到了C++,这样很好,也许可以提高推理的速度。
在正式写代码之前,我打算先找找别人的代码跑跑环境,我首先看到了这个大佬的实现方式https://blog.csdn.net/nihate/article/details/112731327
这个大佬写的很详细,相关代码都开源了,可以去试一下。我试了一下他的这个代码https://github.com/hpc203/yolov5-dnn-cpp-python,他只是用了opencv模块就完成了yolov5的C++部署,大家可以试一下,但是很遗憾,我报错了。
在forward函数中报错了
this->net.forward(outs, this->net.getUnconnectedOutLayersNames());
调试无果之后,果断放弃了。我观察到这位博主的实现方式已经比较老了,我发现还有其他的实现方式,我最终选择是使用libtorch来完成,因为考虑到都是torch嘛,可能兼容性更好一点,而且本人对pytorch还是有一些熟悉的。所以就用这个了。
Torch::cuda::is_available()
注意,这是返回Fasle你需要安装我发的两个参考链接中第一个设置一下,如果你返回的是True,你可能也无法调用cuda,这个你现在看不出来,但是你很可能无法加载模型,这时你需要按照这个链接来重新设置一下http://blog.17baishi.com/16743/。#include <torch/torch.h> #include <torch/script.h> #include <iostream> class Detector { public: /*** * @brief constructor * @param model_path - path of the TorchScript weight file * @param device_type - inference with CPU/GPU */ Detector(const std::string& model_path, bool use_gpu); // other methond ... private: torch::jit::script::Module module_; torch::Device device_; bool half_; }; Detector::Detector(const std::string& model_path, bool use_gpu) :device_(torch::kCPU) { if (torch::cuda::is_available() && use_gpu) { //std::cout << "use cuda...\n"; device_ = torch::kCUDA; } else { //std::cout << "use cpu...\n"; device_ = torch::kCPU; } try { // Deserialize the ScriptModule from a file using torch::jit::load(). module_ = torch::jit::load(model_path); } catch (const c10::Error& e) { std::cerr << "Error loading the model!\n"; std::exit(EXIT_FAILURE); } half_ = (device_ != torch::kCPU); module_.to(device_); if (half_) { module_.to(torch::kHalf); } module_.eval(); } int main() { std::shared_ptr<Detector> detector = std::make_shared<Detector>(yourpath, true); }
如果你可以正常导入模型并且cuda也可用的话,那很好,你省去了很多麻烦,我在这一步卡了很久,我没有办法使用torch::fit::load导入模型,这个地方报错c10异常。我在网络上查找了很多资料,发现主要有这几方面原因:
我看我的GPU还没有跑满,后面打算用一下多线程技术进一步提高帧率。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。