yolov4 在ROS、rviz

8 篇文章 1 订阅
6 篇文章 0 订阅

一、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

  • 5
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值