opencv处理深度图基本操作

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

opencv处理深度图,和处理普通图像差不多,但是有一些地方需要注意。

  1. opencv数据类型对应关系:
    在这里插入图片描述

  2. opencv数据类型对应的解释:
    在这里插入图片描述

一、opencv读取深度图

深度图为tiff文件,一般是单通道32位,也即CV_32F(对应5,也即float类型)。有必要在读取图像后,输出一下数据类型,以防后续对像素进行操作时出现错误

	cv::Mat img = cv::imread("../.tiff", -1);
	std::cout << "img.type() = " << img.type() << std::endl;
	if (img.empty()) {
		cout << "请检查文件名称是否有误!" << endl;
		return -1;
	}

深度图为png文件,一般是单通道16位,也即CV_16U(对应2,也即ushort)。

二、opencv处理深度图像素

以float类型为例:

	for (int i = 0; i < img.rows; i++)
	{
		for (int j = 0; j < img.cols; j++)
		{
			cout << "d= " << img.at<float>(i, j) << endl;
			cout << "d = " << img.ptr<float>(i)[j] << endl;
		}
	}

考虑到png格式的深度图,根据type类型,将float改成short或者ushort即可

三、opencv处理深度图

1.中值滤波

	cv::Mat median;
	cv::medianBlur(depth, median, 5);//对于深度图,卷积核大小只能为3或5

2.高斯滤波

	cv::Mat gauss;
	cv::GaussianBlur(depth, gauss, cv::Size(3, 3), 5, 5);

3.求梯度

	cv::Mat xgrad, ygrad;
	//这里为什么用CV_32F, 因为深度图是CV_16U,我们设置输出图像的深度比灰度图更大, 就可以容纳更大的特征值, 提取效果也就更明显, 
	//你也可以填-1等同于输入图像的深度,但是反正不能小于输入图像的深度。
	//cv::Scharr(median, xgrad, CV_32F, 1, 0);
	//cv::Scharr(median, ygrad, CV_32F, 0, 1);
	cv::Sobel(depth, xgrad, CV_32F, 1, 0, 3); // 使用Gx
	cv::Sobel(depth, ygrad, CV_32F, 0, 1, 3); // 使用Gy
	
	//这个函数的作用是保证Sobel算子操作过后有些负数结果值不被置为0, 也就是不被截取掉
	cv::convertScaleAbs(xgrad, xgrad);
	cv::convertScaleAbs(ygrad, ygrad);

	cv::Mat xygrad = cv::Mat(xgrad.size(), xgrad.type()); // 初始化图像
	cv::addWeighted(xgrad, 0.5, ygrad, 0.5, 0, xygrad);
	

四、深度图转点云

这里是单通道的深度图,也即非彩色;对于彩色图,遍历时需要m+=3,彩色信息按照已注释部分添加即可

	float fx = ...;
	float fy = ...;
	float cx = ...; 
	float cy = ...; 

	for (int m = 0; m < depth.rows; m++)//循环遍历新的关键帧的深度值的行
	{
		for (int n = 0; n < depth.cols; n++)//循环遍历新的关键帧的深度值的列
		{
			//std::cout << depth.ptr<short>(m)[n] << std::endl;
			float d = 0;
			if (depth.type() == CV_16U && depth.channels() == 1)
				d = depth.ptr<short>(m)[n];//depth是一个opencv里的mat类型,使用指针进行遍历
			else if (depth.type() == CV_32F && depth.channels() == 1)
				d = depth.ptr<float>(m)[n];
			else
				continue;

			if (d < 10 || d > 50000)//排除掉深度值过大或过小的点
				continue;
			if (_isnan(d))//排除nan值点
				continue;

			pcl::PointXYZ p;
			p.z = d;
			p.x = (n - cx) * p.z / fx;//cx,fx,fy是相机内参
			p.y = (m - cy) * p.z / fy;//相当于把像素坐标转化为相机坐标

			//p.b = imageRGB.ptr<uchar>(m)[n * 3];//保存每个点的rgb值
			//p.g = imageRGB.ptr<uchar>(m)[n * 3 + 1];
			//p.r = imageRGB.ptr<uchar>(m)[n * 3 + 2];

			cloud->points.push_back(p);//将每个点保存到 PointCloud中的 points里面
		}
	}

总结

总结了下opencv对深度图常规操作,后续遇到新情况继续添加补充。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值