//Description: 记录使用C++在linux上部署yolov8检测和跟踪的过程,及在RK3588带aarch64的Kylin系统上部署ROS+SLAM的过程。遇到dnn::readNetFromONNX
错误,升级OpenCV版本可解决。同时记录输入图像尺寸和模型尺寸不一致时出现的错误。写于2024年夏。
//Create Date: 2024-06-11 14:14:28
//Author: channy
[toc]
使用Opencv4.2在dnn::readNetFromONNX(ModelPath);
时会报错,改用Opencv4.9则该报错消失。
tensor_proto.raw_data().empty() || !tensor_proto.float_data().empty() || !tensor_proto.double_data().empty() || !tensor_proto.int64_data().empty()
当输入图像尺寸和模型输入尺寸不一致时会报错,改成模型尺寸则该报错消失。
[ERROR:0@0.134] global net_impl.cpp:1162 getLayerShapesRecursively OPENCV/DNN: [Reshape]:(onnx_node!/model.22/dfl/Reshape): getMemoryShapes() throws exception. inputs=1 outputs=1/1 blobs=0
[ERROR:0@0.134] global net_impl.cpp:1168 getLayerShapesRecursively input[0] = [ 1 64 75600 ]
[ERROR:0@0.134] global net_impl.cpp:1172 getLayerShapesRecursively output[0] = [ ]
[ERROR:0@0.134] global net_impl.cpp:1178 getLayerShapesRecursively Exception message: OpenCV(4.9.0-dev) /home/channy/Documents/thirdlibs/opencv-4.x/modules/dnn/src/layers/reshape_layer.cpp:109: error: (-215:Assertion failed) total(srcShape, srcRange.start, srcRange.end) == maskTotal in function 'computeShapeByReshapeMask'
terminate called after throwing an instance of 'cv::Exception'
what(): OpenCV(4.9.0-dev) /home/channy/Documents/thirdlibs/opencv-4.x/modules/dnn/src/layers/reshape_layer.cpp:109: error: (-215:Assertion failed) total(srcShape, srcRange.start, srcRange.end) == maskTotal in function 'computeShapeByReshapeMask'
Aborted (core dumped)
以部署VINS-Mono为例。
故考虑docker。
docker pull arm64v8/ros:noetic-ros-core
使用国内源镜像pull不成功,报timeout
错误,试了好几个ros1版本的均失败。
docker pull arm64v8/ubuntu
一开始指定了aarch64但没有指定ubuntu的版本,直接拉的24.04,pull成功,但启动失败。
docker pull arm64v8/ubuntu:20.04
换了指定ubuntu版本依旧是pull成功,但启动失败。
后面查看了官方hello-world中的提示,不指定aarch64
docker run -it ubuntu bash
能够成功pull下ubuntu 24.04的镜像。但目前为止ros对ubuntu 24 的支持还不完善,安装ros过程中遇到报错没有完全解决。故改用ubuntu 20.04。
docker run -it ubuntu:20.04 bash
能够启动成功,在上面换国内源安装ros,项目需要安装的是noetic。
正常安装完成ros后能够成功运行项目代码。
rosbag play YOUR_PATH_TO_DATASET/MH_01_easy.bag 根据时间戳
roslaunch vins_estimator euroc.launch
2.1 feature_tracker
2.2 vins_estimator
2.3 pose_graph
但npu的矩阵运算 \(A_{MxK} * B_{KxN} = C_{MxN}\) 只支持K是32的倍数,N是16的倍数。
经实验,当矩阵维度太大时(128x128x128?)会出现内存错误而导致矩阵运算失败。
且从时间统计上看,同样的数据,使用npu耗时并没有比使用cpu耗时有减少。
默认的Kylin系统用apt安装的opencv不带opencl,需要重新勾选上opencl重新编译opencv。
但从多帧检测的统计结果看,对500帧图像检测特征点并计算总时长,opencl仅比cpu少用1秒。
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/ocl.hpp>
int main() {
// 检查是否有可用的 OpenCL(用于 GPU 加速)
if (!cv::ocl::haveOpenCL()) {
std::cout << "OpenCL is not available." << std::endl;
return -1;
}
// 设置 OpenCL 为可用状态
cv::ocl::setUseOpenCL(true);
// 读取图像
cv::Mat image = cv::imread("your_image.jpg");
if (image.empty()) {
std::cout << "Could not read the image." << std::endl;
return -1;
}
// 创建特征点检测器
cv::Ptr<cv::Feature2D> detector = cv::ORB::create();
// 检测特征点
std::vector<cv::KeyPoint> keypoints;
cv::Mat descriptors;
detector->detectAndCompute(image, cv::noArray(), keypoints, descriptors);
// 绘制特征点
cv::Mat outputImage;
cv::drawKeypoints(image, keypoints, outputImage, cv::Scalar::all(-1), cv::DrawMatchesFlags::DEFAULT);
// 显示结果
cv::imshow("Image with Keypoints", outputImage);
cv::waitKey(0);
return 0;
}