64位系统树莓派部署yolo-fatestv2---超多坑

最近在研究yolo-fastest,开始面对作者大大的一堆部署的指令在pycharm的终端里面一顿操作,然后一路报错,后来才发现原来都是linux的指令...后来在虚拟机上也尝试部署过,成功之后本来想直接挪到树莓派上,但是尝试许久都以失败告终,当然最后都是成功跑起来了,过程比较曲折,但是也学到了不少东西,做个记录。

下面就opencv的安装,ncnn的部署,模型的移植和一些关于模型的修改展开

1.opencv的安装

首先是numpy

sudo pip3 install numpy

然后是opencv所需的依赖

sudo apt-get install build-essential git cmake pkg-config -y
sudo apt-get install libjpeg8-dev -y
sudo apt-get install libtiff5-dev -y
sudo apt-get install libjasper-dev -y
sudo apt-get install libpng12-dev -y

sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev -y

sudo apt-get install libgtk2.0-dev -y
sudo apt-get install libatlas-base-dev gfortran -y

在安装的过程中会遇到一些问题,最多的就是依赖的问题,这时候可以先

sudo apt-get aptitude

这个工具比较神奇,如果报依赖错误的话可以把apt-get换成aptitude,接下来他就会给你一些解决方案自己选

如果也不行的话那可以考虑换源,换成国内源,比如清华源,最终我自己实际上并没有都安装成功,但是最后也跑起来了,所以如果所有方法都尝试了都不行可以往下走

64位系统树莓派部署yolo-fatestv2---超多坑_第1张图片

 这是我自己安装的情况,打问号的是没安装成功的,暂时没遇到问题

安装好依赖之后就可以下载opencv

需要下载Opencv和OpenCV_Contrib两个压缩包,链接如下,可能要打开好几次才能进去,我是尝试了好几次

OpenCV:Github
OpenCV_Contrib:Github

64位系统树莓派部署yolo-fatestv2---超多坑_第2张图片

4.x代表四点几的版本,后面的tags是细分,可以自行选择,我安装的是4.5.5

64位系统树莓派部署yolo-fatestv2---超多坑_第3张图片

选好版本之后点击Download ZIP下载,两个都要下载,然后传送到树莓派的/home/pi/Downloads目录下面,当然也可以是其他目录。

传文件用filezilla,这个可以传文件夹比较方便,只要把需要的文件夹拖到对应目录就可以

客户端 - FileZilla中文网

这里补充一下我当时在这里遇到的两个问题

第一个就是连不上树莓派,输入的地址完全正确但就是连不上

 之后我把端口改成了22莫名其妙就连上了,不知道什么原理

还有一个问题就是传送失败,传送到/home/pi/Downloads下面应该没什么问题,但是其他目录就会传送失败,这时候可以考虑把需要传到的地址的权限打开

sudo chmod -R 777 文件名

 文件名也就是路径,比如想要往/mnt里面写东西,文件名就写/mnt

ok回归正题,传送好之后应该是这样

64位系统树莓派部署yolo-fatestv2---超多坑_第4张图片

划掉的是没有的,就两压缩包

然后就是解压

cd /home/pi/Downloads
unzip opencv-版本.zip   
unzip opencv_contrib-版本.zip
// 版本填你自己的

接下来是cmake

进入下载的解压后的opencv,然后创建build文件夹,进行配置

cd /home/pi/Downloads/opencv-版本
mkdir build
cd build

调好cmake的参数,然后执行

cmake -D CMAKE_BUILD_TYPE=BULLSEYE -D CMAKE_INSTALL_PREFIX=/usr/local -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D OPENCV_EXTRA_MODULES_PATH=/home/pi/Downloads/opencv_contrib-4.5.5/modules -D BUILD_EXAMPLES=ON -D WITH_LIBV4L=ON -D PYTHON3_EXECUTABLE=/usr/lib/python3.9 -D PYTHON_INCLUDE_DIR=/usr/include/python3.9 -D PYTHON_LIBRARY=/usr/lib/aarch64-linux-gnu/libpython3.9.so -D PYTHON3_NUMPY_INCLUDE_DIRS=/usr/lib/python3/dist-packages/numpy/core/include ..

参数解释

CMAKE_BUILD_TYPE=RELEASE \ 代表编译类型为发行版本
CMAKE_INSTALL_PREFIX=/usr/local \ 安装路径
INSTALL_C_EXAMPLES=ON \ C demo
INSTALL_PYTHON_EXAMPLES=ON \ Python demo
OPENCV_EXTRA_MODULES_PATH=/home/pi/Downloads/opencv_contrib-4.5.5/modules \ OpenCV Contrib路径
BUILD_EXAMPLES=ON \ 编译demo
WITH_LIBV4L=ON \ 开启Video for Linux
PYTHON3_EXECUTABLE=/usr/lib/python3.9 \ Python3路径
PYTHON_INCLUDE_DIR=/usr/include/python3.9 \ Python3 include文件夹
PYTHON_LIBRARY=/usr/lib/arm-linux-gnueabihf/libpython3.9.so \ Python3库
PYTHON3_NUMPY_INCLUDE_DIRS=/usr/lib/python3/dist-packages/numpy/core/include \ Python3 Numpy安装路径

当然每个人的参数是不一样的,如果不知道有些文件在哪,那就需要针对性的去找,找文件的指令如下

find / -name 文件名

比如想要找libpython3.9.so那就在终端输入find / -name libpython3.9.so,找到了会返回给你路径,不过似乎是是对于/home/pi的相对路径,可以自己顺着去找到相应文件再复制路径,要用绝对路径 

编译

在build目录下面执行命令

make

这一步需要很长时间,我大概花了八个小时?也许还不止?可能是我的问题。中间卡住了好几次,就是直接断联一样,点击也没反应,后来查了一下可能跟默认的交换空间小也有一点关系。

下面是如何扩充交换空间的链接

https://blog.csdn.net/weixin_43053387/article/details/89204760?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%A0%91%E8%8E%93%E6%B4%BE%E5%BE%88%E5%8D%A1&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-4-89204760.142^v31^pc_rank_34,185^v2^control&spm=1018.2226.3001.4187

我当时照着做了,后来也没快多少,但确实没卡死过

接下来是安装

sudo make insall

 最后还需要告诉机器你的opencv在哪里,这就需要写一个.pc文件

cd /usr/local/lib/pkgconfig
sudo touch opencv.pc                                 

可能你的lib里面没有pkgconfig文件夹,手动创建一个然后再执行

打开opencv.pc,在里面写入
 

prefix=/usr/local
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib
 
Name: opencv
Description: The opencv library
Version:4.0.1
Cflags: -I${includedir}/opencv4
Libs: -L${libdir} -lopencv_shape -lopencv_stitching -lopencv_objdetect -lopencv_superres -lopencv_videostab -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_video -lopencv_photo -lopencv_ml -lopencv_imgproc -lopencv_flann  -lopencv_core
~        

自己改掉版本,其他应该不用改 

理论上到了这一步opencv就算安装完成了,但实际上还得看测试[狗头][狗头][狗头]

测试

先是py的测试

import cv2
cv2.__version__

能输出版本就算成功了

然后是c++的测试,这个比较重要,跟要部署的yolo-fastestv2还是有挺大关系的

当然以下代码是抄的别人的

随便找一个目录,创建一个test文件夹

mkdir test
cd test

创建一个demo test_opencv.cpp文件,写进测试程序

#include 
#include 
#include 
using namespace cv;
 
int main(int argc, const char * argv[]) {
    Mat image;
    VideoCapture capture(0);//打开摄像头
    while(1){
    	capture>>image;
	    imshow("test",image);
	    waitKey(20);
    }
}

然后创建一个CMakeLists.txt编译用

cmake_minimum_required(VERSION 2.6)
project(test_opencv)
find_package(OpenCV REQUIRED)
add_executable(test_opencv test_opencv.cpp)
target_link_libraries(test_opencv ${OpenCV_LIBS})

cpp所在目录下编译运行

​cmake .
make 
./test_opencv

当时在这里卡了很久,因为64位操作系统移除了对摄像头的一些驱动的支持,导致摄像头打不开。

如果你也有同样问题的话可以参考这篇文章:

树莓派4b 64bit无法使用 Pi Camera V2 的解决办法 - DouSTN - 博客园

不出意外到这里opencv就告一段落了。接下来是ncnn的部署。

2.ncnn的部署

打开终端,输入以下命令,建议一个一个来,方便定位错误

git clone https://github.com/Tencent/ncnn.git
cd ncnn
makedir build && cd build
cmake ../
make
make install

不出意外你的/home目录下面应该就已经多出了ncnn文件夹

然后把ncnn中build的install下的三个文件拷贝到你的项目yolo-fastest的sample/ncnn中,把三个替换掉

这样就已经安装好ncnn了,这个应该会比较顺利。

然后测试一下,cd到项目的ncnn的目录下执行以下命令

sh build.sh
./demo

3.模型转换

那么如何把windows下的训练好的模型转到树莓派中?我自己是在虚拟机中完成的,因为直接把虚拟机里面跑起来的模型在树莓派也能跑,所以应该也不会差太多。

下面是作者大大原话,也就是先转模型再简化得到onnx,这些都是在pycharm的终端中完成的,,记得改参数。

转换模型

python3 pytorch2onnx.py --data data/coco.data --weights modelzoo/coco2017-0.241078ap-model.pth --output yolo-fastestv2.onnx

 简化模型

python3 -m onnxsim yolo-fastestv2.onnx yolo-fastestv2-opt.onnx

 然后得到一个onnx模型,把这个传到树莓派(我自己是传到虚拟机,道理一样)

接下来是转换参数,也就是要把我们训练出来的参数换到项目中去

作者是这样写的

cd ncnn/build/tools/onnx
./onnx2ncnn yolo-fastestv2-opt.onnx yolo-fastestv2.param yolo-fastestv2.bin
cp yolo-fastestv2* ../
cd ../
./ncnnoptimize yolo-fastestv2.param yolo-fastestv2.bin yolo-fastestv2-opt.param yolo-fastestv2-opt.bin 1
cp yolo-fastestv2-opt* ~/Yolo-FastestV2/sample/ncnn/model

 我当时是蒙了挺久的,你要是直接复制这个到终端一执行估计也是直接破防。

下面就我的理解来解释一下。

首先刚开始的第一句没有任何问题,也就是转到下载的ncnn的onnx目录下,接下来这一句就比较坑,为什么说比较坑,因为这里的后面三个参数都相当于变量,所以你自己写的话就需要告诉计算机这些东西到底在哪里,第二个代表你自己的onnx的模型,后面两个也就是转换成的模型参数,一定要写这些文件的地址,我建议是绝对路径,方便自己找

./onnx2ncnn /hgfs/share/onnx_s/yolo-fastestv2.onnx /hgfs/share/Yolo-FastestV2-main/sample/ncnn/model/yolo-fastestv2-opt.param /hgfs/share/Yolo-FastestV2-main/sample/ncnn/model/yolo-fastestv2-opt.bin

后面也就是用转换出来的参数来替换你的项目文件yolo-fastest的目录下sample/ncnn/model的参数,我就直接把路径写到里面了,也就是执行完就直接替换掉了

4.一些修改 

首先对于这样的一个项目我们当然不可能满足于就是检测照片,检测视频才是我们想要的。

下面是抄来的一个代码,里面有一些小改动。

#include "yolo-fastestv2.h"
#include 
int main()
{
	// ÕâžöÊÇÀà±ð,±ð˵Äã²»»ážÄ.
	/*
	static const char* class_names[] = {
		"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
		"fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
		"elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
		"skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
		"tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
		"sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
		"potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
		"microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
		"hair drier", "toothbrush"
	};
	*/
	static const char* class_names[] = {
		"person",
		"cat",
		"motorbike",
		"bicycle"
	};
	
	//   ÕâžöÒ²ÊÇÀà±ð.
	//    static const char* class_names[] = {
	//        "airplane", "ship", "storage tank", "baseball diamond", "tennis court",
	//        "basketball court", "ground track field", "harbor", "bridge", "vehicle"
	//    };
		//ÔÚyolo-fastestv2.h ÖÐ, ÓÐÒ»žöÀຯÊý  yoloFastestv2
	yoloFastestv2 api;
	//  ¶ÁÈ¡Ä£ÐÍ
	//¶ÁÈ¡Ä£ÐÍ£¬µØÖ·ÒªžÄ?
	api.loadModel("./model/yolo-fastestv2-opt.param",
		"./model/yolo-fastestv2-opt.bin");

	//cv::Mat cvImg = cv::imread("058.jpg");
	// VectorÈÝÆ÷ÖÐŽæ·Å×Ô¶šÒåÊýŸÝÀàÐÍ,Žæ·ÅÄ¿±ê¿òµÄÐÅÏ¢(cls,score,x,y,w,h,area), ÔÚ yolo-fastestv2.h  ÓÐÉùÃ÷
	std::vector boxes;
	cv::VideoCapture capture;
	//   Žò¿ª "person.mp4"ÎÄŒþ,žÄ³É 0 ŸÍÊÇÉãÏñÍ·.(ÊÇ 0 ²»ÊÇ "0")
	capture.open(0);
	//»ñÈ¡µ±Ç° ÊÓƵÐÅÏ¢
	cv::Size S = cv::Size((int)capture.get(cv::CAP_PROP_FRAME_WIDTH),
		(int)capture.get(cv::CAP_PROP_FRAME_HEIGHT));

	// -----------±£ŽæÊÓƵµÄŒì²âœá¹û--------------
	cv::VideoWriter outputVideo;
	
	//在这里我改过格式
	//原来的是avi格式?如下
	outputVideo.open("/hgfs/share/Yolo-FastestV2-main/sample/ncnn/out1.avi", cv::VideoWriter::fourcc('P', 'I', 'M', '1'), 30.0, S, true);
	//这个是mp4
	//outputVideo.open("./out.mp4", cv::VideoWriter::fourcc('M', 'P', '4', 'V'), 30.0, S, true);
	
	if (!outputVideo.isOpened()) {
		std::cout << "fail to open!" << std::endl;
		return -1;
	}
	// ---------------------------------

	cv::Mat frame;
	while (1) {
		capture >> frame;//¶ÁÈëÊÓƵµÄÖ¡
		if (frame.empty()) break;

		// Œì²â ÍŒÏñ,œá¹û±£ŽæÔÚ boxes
		api.detection(frame, boxes);
		// ¿ÉÊÓ»¯,»æÖÆ¿ò
		for (int i = 0; i < boxes.size(); i++) {
			std::cout << boxes[i].x1 << " " << boxes[i].y1 << " " << boxes[i].x2 << " " << boxes[i].y2
				<< " " << boxes[i].score << " " << boxes[i].cate << std::endl;

			char text[256];
			sprintf(text, "%s %.1f%%", class_names[boxes[i].cate], boxes[i].score * 100);

			int baseLine = 0;
			cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);

			int x = boxes[i].x1;
			int y = boxes[i].y1 - label_size.height - baseLine;
			if (y < 0)
				y = 0;
			if (x + label_size.width > frame.cols)
				x = frame.cols - label_size.width;

			cv::rectangle(frame, cv::Rect(cv::Point(x, y), cv::Size(label_size.width, label_size.height + baseLine)),
				cv::Scalar(255, 255, 255), -1);
			cv::putText(frame, text, cv::Point(x, y + label_size.height),
				cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));

			cv::rectangle(frame, cv::Point(boxes[i].x1, boxes[i].y1),
				cv::Point(boxes[i].x2, boxes[i].y2), cv::Scalar(255, 255, 0), 2, 2, 0);
		}

		cv::namedWindow("img", CV_WINDOW_NORMAL);
		cv::imshow("img", frame);

		// ±£Žæ ÊÓƵŒì²âÎÄŒþ
		outputVideo.write(frame); //°ÑÍŒÏñÐŽÈëÊÓƵÁ÷

		//°ŽÏÂESCÍ˳öÕûžö³ÌÐò
		//°ŽÏÂESCÍ˳öÕûžö³ÌÐò
		//°ŽÏÂESCÍ˳öÕûžö³ÌÐò
		int c = cv::waitKey(30);
		if (char(c) == 27) return -1;
	}
	//    cv::imwrite("output.png", cvImg);
		// ¹Ø±ÕÊÍ·Å
	capture.release();
	cv::waitKey(0);
	return 0;
}

 有不少乱码就不用管了,主要因为在系统之间转来转去,本来好的到虚拟机直接乱码了,主要是中文注释的几句,首先是关于类别,开始是八十个类别,但实际上自己根本用不了那么多可以直接删掉,或者注释掉自己写一个。同时在虚拟机后缀mp4似乎不能跑?我用的avi是跑起来了,同时不要忘记改动outputVideo的路径。

差不多就先写这么多吧,同时感谢文中出现的和以下几位大佬的博客

安装opencv,测试代码来源

树莓派配置opencv环境(包含c++和python)_菜鸡caiji的博客-CSDN博客_树莓派opencv环境搭建

ncnn的部署,视频代码来源

Ubuntu 安装Yolo-FastestV2 的一般流程(5),部署ncnn工程._蒼花星河的博客-CSDN博客

你可能感兴趣的:(opencv,计算机视觉,人工智能)