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

486 阅读4分钟

效果

屏幕截图-2023年04月07日 屏幕视频 19时26分57秒.webm-2.png

实现

本项目采用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})
 

奥比中光深度相机驱动

blog.csdn.net/m0_55986434…