yolov4 在ROS、rviz_fatal error: stb_image.h: no such file or director-程序员宅基地

技术标签: ROS  深度相机D435i  yolov4  

一、ROS yoloV4

1、建立工作空间

mkdir -p catkin_ws/src
cd catkin_ws/src/
catkin_init_workspace
cd ..
catkin_make

2、下载所需的包

(1)下载darknet_ros包

链接:https://github.com/leggedrobotics/darknet_ros

git clone https://github.com/leggedrobotics/darknet_ros

下载后有3个文件夹:darknet、darknet_ros、darknet_ros_msgs

(2)yolov4 源码下载

链接:https://github.com/AlexeyAB/darknet
将yolov4源码放在darknet文件夹下

rm -r darknet/
git clone https://github.com/AlexeyAB/darknet

3、编译

cd catkin_ws
catkin_make

此时自动下载权重yolov2-tiny.weights、yolov3.weights和yolov2.weights,再自行下载yolov4.weights,将权重文件放在(darknet_ros/yolo_network_config/weights/)路径下

4、编译过程中的问题解决

(1) 问题1:Cannot find source file:src/cuda.c
在这里插入图片描述

解决:修改darknet_ros文件夹下CMakeLists.txt文件,将{DARKNET_PATH}/src/cuda.c改为{DARKNET_PATH}/src/dark_cuda.c
原因:yolov1-3是cuda.c,yolov4应为dark_cuda.c

(2)问题2:Cannot find source file:src/logistic_layer.c
在这里插入图片描述

解决:打开刚才的CMakeLists.txt文件,屏蔽{DARKNET_PATH}/src/logistic_layer.c
原因:yolov4代码去掉了logistic_layer.c
(3)问题3:Cannot find source file:src/l2norm_layer.c
解决:打开刚才的CMakeLists.txt文件,屏蔽{DARKNET_PATH}/src/l2norm_layer.c
原因:同上问题3
(4)问题4:Cannot find source file:examples/art.c
解决:将CMakeLists.txt文件中{DARKNET_PATH}/examples/art.c修改为${DARKNET_PATH}/src/art.c,即将所有的examples改为src
原因: Yolo v4的代码中将Yolo v1-v3的源代码中examples文件夹下的代码均放到src文件夹下了
(5)问题5:Cannot find source file:src/lsd.c
解决:打开CMakeLists.txt文件,屏蔽{DARKNET_PATH}/src/lsd.c
原因:同问题2
(6)同上述相同的问题:Cannot find source file:src/attention.c、src/regressor.c和src/segmenter.c
解决:打开CMakeLists.txt文件,屏蔽上述文件
在这里插入图片描述

(7)问题7:image_interface.h:16:30: error: unknown type name ‘IplImage’
在这里插入图片描述
解决:在image_interface.h文件中添加头文件:

#include "opencv2/core/types_c.h"

原因:IplImage的定义找不到对应的头文件,IplImage在"opencv2/core/types_c.h"中进行定义
(8)问题8:image.c:16:23: fatal error: stb_image.h: No such file or directory
在这里插入图片描述
解决:修改image.c文件,修改头文件

#include "../3rdparty/stb/include/stb_image.h"

原因:找不到头文件stb_image.h,该头文件在/3rdparty/stb/include/路径下
(9)问题9:fatal error: stb_image_write.h: No such file or directory在这里插入图片描述
解决:同上修改路径
原因:同问题8
(10)问题10:YoloObjectDetector.hpp: error: conflicting declaration of C function ‘void show_image_cv(image, const char*, IplImage*)’
在这里插入图片描述
解决:屏蔽这一行
(11)问题11:YoloObjectDetector.cpp:278:3: error: ‘fill_cpu’ was not declared in this scope
在这里插入图片描述
解决:添加头文件

#include "../../darknet/src/blas.h"

原因:fill_cpu函数的定义所在头文件没有添加
同样问题: ‘axpy_cpu’ was not declared in this scope,axpy_cpu函数的声明也在blas.h中;
(12)问题12:YoloObjectDetector.cpp:290:104: error: too few arguments to function ‘detection* get_network_boxes(network*, int, int, float, float, int*, int, int*, int)’
在这里插入图片描述
解决:在对应调用到get_network_boxes()函数的末尾添加一个1

detection *dets = get_network_boxes(net, buff_[0].w, buff_[0].h, demoThresh_, demoHier_, 0, 1, nboxes,1);

原因:查看network.c文件中get_network_boxes()函数定义可知,末尾缺少一个参数
(13)问题13:YoloObjectDetector.cpp:300:39: error: could not convert ‘((darknet_ros::YoloObjectDetector*)this)->darknet_ros::YoloObjectDetector::net_’ from ‘network*’ to ‘network’
在这里插入图片描述
解决:在net_前面加一个*号

float* prediction = network_predict(*net_, X);

原因:通过network.c文件中network_predict()函数定义可知,输入参数类型与定义不一致。
(14)问题14:YoloObjectDetector.cpp:316:94: error: invalid conversion from ‘detection*’ to ‘int’ [-fpermissive]
在这里插入图片描述
解决:修改代码:

draw_detections_v3(display, dets, nboxes, demoThresh_, demoNames_, demoAlphabet_, demoClasses_, 1)

原因:yolov4画框函数draw_detections在yolov1-v3有变化
(15)问题15:YoloObjectDetector.cpp:384:61: error: too many arguments to function ‘void show_image_cv(image, const char*)’
在这里插入图片描述
解决:修改代码:

show_image_cv(buff_[(buffIndex_ + 1)%3], "YOLO V4");

原因:show_image_cv少了一个参数定义。该函数在image_opencv.cpp文件中
(16)问题16:将YoloObjectDetector.cpp中的7个“YOLO V3”改为 “YOLO V4”
(17)问题17:yolo_v2_class.cpp:16:10: fatal error: stb_image.h: No such file or directory在这里插入图片描述
解决:修改yolo_v2_class.cpp头文件

#include "../3rdparty/stb/include/stb_image.h"

(18)问题18:undefined reference to `draw_detections_cv_v3’,undefined reference to 'this_thread_sleep_for’等
在这里插入图片描述
在这里插入图片描述
解决:找到所有出现undefined reference to问题的部分,将对应的定义cpp文件添加到CMakeLists.txt中;
例如:draw_detections_cv_v3()函数是在image_opencv.cpp文件中定义的,就需要在CMakeLists.txt中添加如下语句:

${
    DARKNET_PATH}/src/image_opencv.cpp

其他文件:如下
在这里插入图片描述
(19)问题19:在YoloObjectDetector.cpp中使用到的ipl_into_image()函数和ipl_to_image()函数并没有在Yolo v4代码中进行定义,因此需要在Yolo v4源代码中的src/image.c文件的末尾添加这两个函数的定义,即:
a:ipl_into_image()函数的定义:

void ipl_into_image(IplImage* src, image im)
{
    
    unsigned char *data = (unsigned char *)src->imageData;
    int h = src->height;
    int w = src->width;
    int c = src->nChannels;
    int step = src->widthStep;
    int i, j, k;

    for(i = 0; i < h; ++i){
    
        for(k= 0; k < c; ++k){
    
            for(j = 0; j < w; ++j){
    
                im.data[k*w*h + i*w + j] = data[i*step + j*c + k]/255.;
            }
        }
    }
}

b:ipl_to_image()函数的定义

image ipl_to_image(IplImage* src)
{
    
    int h = src->height;
    int w = src->width;
    int c = src->nChannels;
    image out = make_image(w, h, c);
    ipl_into_image(src, out);
    return out;
}

(20)问题20:image.c:16:30: error: unknown type name ‘IplImage’
解决:在src/image.c中添加头文件

#include "opencv2/core/types_c.h"

5、ros_yolov4相应的文件配置

(1)权重文件的下载:yolov4.weights,将文件放在yolo_network_config/weights文件夹下
(2)将darknet_ros/darknet/cfg/文件夹下的配置文件yolov4.cfg复制yolo_network_config/cfg文件夹下;
(3)在darknet_ros/config文件夹下,建立yolov4.yaml,将yolov2.yaml内容复制yolov4.yaml中,并修改内容为:

yolo_model:

  config_file:
    name: yolov4.cfg
  weight_file:
    name: yolov4.weights

(4)在darknet_ros/config文件夹下,将ros.yaml中camera_reading 下的topic改为摄像头的图像发布话题,D435i相机如下:

subscribers:

  camera_reading:
    topic: /camera/color/image_raw
    queue_size: 1

(5)在darknet_ros/launch文件夹下,建立yolo_v4.launch,将yolo_v3.launch中内容复制到里面, 并修改内容:

<arg name="network_param_file"    default="$(find darknet_ros)/config/yolov4.yaml"/>

二、利用D435i相机进行yolov4、ros

1、打开ROS主节点:

roscore

2、打开相机节点:

roslaunch realsense2_camera rs_camera.launch

3、运行yolov4_ros节点

roslaunch darknet_ros yolo_v4.launch

此时可能出现错误,根据电脑配置进行batch的更改

4、打开rviz进行显示

rviz

选择添加图片,话题修改为/darknet_ros/detection_image
此时出现显示问题,需进行一下修改
(1)打开YoloObjectDetector.cpp文件,搜索关键词viewImage_,定位到第4处,代码如下:

if (viewImage_) {
    
    displayInThread(0);
} else {
    
    generate_image(buff_[(buffIndex_ + 1)%3], ipl_);
}

这里的viewImage_参数就对应于ros.yaml文件中的image_view:enable_opencv参数,即是否对检测结果进行显示。显示图像用到了show_image_cv()。
yolov3_ros函数:

void show_image_cv(image p, const char *name, IplImage *disp)

yolov4_ros所用的show_image_cv()函数定义:

void show_image_cv(image p, const char *name);

解决1:将ros.yaml文件中的enable_opencv: true参数改为false,在rviz中查看/darknet_ros/detection_image话题时能够正常显示结果,但是检测结果不会实时显示
解决2:修改YoloObjectDetector.cpp,如下:

if (viewImage_) {
    
    generate_image(buff_[(buffIndex_ + 1)%3], ipl_);
    displayInThread(0);
} else {
    
    generate_image(buff_[(buffIndex_ + 1)%3], ipl_);
}

5、利用摄像头实时显示

roscore
roslaunch realsense2_camera rs_rgbd.launch
roslaunch darknet_ros darknet_ros.launch

步骤同上1-4.若出现多检测框,检测错误
解决:进入darknet_ros/config,打开darknet_ros.launch,修改如下

arg name="network_param_file"         default="$(find darknet_ros)/config/yolov2-tiny.yaml"/
 
改为
 
arg name="network_param_file"         default="$(find darknet_ros)/config/yolov3.yaml"/

三、本地视频测试

1、在src下建立包

catkin_create_pkg local_vedio_detect std_msgs rospy roscpp

2、话题模型创建

(1)创建videopub.cpp

#include<ros/ros.h>
#include<cv_bridge/cv_bridge.h>
#include<sensor_msgs/image_encodings.h>
#include<image_transport/image_transport.h>

#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>

#include<stdio.h>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    
    // ROS节点初始化
    ros::init(argc, argv, "image_publisher");
    ros::NodeHandle n; 
    ros::Time time = ros::Time::now();
    ros::Rate loop_rate(5);
    
     // 定义节点句柄   
    image_transport::ImageTransport it(n);
    image_transport::Publisher pub = it.advertise("/camera/image_raw", 1);
    sensor_msgs::ImagePtr msg;
        
    // opencv准备读取视频
    cv::VideoCapture video;
    video.open("/home/data/11.mp4");  

    if( !video.isOpened() )
    {
    
        ROS_INFO("Read Video failed!\n");
        return 0;
    }
    Mat frame;
    int count = 0;
    while(1)
    {
    
        video >> frame;
        if( frame.empty() )
            break;
        count++;
        
        msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", frame).toImageMsg();
        pub.publish(msg);
        
        ROS_INFO( "read the %dth frame successfully!", count );
        loop_rate.sleep();
        ros::spinOnce();
    }
    video.release();
    
    return 0;
}

注意: /camera/image_raw与ros.yaml中camera_reading中的topic一致

     // 定义节点句柄   
    image_transport::ImageTransport it(n);
    image_transport::Publisher pub = it.advertise("/camera/image_raw", 1);
    sensor_msgs::ImagePtr msg;

(2)创建videosub.cpp

#include<ros/ros.h>
#include<cv_bridge/cv_bridge.h>
#include<sensor_msgs/image_encodings.h>
#include<image_transport/image_transport.h>

#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>

#include<stdio.h>
#include<math.h>
#include<vector>


void imageCalllback(const sensor_msgs::ImageConstPtr& msg)
{
    
	ROS_INFO("Received \n");
	try{
    
        cv::imshow( "video", cv_bridge::toCvShare(msg, "bgr8")->image );
        cv::waitKey(30);
    }
    catch( cv_bridge::Exception& e )
    {
    
        ROS_ERROR( "Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str() );
    }
}

int main(int argc, char** argv)
{
    
	ros::init(argc, argv, "image_listener");
	ros::NodeHandle n;
    cv::namedWindow("video");
    cv::startWindowThread();

    image_transport::ImageTransport it(n);
    image_transport::Subscriber sub = it.subscribe( "video_image", 1, imageCalllback );

	
	ros::spin();
    cv::destroyWindow("video");
	return 0;
}

(3)CMakeList.txt修改

a: find_package(catkin …)修改为一下内容

find_package(catkin REQUIRED COMPONENTS
  cv_bridge
  image_transport
  roscpp
  rospy
  sensor_msgs
  std_msgs
)
find_package(OpenCV REQUIRED)

b: 将include_directories(…)修改为以下内容

include_directories(include ${catkin_INCLUDE_DIRS})
include_directories(include ${OpenCV_INCLUDE_DIRS})
 
add_executable(videopub src/videopub.cpp)
target_link_libraries(videopub ${catkin_LIBRARIES} ${OpenCV_LIBRARIES})
#add_dependencies(mytest opencvexam_gencpp)

add_executable(videosub src/videosub.cpp)
target_link_libraries(videosub ${catkin_LIBRARIES} ${OpenCV_LIBRARIES})

3、编译

catkin_make

4、运行

roscore
roslaunch darknet_ros darknet_ros.launch
rosrun local_vedio_detect vediopub

注意:显示框中满屏横线,解决同上
解决:进入darknet_ros/config,打开darknet_ros.launch,修改如下

arg name="network_param_file"         default="$(find darknet_ros)/config/yolov2-tiny.yaml"/
 
改为
 
arg name="network_param_file"         default="$(find darknet_ros)/config/yolov3.yaml"/

参考链接:https://blog.csdn.net/JIEJINQUANIL/article/details/106461895

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_45702256/article/details/112464457

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签