当前位置: 首页 > article >正文

open3d+opencv实现矩形框裁剪点云操作(C++)

👑主页:吾名招财
👓简介:工科学硕,研究方向机器视觉,爱好较广泛…
​💫签名:面朝大海,春暖花开!

open3d+opencv实现矩形框裁剪点云操作(C++)

  • 1,引言
  • 2,相关测试数据资源如下
  • 3,彩色图、深度图和相机内参
  • 4,C++代码
  • 5,最终效果

1,引言

  针对彩色图和深度图以及相机内参可以合成点云,而对某一区域的点云数据截取,可以通过二维ROI区域截取深度图及彩色图出来。不过不能整张图像裁剪,其图像大小不能变,把除了截取区域外的给置为0就行了。

2,相关测试数据资源如下

  本人上传了一个用于三维重建测试的公开数据集,内含彩色图、深度图、相机内参、相机位姿等相关数据,可用于相关测试
https://download.csdn.net/download/qq_44870829/90236553
在这里插入图片描述

3,彩色图、深度图和相机内参

在这里插入图片描述
在这里插入图片描述

4,C++代码

#include <string>
#include <iostream>
#include "Open3D/Open3D.h"
#include <opencv2/opencv.hpp>

using namespace std;


open3d::geometry::Image o3d_cv(const cv::Mat& A) {
	open3d::geometry::Image B;
	int bytes_per_channel = (A.depth() / 2 + 1);//refer to the fuction depth
	B.Prepare(A.cols, A.rows, A.channels(), bytes_per_channel);
	std::memcpy(B.data_.data(), A.data, A.total() * A.channels() * bytes_per_channel);
	return B;
}

int main(int argc, char* argv[]) {

	//--------------------------------------1,相关参数----------------------------------
	//要截取的ROI区域大小
	int x = 285;
	int y = 363;
	int w = 150;
	int h = 120;

    //相机内参设置
	int width = 640;   // 输入图像的宽度
	int height = 480;  // 输入图像的高度
	double fx = 585; // x轴焦距 
	double fy = 585; // y轴焦距
	double cx = 320; // 相机原点的x坐标
	double cy = 240; // 相机原点的y坐标

	// 方式一
	auto intrinsic = open3d::camera::PinholeCameraIntrinsic(width, height, fx, fy, cx, cy); // 使用自定义内参
	 方式二
	open3d::camera::PinholeCameraIntrinsic intrinsic = open3d::camera::PinholeCameraIntrinsic();
	intrinsic.SetIntrinsics(width, height, fx, fy, cx, cy);
	//open3d::camera::PinholeCameraIntrinsic intrinsic = open3d::camera::PinholeCameraIntrinsic(
	//	open3d::camera::PinholeCameraIntrinsicParameters::PrimeSenseDefault); // 使用默认内参

    // -RGBD图像参数设置
	double depth_scale = 1000.0; // 深度值的缩放倍数
	double depth_trunc = 3.0;    // 深度值的截断系数
	bool convert_rgb_to_intensity = false; // 是否将彩色图转为强度图

	//-------------------------------------2,读取图像并裁剪-------------------------------------
	//用opencv读取二维彩色图及深度图像,将某一ROI区域裁剪出来,然后再进行点云生成
	cv::Mat colorimg = cv::imread("frame-000276.color.jpg");
	cv::Mat depthimg = cv::imread("frame-000276.depth.png", -1);  //深度图要读取原图

	//制作ROI区域掩膜
	cv::Mat templateImg_color = cv::Mat::zeros(colorimg.size(), colorimg.type());
	cv::Mat mask = cv::Mat::zeros(colorimg.size(), colorimg.type());
	cv::rectangle(mask, cv::Point(x, y), cv::Point(x + w, y + h), cv::Scalar(255, 255, 255), -1);//矩形的两个顶点,两个顶点都包括在矩形内部
	colorimg.copyTo(templateImg_color, mask);

	cv::Mat templateImg_depth = cv::Mat::zeros(depthimg.size(), depthimg.type());
	cv::Mat mask2 = cv::Mat::zeros(depthimg.size(), CV_8UC1);
	cv::rectangle(mask2, cv::Point(x, y), cv::Point(x + w, y + h), cv::Scalar(255, 255, 255), -1);//矩形的两个顶点,两个顶点都包括在矩形内部
	//cv::bitwise_and();
	depthimg.copyTo(templateImg_depth, mask2);

	//-------------------------------------3,显示未裁剪前的原始点云-------------------------------------
	open3d::geometry::Image color_o = o3d_cv(colorimg);
	open3d::geometry::Image depth_o = o3d_cv(depthimg);
	// 生成RGBD图像
	std::shared_ptr<open3d::geometry::RGBDImage> rgbd_image_o = open3d::geometry::RGBDImage::CreateFromColorAndDepth(
		color_o,                    // 输入的彩色图像
		depth_o,                    // 输入的深度图像
		depth_scale,              // 深度值的缩放倍数
		depth_trunc,              // 深度值大于该值将被截断为0
		convert_rgb_to_intensity);// 设置是否将彩色图像转为强度图
   // RGBD转点云
	auto pcd_o = open3d::geometry::PointCloud::CreateFromRGBDImage(*rgbd_image_o, intrinsic);
	open3d::visualization::DrawGeometries({ pcd_o });

	//-------------------------------------4,显示并保存裁剪后的点云-------------------------------------
	open3d::geometry::Image color = o3d_cv(templateImg_color);
	open3d::geometry::Image depth = o3d_cv(templateImg_depth);

	直接使用open3d读取图像
	//open3d::geometry::Image color, depth;
	//open3d::io::ReadImage("0.png", color); // 读取彩色图像
	//open3d::io::ReadImage("0_depth.png", depth); // 读取深度图像

	//将裁剪后的深度图及彩色图转换成点云并显示保存

	//输出图像基本信息
	open3d::utility::LogInfo("Reading RGBD image : ");
	open3d::utility::LogInfo("     Color : {:d} x {:d} x {:d} ({:d} bits per channel)",
		color.width_, color.height_, color.num_of_channels_,
		color.bytes_per_channel_ * 8);
	open3d::utility::LogInfo("Depth : {:d} x {:d} x {:d} ({:d} bits per channel)",
		depth.width_, depth.height_, depth.num_of_channels_,
		depth.bytes_per_channel_ * 8);

	// 生成RGBD图像
	std::shared_ptr<open3d::geometry::RGBDImage> rgbd_image = open3d::geometry::RGBDImage::CreateFromColorAndDepth(
		color,                    // 输入的彩色图像
		depth,                    // 输入的深度图像
		depth_scale,              // 深度值的缩放倍数
		depth_trunc,              // 深度值大于该值将被截断为0
		convert_rgb_to_intensity);// 设置是否将彩色图像转为强度图
    // RGBD转点云
	auto pcd = open3d::geometry::PointCloud::CreateFromRGBDImage(*rgbd_image, intrinsic);
	open3d::visualization::DrawGeometries({ pcd });

	//5.保存点云文件 保存
	open3d::io::WritePointCloudToPCD("moban.pcd", *pcd, false);
	//open3d::io::WritePointCloudToPCD("search.pcd", *pcd, false);

	return 0;
}

5,最终效果

未裁剪前的点云
在这里插入图片描述

裁剪后的点云
在这里插入图片描述


http://www.kler.cn/a/503335.html

相关文章:

  • 【ArcGIS初学】产生随机点计算混淆矩阵
  • 主数据系统建设模式分析
  • WPF 如何添加系统托盘
  • 支持Google Analytics快捷添加的CMS:费用与部署形式详解
  • Springboot Rabbitmq + 线程池技术控制指定数量task执行
  • ubuntu20.04 安装RTX2060驱动
  • 【动态规划-矩阵】5.下降路径最小和
  • 蓝牙的UUID(Universally Unique Identifier,通用唯一识别码)
  • 探索深度学习:开启智能新时代
  • 信号量机制之苹果-橘子问题
  • 【汇编】x86汇编编程寄存器资源心中有数
  • vulnhub靶场【IA系列】之Tornado
  • 地瓜机器人RDK Studio使用入门教程
  • 《自动驾驶与机器人中的SLAM技术》ch10:自动驾驶车辆的实时定位系统
  • 解决 vxe-table 的下拉框、日期选择等组件被 element-plus element-ui 弹窗遮挡问题 z-index
  • es 3期 第23节-运用Pipeline实现二转聚合统计
  • 【AI日记】25.01.14
  • 【Linux】从零开始:编写你的第一个Linux进度条小程序
  • PostgreSQL技术大讲堂 - 第78讲:分布式数据库-GreenPlum应用实践
  • 实战threeJS数字孪生开源 数字工厂
  • 关于扫描模型 拓扑 和 传递贴图工作流笔记
  • python检测gitlab中某个标签在一个月内添加和移除了多少次
  • Microsoft
  • 【微信小程序】let和const-综合实训
  • 【spring mvc】文件上传、下载
  • 【练习】力扣热题100 有效的括号