摘要:ros下,利用realsense D435采集深度图,并将其转换成opencv的数据类型。

一. RGBD图像采集

通过image_transport包,根据给定的采集速度从realsense D435发布的topic中订阅深度图的代码。

void depth_Callback(const sensor_msgs::ImageConstPtr& depth_msg)
{
cv_bridge::CvImagePtr depth_ptr;
try
{
//cv::imshow("depth_view", cv_bridge::toCvShare(depth_msg, sensor_msgs::image_encodings::TYPE_16UC1)->image);
//depth_ptr = cv_bridge::toCvCopy(depth_msg, sensor_msgs::image_encodings::TYPE_16UC1);
cv::imshow("depth_view", cv_bridge::toCvShare(depth_msg, sensor_msgs::image_encodings::TYPE_32FC1)->image);
depth_ptr = cv_bridge::toCvCopy(depth_msg, sensor_msgs::image_encodings::TYPE_32FC1); cv::waitKey();
}
catch (cv_bridge::Exception& e)
{
ROS_ERROR("Could not convert from '%s' to '32fc1'.", depth_msg->encoding.c_str());
} }

在main函数中,

image_transport::ImageTransport it(nh);
image_transport::Subscriber sub1 = it.subscribe("/camera/aligned_depth_to_color/image_raw", 1, depth_Callback);

如代码所示,在ros中采集到的深度图是ros自带的数据类型sensor_msgs::image。如果要利用opencv对该深度图像进行操作,则需要转换成opencv的图像数据类型Mat,这一步转换操作通过cv_bridge完成。

在上述代码中, sensor_msgs::image_encodings::TYPE_16UC1 表示将ros数据类型转换cv数据类型的编码方式。一般而言,深度图的编码方式都有8UC, 16UC1, 32FC1等三种。在我们的程序中,如何判断选用哪种编码方式呢?最好的方法就是,深度图转换成cv数据类型后将深度值print出来,以此选定最佳的编码方式。

二. 读取深度值

深度图转换成opencv的数据类型后,需要读取其中的深度值。这里着重介绍opencv矩阵元素的操作方法。

opencv中矩阵元素值的读取方法,转自https://blog.csdn.net/u011028345/article/details/73185166

1, 利用at函数读取

(1)单通道图像读取

Mat img1 = imread(filename,IMREAD_GRAYSCALE);
for( size_t nrow = ; nrow < img1.rows; nrow++)
{
for(size_t ncol = ; ncol < img1.cols; ncol++)
{
uchar val = mat_CV_8UC1.at<uchar>(nrow,ncol);
}
}

(2)三通道图像读取

Mat img2 = imread(filename,IMREAD_COLOR);
for( size_t nrow = ; nrow < img2.rows; nrow++)
{
for(size_t ncol = ; ncol < img2.cols; ncol++)
{
Vec3i bgr = mat_CV_8UC3.at<Vec3b>(nrow,ncol);//用Vec3b也行
cout << "("<<bgr.val[]<<","
<<bgr.val[]<<","
<<bgr.val[]<<")";
}
cout << endl;
}

2, 使用指针读取

for( size_t nrow = ; nrow < img3.rows; nrow++)
{
uchar* data = img3.ptr<uchar>(nrow);
for(size_t ncol = ; ncol < img3.cols * img3.channels(); ncol++)
{
cout << int( data[ncol] ) ;
}
cout << endl;
}

3, 使用迭代器

Mat img4 = imread(filename,IMREAD_GRAYSCALE);
MatIterator_<uchar> it = img4.begin<uchar>(), it_end = img4.end<uchar>();
for(int cnt = ; it != it_end; ++it)
{
cout << ( int(*it) ) ;
if( (cnt++ % img4.cols) == )
cout << endl;
}

4, 使用矩阵元素的地址定位

Mat img5(rows, cols,CV_8U, Scalar());
for( size_t nrow = ; nrow < img5.rows; nrow++)
for(size_t ncol = ; ncol < img5.cols; ncol++)
{
cout<<(int)(*(img5.data+img5.step[]*nrow+img5.step[]*ncol));
}

5, 补充:在使用 at 函数的情况下需要预先知道Mat变量中存储的元素类型,如果类型不匹配就会出现读错误。所以可以采用c++  boost库中的BOOST_TYPEOF来获取图像的元素数据类型。

Mat img6 = imread(filename);
typedef BOOST_TYPEOF(*img6.data) ElementType
for( size_t nrow = ; nrow < img1.rows; nrow++)
{
for(size_t ncol = ; ncol < img1.cols; ncol++)
{
cout<<mat_CV_8UC1.at<ElementType>(nrow,ncol);
}
}

关于如何判断opencv矩阵元素的数据类型,方法转自https://www.jianshu.com/p/204f292937bb

cv::Mat 类的对象有一个成员函数 type() 用来返回矩阵元素的数据类型,返回值是 int类型,不同的返回值代表不同的类型。OpenCV Reference Manual 中对 type() 的解释如下所示:

Mat::type
C++: int Mat::type() const
The method returns a matrix element type. This is an identifier compatible with the CvMat type system, like CV_16SC3 or 16-bit signed 3-channel array, and so on.

以本例的深度图为,

int pic_type = depth_ptr->image.type();
std::cout << "the element type of depth_pic is " << pic_type << std::endl;

从type()函数返回一个整数值,下一步就是查找返回值和具体类型之间的对应关系。

OpenCV中定义的图像数据类型可以由以下公式给出,

CV_<bit-depth>{U|S|F}C(<number_of_channels>).

其中,U为无符号整数,S为有符号整数,F为浮点数。

注意事项:

so CV_8UC3 is an 8-bit unsigned integer matrix/image with 3 channels. Although it is most common that this means an RGB (or actually BGR) image, it does not mandate it. It simply means that there are three channels, and how you use them is up to you and your application.

OpenCV常用的6种数据类型缩写

b = unsigned char,    8 bit    [0~255]

w = unsigned short,  16 bit  [0~65535]

s = short,                   16 bit [-32768~32767]

i = int

f = float

d = double

深度图从ros数据类型转换成opencv数据类型的更多相关文章

  1. Java将其他数据类型转换成JSON字符串格式

    Student.java package com.demo.servlet; import java.util.List; import java.util.Map; public class Stu ...

  2. mysql中将一个数据类型转换成另外的数据类型?mysql中cast函数的使用?

    需求描述: 今天在看mysql的函数,提到了通过cast函数将一个数据类型值转换为特定类型的结果值. 在此记录下.将一个表达式转换为特定精度的小数. 操作过程: 1.查看6/4的结果 mysql; + ...

  3. ibtais中把clob数据类型转换成string并展示到前台

    1,在xml中定义一个resultMap <resultMap class="com.aa.bb" id="clobToString"> <r ...

  4. ibtais中把clob数据类型转换成string并插入到数据库中

    1,在xml中定义一个parameterMap <parameterMap id="stringToClob" class="com.a.b.c"> ...

  5. SQL Server数据类型转换

    在SQL Server日常的函数.存储过程和SQL语句中,经常会用到不同数据类型的转换.在SQL Server有两种数据转换类型:一种是显性数据转换:另一种是隐性数据转换.下面分别对这两种数据类型转换 ...

  6. {}+[] = ? 和 []+{} = ? 浅谈JS数据类型转换

    参加公司技术嘉年华第一季(前端.服务端)的间隙,陈导问了我一个问题:{}+[] 和 []+{}两个表达式的值分别是什么?根据我的理解我觉得结果应该都是"[object Object]&quo ...

  7. 第三十五节,json数据类型转换字符串模块

    在使用json模块时需要先 import json 引入模块 json.dumps()模块函数 功能:将Python数据类型转换成字符串[有参] 使用方法:json.dumps(要转换的数据类型变量) ...

  8. 第三十四节,pickle数据类型转换二进制字节码模块

    在使用pickle模块时需要先 import pickle 引入模块 pickle.dumps()模块函数 功能:将python各种类型的数据转换成计算机识别的二进制字节码[有参] 使用方法:pick ...

  9. Struts2(二)之封装请求正文、数据类型转换、数据验证

    一.封装请求正文到对象中(重点) 1.1.静态参数封装 在struts.xml文件中,给动作类注入值,使用的是setter方法 1.2.动态参数封装 通过用户表单封装请求正文参数 1.2.1.动作类作 ...

随机推荐

  1. JWT ajax java spingmvc 简洁教程

    1.添加依赖 <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</ ...

  2. mysql5.5大数据量下表结构升级

    升级一张4万多行(增加一个字段),且包含blob字段的表(blob字段包含100KB左右的数据),运行alter语句:ALTER TABLE `imgdetail` ADD COLUMN  `uplo ...

  3. Saiku本地编译运行后Debug调试(十二)

    Saiku源码拉下来在本地编译通过,然后想进行单元测试 发现不知道怎么写测试类了... 幸好有同事大佬的帮助,教了一招哈哈哈哈... 1.将本地编译通过的Saiku打包好(mvn clean inst ...

  4. PHP有关守护进程,以及流程控制和信号处理函数

    守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程是一种很有用的进程.PHP也可以实现守护进程的功能. 1.基本概念 进程 ...

  5. Xcode10 library not found for -lstdc++ 找不到问题

    在Xcode9上正常编译的项目,在Xcode10上编译可能会遇到如下错误: library not found library not found library not found for -lst ...

  6. BFC清除浮动

    BFC 就是清除浮动 用来处理文档脱离文档流的问题 清除浮动的方法: a.父元素也添加一个浮动 产生弊端就是:margin 不能使用 b.给父元素添加一个:display:inline-block 弊 ...

  7. LeetCode 81 搜索旋转排序数组II

    题目: 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] ). 编写一个函数来判断给定的目标值是否存在于 ...

  8. Unable to load DLL 'api-ms-win-core-localization-l1-2-0.dll': 找不到指定的模块

    asp.net mvc 4.6 发布到WinServer2008R2 SP1 提示 错误 Unable to load DLL 'api-ms-win-core-localization-l1-2-0 ...

  9. 测试同学必备抓包工具--charles之mock数据

    charles中有三个是我经常用到来mock数据的. 一. 打断点--Breakpoints 1. 先切换查看‘Structure’模式 2. 找到目标链接,对其父级进行打断点,如图 3. 取消掉再次 ...

  10. L328 What Is Millennial Burnout?

    What Is Millennial Burnout?Do you often feel stressed? Does the pace of life make you feel like you' ...