赞
踩
/camera/aligned_depth_to_color/image_raw
(即深度对齐到彩色的话题),这样只需要找到彩色图像的坐标影色到它的坐标读取一下深度,再通过内参矩阵计算就行了,而内参矩阵也通过了/camera/aligned_depth_to_color/camera_info
话题发布出来,直接读取即可。代码:
coordinate_map.cpp
/********************** coordinate_map.cpp author: wxw email: wangxianwei1994@foxmail.com time: 2019-7-29 **********************/ #include <iostream> #include <string> #include <opencv2/opencv.hpp> #include <ros/ros.h> #include <cv_bridge/cv_bridge.h> #include <geometry_msgs/PointStamped.h> #include <image_transport/image_transport.h> #include <sensor_msgs/CameraInfo.h> #include <sensor_msgs/Image.h> using namespace cv; using namespace std; class ImageConverter { private: ros::NodeHandle nh_; image_transport::ImageTransport it_; image_transport::Subscriber image_sub_color;//接收彩色图像 image_transport::Subscriber image_sub_depth;//接收深度图像 ros::Subscriber camera_info_sub_;//接收深度图像对应的相机参数话题 ros::Publisher arm_point_pub_;//发布一个三维坐标点,可用于可视化 sensor_msgs::CameraInfo camera_info; geometry_msgs::PointStamped output_point; /* Mat depthImage,colorImage; */ Mat colorImage; Mat depthImage = Mat::zeros( 480, 640, CV_16UC1 );//注意这里要修改为你接收的深度图像尺寸 Point mousepos = Point( 0, 0 ); /* mousepoint to be map */ public: //获取鼠标的坐标,通过param指针传出到类成员Point mousepos static void on_mouse( int event, int x, int y, int flags, void *param ) { switch ( event ) { case CV_EVENT_MOUSEMOVE: /* move mouse */ { Point &tmppoint = *(cv::Point *) param; tmppoint = Point( x, y ); } break; } } ImageConverter() : it_( nh_ ) { //topic sub: image_sub_depth = it_.subscribe( "/camera/aligned_depth_to_color/image_raw", 1, &ImageConverter::imageDepthCb, this ); image_sub_color = it_.subscribe( "/camera/color/image_raw", 1, &ImageConverter::imageColorCb, this ); camera_info_sub_ = nh_.subscribe( "/camera/aligned_depth_to_color/camera_info", 1, &ImageConverter::cameraInfoCb, this ); //topic pub: arm_point_pub_ = nh_.advertise<geometry_msgs::PointStamped>( "/mouse_point", 10 ); cv::namedWindow( "colorImage" ); setMouseCallback( "colorImage", &ImageConverter::on_mouse, (void *) &mousepos ); } ~ImageConverter() { cv::destroyWindow( "colorImage" ); } void cameraInfoCb( const sensor_msgs::CameraInfo &msg ) { camera_info = msg; } void imageDepthCb( const sensor_msgs::ImageConstPtr &msg ) { cv_bridge::CvImagePtr cv_ptr; try { cv_ptr = cv_bridge::toCvCopy( msg, sensor_msgs::image_encodings::TYPE_16UC1 ); depthImage = cv_ptr->image; } catch ( cv_bridge::Exception &e ) { ROS_ERROR( "cv_bridge exception: %s", e.what() ); return; } } void imageColorCb( const sensor_msgs::ImageConstPtr &msg ) { cv_bridge::CvImagePtr cv_ptr; try { cv_ptr = cv_bridge::toCvCopy( msg, sensor_msgs::image_encodings::BGR8 ); colorImage = cv_ptr->image; } catch ( cv_bridge::Exception &e ) { ROS_ERROR( "cv_bridge exception: %s", e.what() ); return; } //先查询对齐的深度图像的深度信息,根据读取的camera info内参矩阵求解对应三维坐标 float real_z = 0.001 * depthImage.at<u_int16_t>( mousepos.y, mousepos.x ); float real_x = (mousepos.x - camera_info.K.at( 2 ) ) / camera_info.K.at( 0 ) * real_z; float real_y = (mousepos.y - camera_info.K.at( 5 ) ) / camera_info.K.at( 4 ) * real_z; char tam[100]; sprintf( tam, "(%0.2f,%0.2f,%0.2f)", real_x, real_y, real_z ); putText( colorImage, tam, mousepos, FONT_HERSHEY_SIMPLEX, 0.6, cvScalar( 0, 0, 255 ), 1 );//打印到屏幕上 circle( colorImage, mousepos, 2, Scalar( 255, 0, 0 ) ); output_point.header.frame_id = "/camera_depth_optical_frame"; output_point.header.stamp = ros::Time::now(); output_point.point.x = real_x; output_point.point.y = real_y; output_point.point.z = real_z; arm_point_pub_.publish( output_point ); cv::imshow( "colorImage", colorImage ); cv::waitKey( 1 ); } }; int main( int argc, char **argv ) { ros::init( argc, argv, "coordinate_map" ); ImageConverter imageconverter; ros::spin(); return(0); }
CMakeList.txt
cmake_minimum_required(VERSION 2.8.3) project(coordinate_map) ## Compile as C++11, supported in ROS Kinetic and newer add_compile_options(-std=c++11) find_package(catkin REQUIRED COMPONENTS roscpp rostime std_msgs sensor_msgs message_filters cv_bridge image_transport compressed_image_transport tf compressed_depth_image_transport geometry_msgs ) ## System dependencies are found with CMake's conventions find_package(OpenCV REQUIRED) catkin_package( ) include_directories(include ${catkin_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS} ) add_executable(coordinate_map src/coordinate_map.cpp) target_link_libraries(coordinate_map ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} )
package.xml
<?xml version="1.0"?> <package> <name>coordinate_map</name> <version>1.0.0</version> <description>coordinate_map package</description> <maintainer email="wangxianwei1994@foxmail.com">Wangxianwei</maintainer> <license>BSD</license> <buildtool_depend>catkin</buildtool_depend> <build_depend>roscpp</build_depend> <build_depend>rostime</build_depend> <build_depend>std_msgs</build_depend> <build_depend>sensor_msgs</build_depend> <build_depend>message_filters</build_depend> <build_depend>image_transport</build_depend> <build_depend>compressed_image_transport</build_depend> <build_depend>compressed_depth_image_transport</build_depend> <build_depend>cv_bridge</build_depend> <build_depend>tf</build_depend> <build_depend>nav_msgs</build_depend> <run_depend>message_runtime</run_depend> <run_depend>roscpp</run_depend> <run_depend>rostime</run_depend> <run_depend>std_msgs</run_depend> <run_depend>sensor_msgs</run_depend> <run_depend>message_filters</run_depend> <run_depend>image_transport</run_depend> <run_depend>compressed_image_transport</run_depend> <run_depend>compressed_depth_image_transport</run_depend> <run_depend>cv_bridge</run_depend> <run_depend>tf</run_depend> <run_depend>nav_msgs</run_depend> <export> </export> </package>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。