基于Qt和ros的深度相机的识别测距框架

 效果

实现

本项目采用ros框架,用yolov5作为识别模块,采用奥比中光astra深度相机测距,ui界面显示实时图像,点击显示距离。

代码解释:

思路是把yolov5封装成功能包,用python写一个ros收发接口调用模型。主函数接受yolov5模块识别到的数据,调用深度图像得到距离,再把图像和距离显示在ui界面上。

本程序预留串口通信,可与嵌入式端进行通信,扩展成更多项目。

main.cpp

#include <ros/ros.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/image_encodings.h>
#include <cv_bridge/cv_bridge.h>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <image_transport/image_transport.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/CameraInfo.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
#include <message_filters/subscriber.h>
#include <message_filters/time_synchronizer.h>
#include<message_filters/sync_policies/approximate_time.h>
#include <pcl/point_cloud.h>
#include<thread>
#include<pcl/point_types.h>
#include<pcl_conversions/pcl_conversions.h>
#include<pcl/visualization/cloud_viewer.h>
#include <sensor_msgs/PointCloud2.h>
#include "widget.h"
#include <QApplication>
#include "std_msgs/String.h"
using namespace std;
using namespace sensor_msgs;
using namespace message_filters;
using namespace cv;
typedef pcl::PointXYZRGB PointT;
typedef pcl::PointCloud<PointT> testcloud;
//#include<realsense_dev/depth_value.h>       //自定义一个消息类型
cv::Mat depth_pic;        //定义全局变量,图像矩阵Mat形式
String some="someee";
char some1[30];
//realsense_dev::depth_value command_to_pub;   //待发布数据
double x,y,z;
int n=0;

void depthCallback(const sensor_msgs::Image::ConstPtr&msg)
{
    cv_bridge::CvImagePtr Dest ;
    Dest = cv_bridge::toCvCopy(msg,sensor_msgs::image_encodings::TYPE_16UC1);

    depth_pic = Dest->image;
    //cout<<"Output some info about the depth image in cv format"<<endl;
    //cout<< "Rows of the depth iamge = "<<depth_pic.rows<<endl;                       //获取深度图的行数height
    //cout<< "Cols of the depth iamge = "<<depth_pic.cols<<endl;                           //获取深度图的列数width
    //cout<< "Type of depth_pic's element = "<<depth_pic.type()<<endl;             //深度图的类型
    ushort Ld = depth_pic.at<ushort>(command_to_pub2.x+5,command_to_pub2.y+5);           //读取深度值,数据类型为ushort单位为mm
    ushort Rd = depth_pic.at<ushort>((command_to_pub2.x1+command_to_pub2.x)/2,(command_to_pub2.y1+command_to_pub2.y)/2);           //读取深度值,数据类型为ushort单位为mm
     //ushort Ld = depth_pic.at<ushort>(400,788);           //读取深度值,数据类型为ushort单位为mm
    //ushort Rd = depth_pic.at<ushort>(406,800);           //读取深度值,数据类型为ushort单位为mm
    Rd_value = float(Rd)/1000 ;      //强制转换
    Ld_value = float(Ld)/1000 ;      //强制转换
    cout<< "Value of Rdepth_pic's pixel= "<<Rd_value<< "Value of Ldepth_pic's pixel= "<<Ld_value<<endl;    //读取深度值
}

void imageCallback(const sensor_msgs::ImageConstPtr& msg)
{
// clock_t start,ends;
// start=clock();
    try
    {
        cv::Mat image = cv_bridge::toCvShare(msg, "bgra8")->image; //image_raw就是我们得到的图像了
        int rows = image.rows;//std::cout<<"rows="<<rows<<std::endl;
        int cols = image.cols;//std::cout<<"cols="<<cols<<std::endl;
        cvimage=image;
    }
    catch (cv_bridge::Exception &e)
    {
        ROS_ERROR("Could not conveextrinsicMat_RT from '%s' to 'rgb8'.", msg->encoding.c_str());
    }
// ends=clock();
// std::cout<<"img call:"<<(double (ends-start)/CLOCKS_PER_SEC)<<std::endl;
}

void leidaCallback(const std_msgs::String::ConstPtr& msg_p)
{
ROS_INFO("%s",msg_p->data.c_str());
some=msg_p->data.c_str();
//ROS_INFO("我听见:%s",(*msg_p).data.c_str());
char x[6],y[6],x1[6],y1[6];
int i;
for(i=0;i<some.length();i++)
{
    if(some[i-1]=='F'  && some[i]=='C')
    {
        command_to_pub1.Value[0]=some[i+1];
        command_to_pub1.Value[1]=some[i+2]; 
    }
    if(some[i-1]=='y')  //x y q w h
    {
        for(int q=0;q<6;q++)
        {
                if(some[i+q]!= '.' )
                {
                        y[q]=some[i+q];
                        if(some[i+q]== 'q' )
                        {
                            break;
                        }

                }  
                else
                {
                    continue;
                }
        }
        
    }
    if(some[i-1]=='x')
    {
       for(int q=0;q<6;q++)
        {
                if(some[i+q]!= '.' )
                {
                        x[q]=some[i+q];
                        if(some[i+q]== 'y' )
                        {
                            break;
                        }
                }  
                else
                {
                    continue;
                }
        }
    }
    if(some[i-1]== 'w'   )
    {
       for(int q=0;q<6;q++)
        {
                if(some[i+q]!= '.' )
                {
                        y1[q]=some[i+q];
                        if(some[i+q]== 'h' )
                        {
                            break;
                        }

                }  
                else
                {
                    continue;
                }
        }
    }
    if( some[i-1]== 'q' )
    {
       for(int q=0;q<6;q++)
        {
                if(some[i+q]!= '.' )
                {
                        x1[q]=some[i+q];
                        if(some[i+q]== 'w' )
                        {
                            break;
                        }

                }  
                else
                {
                    continue;
                }
        }
    }
}
    command_to_pub2.x = atoi(x);
    command_to_pub2.y= atoi(y);
    command_to_pub2.x1= atoi(x1);
    command_to_pub2.y1= atoi(y1);
    printf("\nsome:%d,%d,%d,%d",command_to_pub2.x,command_to_pub2.y,command_to_pub2.x1,command_to_pub2.y1);
}


int uuu(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}
void ttt(int argc, char *argv[])
{
    ros::init(argc, argv, "stream_pub");               // ros节点初始化
    ros::NodeHandle nh;                                           //创建节点句柄
     image_transport::ImageTransport it(nh);
    ros::AsyncSpinner spinner(1);
    spinner.start();
    ros::Subscriber sub1 = nh.subscribe<std_msgs::String>("/leida_num",1,leidaCallback);
    ros::Subscriber image_sub = nh.subscribe<sensor_msgs::Image>("/camera/depth/image_raw",1,depthCallback);   //订阅深度图像
    image_transport::Subscriber sub = it.subscribe("/camera/color/image_raw", 1, &imageCallback);
    //ros::Subscriber element_sub = nh.subscribe<sensor_msgs::Image>("/camera/aligned_depth_to_color/image_raw",100,pixelCallback);     //订阅像素点坐标
    //ros::Publisher mode_pub = nh.advertise<realsense_dev::depth_value>("/depth_info", 10);

    //command_to_pub.Value = 0;    //初始化深度值
    ros::Rate rate(20.0);    //设定自循环的频率
    while(ros::ok)
    {
        //command_to_pub.header.stamp      = ros::Time::now();
        //command_to_pub.Value = d_value;     //depth_pic.rows/2,depth_pic.cols/2  为像素点
    }
    
    ros::Duration(10).sleep();    //设定自循环的频率
}
int main(int argc,char *argv[])
{
    int yt;
    thread th2(uuu,argc, argv);
    thread th3(ttt,argc, argv);
    //uuu(argc, argv);
    th2.join();
    th3.join();
    return yt;
}

widget.cpp片段

void Widget::showww()
{
    Rect rect(command_to_pub2.x,command_to_pub2.y,
     command_to_pub2.x1-command_to_pub2.x,command_to_pub2.y1-command_to_pub2.y);
    Mat mat = cvimage;
    //cvtColor( mat,  mat, COLOR_BGR2RGB);//BGR转化为RGB
    QImage::Format format = QImage::Format_ARGB32;
    switch ( mat.type())
    {
    case CV_8UC1:
      format = QImage::Format_Indexed8;
      break;
    case CV_8UC3:
      format = QImage::Format_RGB888;
      break;
    case CV_8UC4:
      format = QImage::Format_ARGB32;
      break;
    }
    QImage image = QImage((const uchar*) mat.data,  mat.cols,  mat.rows,
       mat.cols *  mat.channels(), format);
    /*cvtColor(mat, mat, CV_BGR2RGB);
    QImage image(mat.data, 
			 mat.cols, 
			 mat.rows, 
			 mat.step, 
			 QImage::Format_RGB888);*/
    //QString filename("/home/q/图片/标定二维码/image/1.bmp");
    QImage* img=new QImage;
    img=&image;
    ui->labImgShow->setPixmap(QPixmap::fromImage(*img));
    timer->start(20);//启动计时器
}

void Widget::text()
{
    float uio=5.8;
    String utf5=to_string( Ld_value);
    char  utf8[20];
    strcpy( utf8,utf5.c_str());
    QString str2=QString::fromUtf8(utf8);
    ui->Ldepth_textEdit->append(str2); //接收区显示 -- 追加方式
    ui->Ldepth_textEdit->show();
    String utf6=to_string( Rd_value);
    char  utf9[20];
    strcpy( utf9,utf6.c_str());
    QString str3=QString::fromUtf8(utf9);
    ui->Rdepth_textEdit->append(str3); //接收区显示 -- 追加方式
    ui->Rdepth_textEdit->show();
    String utf59= "people";
    char  utf89[20];
    strcpy( utf89,utf59.c_str());
    QString str26=QString::fromUtf8(utf89);
    ui->name_textEdit->append(str26); //接收区显示 -- 追加方式
    ui->name_textEdit->show();
}

yolov5识别片段

# src=cv2.imread('biye.jpg')
def detect(img):
    time1 = time.time()

    global ros_image
    global xytoxy
    global label_name
    cudnn.benchmark = True
    dataset = loadimg(img)
    # print(dataset[3])
    # plt.imshow(dataset[2][:, :, ::-1])
    names = model.module.names if hasattr(model, 'module') else model.names
    # colors = [[random.randint(0, 255) for _ in range(3)] for _ in range(len(names))]
    # colors=[[0,255,0]]
    augment = 'store_true'
    conf_thres = 0.3
    iou_thres = 0.45
    classes = (0, 1, 2, 3, 5, 7)
    agnostic_nms = 'store_true'
    img = torch.zeros((1, 3, imgsz, imgsz), device=device)  # init img
    _ = model(img.half() if half else img) if device.type != 'cpu' else None  # run once
    path = dataset[0]
    img = dataset[1]
    im0s = dataset[2]
    vid_cap = dataset[3]
    img = torch.from_numpy(img).to(device)
    img = img.half() if half else img.float()  # uint8 to fp16/32
    img /= 255.0  # 0 - 255 to 0.0 - 1.0

    time2 = time.time()
    if img.ndimension() == 3:
        img = img.unsqueeze(0)
    # Inference
    pred = model(img, augment=augment)[0]
    # Apply NMS
    pred = non_max_suppression(pred, conf_thres, iou_thres, classes=classes, agnostic=agnostic_nms)

    view_img = 1
    save_txt = 1
    save_conf = 'store_true'
    time3 = time.time()

    for i, det in enumerate(pred):  # detections per image
        p, s, im0 = path, '', im0s
        s += '%gx%g ' % img.shape[2:]  # print string
        gn = torch.tensor(im0.shape)[[1, 0, 1, 0]]  # normalization gain whwh
        if det is not None:
            # print(det)
            # Rescale boxes from img_size to im0 size
            det[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0.shape).round()
            # Print results
            for c in det[:, -1].unique():
                n = (det[:, -1] == c).sum()  # detections per class
                s += '%g %ss, ' % (n, names[int(c)])  # add to string
                # Write results
            for *xyxy, conf, cls in reversed(det):
                if save_txt:  # Write to file
                    xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist()  # normalized xywh
                    line = (cls, conf, *xywh) if save_conf else (cls, *xywh)  # label format
                    y = torch.tensor(xyxy).view(1, 4)
                    xy = y.clone() if isinstance(y, torch.Tensor) else np.copy(y)
                    xytoxy = xy.view(-1).tolist()
                if view_img:  # Add bbox to image
                    label = '%s %.2f' % (names[int(cls)], conf)
                    label_name = names[int(cls)]
                    plot_one_box(xyxy, im0, label=label, color=[0, 255, 0], line_thickness=3)
    time4 = time.time()
    cv2.putText(im0, str(fps), (20, 20), 0, 0.75, [225, 255, 255], thickness=3, lineType=cv2.LINE_AA)
    print('************')
    print('2-1', time2 - time1)
    print('3-2', time3 - time2)
    print('4-3', time4 - time3)
    print('total', time4 - time1)
    print('xy2xy', xytoxy[0])
    print("label_name:", label_name)
    some = "FC" + str(label_name) + "x" + str(xytoxy[0]) + "y" + str(xytoxy[1]) + "q" + str(xytoxy[2]) + "w" + str(xytoxy[3]) +"h"+ "RA"
    print("label_name:", some)
    out_img = im0[:, :, [2, 1, 0]]
    ros_image = out_img
    cv2.imshow('YOLOV5', out_img)
    a = cv2.waitKey(1)
    #### Create CompressedIamge ####
    # publish_image(im0)
    publish_image1(some)

 CmakeList.cpp

cmake_minimum_required(VERSION 3.5)
project(picture2pcl)

## Compile as C++11, supported in ROS Kinetic and newer
#add_compile_options(-std=c++11)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

find_library(librealsense REQUIRED)

find_package(catkin REQUIRED COMPONENTS
  geometry_msgs
  roscpp
  rospy
  std_msgs
  cv_bridge
  message_generation
  image_transport
  pcl_ros
  sensor_msgs
  tf
  
)
find_package(Eigen3 REQUIRED)
find_package(PCL REQUIRED)
#find_package(realsense2 REQUIRED)
find_package(OpenCV REQUIRED)



catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES realsense_dev
   CATKIN_DEPENDS roscpp std_msgs 
   DEPENDS EIGEN3 PCL OpenCV
  INCLUDE_DIRS
#  DEPENDS system_lib
)


include_directories(
# include
  ${catkin_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
  ${EIGEN3_INCLUDE_DIR}
	${PCL_INCLUDE_DIRS}
)

#add_executable(stream_pub src/stream_pub.cpp)
#target_link_libraries(stream_pub ${catkin_LIBRARIES} ${OpenCV_LIBS})



#add_executable(main src/main.cpp  src/serial_communication.cpp )

#find_package(Qt5 COMPONENTS Widgets REQUIRED)
#find_package(Qt5 COMPONENTS Core SerialPort REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
find_package(Qt5SerialPort REQUIRED)
if(ANDROID)
  add_library(tongxin11 SHARED
    src/main.cpp  
    src/serial_communication.cpp
    src/serial_communication.h
    src/main.cpp
    src/widget.cpp
    src/widget.h
    src/widget.ui
  )
else()
  add_executable(tongxin11
    src/main.cpp  
    src/serial_communication.cpp
    src/serial_communication.h
    src/main.cpp
    src/main.cpp
    src/widget.cpp
    src/widget.h
    src/widget.ui
  )
endif()

target_link_libraries(tongxin11 ${Qt5Core_LIBRARIES}  ${Qt5Widgets_LIBRARIES}  ${Qt5SerialPort_LIBRARIES} ${catkin_LIBRARIES} ${PCL_LIBRARIES} ${OpenCV_LIBS}  -lpthread -luuid)
#target_link_libraries(serialportLIB     ${Qt5Core_LIBRARIES}  ${Qt5Widgets_LIBRARIES}  ${Qt5SerialPort_LIBRARIES})
#target_link_libraries(tongxin11 ${catkin_LIBRARIES} ${PCL_LIBRARIES} ${OpenCV_LIBS})

奥比中光深度相机驱动

奥比中光Orbbec Astra深度相机在ROS Melodic的使用_LCH南安的博客-CSDN博客
 

### 回答1: ROS深度相机小车循迹是指使用ROS(机器人操作系统)结合深度相机技术来实现小车的循迹功能,并使用Python编程语言进行控制。具体步骤如下: 首先,需要搭建ROS环境。安装好ROS之后,我们可以使用ROS提供的各种工具和库来开发和控制我们的小车。 接下来,需要连接深度相机到小车上,并配置好相机的驱动程序。常用的深度相机有Kinect、RealSense等,可以通过官方提供的驱动程序或第三方库进行配置。 然后,需要使用ROS提供的视觉传感器包,例如OpenCV或PCL,读取深度相机的数据。可以通过ROS的图像传输工具将深度图像和彩色图像传输到ROS中。 在ROS中,使用Python编程语言创建一个节点,用于接收深度图像的数据。可以使用ROS提供的点云库对深度图像进行处理,提取出需要的信息,如障碍物的位置和形状。 根据深度图像的信息,可以设计一个算法来实现小车的循迹功能。例如,可以使用视觉巡线算法来检测道路的位置和方向,并根据检测结果调整小车的运动方向和速度。 最后,将控制指令发送给小车的驱动系统,控制小车按照设定的循迹算法运动。可以使用ROS提供的底层硬件驱动接口或者第三方库来实现与小车驱动系统的通信。 综上所述,ROS深度相机小车循迹Python是一种利用ROS深度相机技术来实现小车循迹功能,并通过Python进行控制的方法。通过搭建ROS环境、配置深度相机驱动、读取深度图像数据、设计循迹算法和控制小车运动,可以实现小车在道路上的自动行驶。 ### 回答2: ROS (机器人操作系统) 是一个开源的机器人软件平台,能够帮助开发者轻松地创建机器人应用。ROS 提供了很多功能包和工具,包括与深度相机和小车循迹相关的功能。 深度相机是一种能够感知三维环境信息的摄像头,能够为机器人提供更精确的感知能力。在 ROS 中,可以使用深度相机的驱动程序和库进行数据的获取和处理。例如,可以使用 ROS 中的 OpenCV 和 PCL (点云库) 实现深度图像的处理和分析。通过深度相机,机器人可以感知环境的障碍物、物体位置等信息,以便进行导航和路径规划。 小车循迹是指小车按照预定的线路自动行驶的功能。在 ROS 中,可以使用小车底盘驱动程序来控制小车的运动。利用小车底盘的编码器和传感器信息,我们可以实现小车的定位和导航。结合深度相机的数据,可以进一步提高小车循迹的精确性和稳定性。 Python 是 ROS 中常用的编程语言之一,提供了丰富的库和工具。通过编写 Python 脚本,我们可以实现深度相机和小车循迹的控制。例如,可以使用 ROS 提供的 Python API (Application Programming Interface) 来订阅深度图像的话题,进行图像处理,并发送控制指令给小车底盘。另外,还可以使用一些第三方的 Python 库,如 PyTorch 和 TensorFlow,来进行深度学习和计算机视觉的任务。 总结来说,通过 ROS深度相机和小车底盘的结合,我们可以实现使用 Python 控制小车进行循迹和感知环境的功能。这为机器人应用的开发提供了更强大的工具和平台。 ### 回答3: ROS是一个开源的机器人操作系统,可以帮助我们方便地开发和管理机器人的软硬件系统。深度相机是一种可以获取环境中物体距离和深度信息的相机设备。小车循迹是指小车能够根据特定的路径和线路进行自主行驶的能力。Python是一种流行的编程语言,它具有简洁易懂、易于学习和强大的库支持等特点。 在ROS中,可以使用ROS的Python库来实现小车循迹功能。首先,需要使用ROS提供的深度相机的驱动节点来获取深度图像和距离信息。然后,通过编写Python程序来处理获取到的深度信息,比如使用图像处理算法来识别出特定路径或线路的位置信息。 接下来,可以通过ROS提供的小车控制节点来控制小车的运动。通过Python程序将提取到的位置信息传递给小车控制节点,从而实现小车沿着设定的路径或线路行驶。 在具体实现时,可以使用Python的图像处理库(如OpenCV)来处理深度图像,并使用计算机视觉算法来识别出路径或线路。通过与ROS相结合,可以利用ROS提供的通信机制将图像处理和小车控制部分进行集成。 总之,通过ROS深度相机和Python的图像处理能力,结合小车控制节点,可以实现小车循迹的功能。通过编写Python程序和与ROS进行通信,可以使小车根据深度相机的获取信息来自主行驶。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值