点云投影为深度图

一、原理

上一篇我们讲了深度图生成点云,同理点云也能生成深度图
在这里插入图片描述

  • 由于遮挡,映射到相同像素坐标的物体在深度图中只保留最近物体。图中近景点云遮挡远景点云
  • 图中点云稀疏出发生“透射”现象。对于一些测量应用“透射”现象带来错误数据

二、“透射”问题的解决——使用灰度图形态学滤波

在这里插入图片描述

# !/usr/bin/python3
# coding=utf-8

import numpy as np

CAM_WID, CAM_HGT = 640, 480  # 重投影到的深度图尺寸
CAM_FX, CAM_FY = 795.209, 793.957  # fx/fy
CAM_CX, CAM_CY = 332.031, 231.308  # cx/cy

EPS = 1.0e-16

# 加载点云数据
pc = np.genfromtxt('pc_rot.csv', delimiter=',').astype(np.float32)

# 滤除镜头后方的点
valid = pc[:, 2] > EPS
z = pc[valid, 2]

# 点云反向映射到像素坐标位置
u = np.round(pc[valid, 0] * CAM_FX / z + CAM_CX).astype(int)
v = np.round(pc[valid, 1] * CAM_FY / z + CAM_CY).astype(int)

# 滤除超出图像尺寸的无效像素
valid = np.bitwise_and(np.bitwise_and((u >= 0), (u < CAM_WID)),
                       np.bitwise_and((v >= 0), (v < CAM_HGT)))
u, v, z = u[valid], v[valid], z[valid]

# 按距离填充生成深度图,近距离覆盖远距离
img_z = np.full((CAM_HGT, CAM_WID), np.inf)
for ui, vi, zi in zip(u, v, z):
    img_z[vi, ui] = min(img_z[vi, ui], zi)  # 近距离像素屏蔽远距离像素

# 小洞和“透射”消除
img_z_shift = np.array([img_z, \
                        np.roll(img_z, 1, axis=0), \
                        np.roll(img_z, -1, axis=0), \
                        np.roll(img_z, 1, axis=1), \
                        np.roll(img_z, -1, axis=1)])
img_z = np.min(img_z_shift, axis=0)

# 保存重新投影生成的深度图dep_rot
np.savetxt('dep_rot.csv', img_z, fmt='%.12f', delimiter=',', newline='\n')

# 加载刚保存的深度图dep_rot并显示
import matplotlib.pyplot as plt

img = np.genfromtxt('dep_rot.csv', delimiter=',').astype(np.float32)
plt.imshow(img, cmap='jet')
plt.show()


  • 11
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
转化为深度的过程可以理解为将三维坐标映射到二维平面上,也就是将点中每个点的深度信息转化为像素的灰度值。下面是一个简单的点深度的 C 代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define WIDTH 640 #define HEIGHT 480 typedef struct { float x, y, z; } Point3f; typedef struct { unsigned char r, g, b; } ColorRGB; typedef struct { Point3f pos; ColorRGB color; } Vertex; // 将点投影深度上 void projectPointCloud(Vertex *pointCloud, int numPoints, unsigned short *depthMap) { // 将深度初始化为最大值 for (int i = 0; i < WIDTH * HEIGHT; i++) { depthMap[i] = 0xFFFF; } float fx = 525.0f; // 相机内参 float fy = 525.0f; float cx = 319.5f; float cy = 239.5f; for (int i = 0; i < numPoints; i++) { Point3f pos = pointCloud[i].pos; int x = (int)(pos.x * fx / pos.z + cx); int y = (int)(pos.y * fy / pos.z + cy); // 将点的深度信息转化为灰度值 unsigned short depth = (unsigned short)(pos.z * 1000.0f); if (x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT && depth < depthMap[y * WIDTH + x]) { depthMap[y * WIDTH + x] = depth; } } } int main(void) { int numPoints = 10000; Vertex *pointCloud = (Vertex *)malloc(sizeof(Vertex) * numPoints); unsigned short *depthMap = (unsigned short *)malloc(sizeof(unsigned short) * WIDTH * HEIGHT); // 生成随机点 for (int i = 0; i < numPoints; i++) { pointCloud[i].pos.x = ((float)rand() / RAND_MAX - 0.5f) * 10.0f; pointCloud[i].pos.y = ((float)rand() / RAND_MAX - 0.5f) * 10.0f; pointCloud[i].pos.z = ((float)rand() / RAND_MAX) * 5.0f + 5.0f; pointCloud[i].color.r = (unsigned char)(255 * (pointCloud[i].pos.x / 10.0f + 0.5f)); pointCloud[i].color.g = (unsigned char)(255 * (pointCloud[i].pos.y / 10.0f + 0.5f)); pointCloud[i].color.b = (unsigned char)(255 * (pointCloud[i].pos.z / 10.0f)); } // 将点投影深度上 projectPointCloud(pointCloud, numPoints, depthMap); // 保存深度 FILE *fp = fopen("depthMap.bin", "wb"); fwrite(depthMap, sizeof(unsigned short), WIDTH * HEIGHT, fp); fclose(fp); free(pointCloud); free(depthMap); return 0; } ``` 这段代码中,我们首先定义了一个点数据结构 `Vertex`,其中包含了每个点的坐标和颜色信息。然后我们实现了一个 `projectPointCloud` 函数,该函数将点投影深度上,其中使用了相机内参和透视投影的知识。最后我们生成了随机点数据,将其投影深度上,并将深度保存到文件中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值