Python使用open3d或matplotlib库实现显示深度3D效果图

前言:因为客户需要比较直观的看拍摄的深度图的3D效果,所以最好的方法是做成一个可执行的程序给客户,再者python库比较多,实现起来比较快,所以想着用python实现显示深度图的3D效果,代码在windows系统实现并测试通过。

一、安装python需要的依赖库。

pip install open3d -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple

二、python代码。

代码中载入的深度图原图为(.raw格式的二进制文件):16位有符号,小端,图像宽*高=360*640。根据实际修改图像的宽和高,以及计算深度的方法,即可适配不同的深度图。

from asyncio.windows_events import NULL
import numpy as np
import tkinter as tk
from tkinter import filedialog
import sys
#from matplotlib.ticker import LinearLocator, FormatStrFormatter
#from matplotlib.ticker import MultipleLocator,FuncFormatter

#方法1用的库
#import open3d as o3d
#方法2用的库
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D


#放大100倍
def to_percent(temp):
    return '%1.0f'%(100*temp)

root = tk.Tk()
root.withdraw()
#打开文件管理器获取raw图文件目录
file_path = filedialog.askopenfilename()

if file_path == NULL or len(file_path) == 0:
    print("-------------------file is null!-------------------")
    sys.exit(0)

isRaw = file_path.endswith(".raw")
if isRaw == False:
    print("-------------------data format is incorrect!-------------------")
    sys.exit(0)
#读取文件二进制数据
with open(file_path, 'rb') as f:
    data = f.read()
#图像宽和高
w = 360
h = 640

if data == NULL or len(data) != w*h*2:
    print("-------------------data length is incorrect!-------------------" + str(len(data)))
    sys.exit(0)

#使用ImageJ打开深度图,在x=220,y=40时,值9756,深度为9756/16毫米,对应图:depth_pic0_1-90cm-noled.raw
#print("depth data x=220,y=40,value=" + str(data[(40*w+220)*2] + data[(40*w+220)*2+1] * 256))
#坐标点
points = np.zeros((w*h, 3), dtype=np.int16)
n = 0
# i:行,j:列
for i in range(h):
    for j in range(w):
        #深度为值/16(毫米),16位有符号,小端存储
        deep = (data[(i*w+j)*2] + data[(i*w+j)*2+1] * 256) / 16
        points[n][0] = i
        points[n][1] = j
        points[n][2] = deep
        n += 1


"""
#第一种方法显示3D图(使用open3d库),加载很快,手动查看也流畅,只是不显示坐标系和无法查看深度值。
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points)
#o3d.io.write_point_cloud("../../test_data/sync.ply", pcd)

#print("==========")
#print(pcd)
#print(np.asarray(pcd.points))
#print("==========")

#
#o3d.visualization.draw_geometries([pcd],
#                                  zoom=0.3412,
#                                  front=[0.4257, -0.2125, -0.8795],
#                                  lookat=[2.6172, 2.0475, 1.532],
#                                  up=[-0.0694, -0.9768, 0.2024])


# 手动绘制颜色
# pcd.paint_uniform_color([1, 0.706, 0])
#pcd.paint_uniform_color([1, 0.706, 0])
# 三维模型的坐标中心
origin = pcd.get_center()
# 坐标系
coordinate = o3d.geometry.TriangleMesh.create_coordinate_frame(size=0.2, origin=origin - 0.5)
# 可视化
o3d.visualization.draw_geometries([pcd, coordinate])
"""


#第二种方法显示3D图(使用matplotlib库),使用matlab显示,能显示坐标系,能查看到深度值,加载慢、鼠标移动图像很卡
fig = plt.figure(figsize=(10,8))
ax = Axes3D(fig)

#设置z轴刻度范围(最小刻度、最大刻度)
#ax.set_zlim(0, 1200)#有效
#ax.set_zlim3d(0,1200)
#设置z轴刻度个数
#ax.zaxis.set_major_locator(LinearLocator(10))#Z轴显示n个刻度值
#坐标刻度放大
#ax.zaxis.set_major_formatter(FuncFormatter(to_percent))

# x
x = points[:,0]
# y
y = points[:,1]
# z
z = points[:,2]

#ax.plot3D(x,y,z)

#ax.scatter3D()函数,前三个参数是x,y,z轴的数据,s表示每个点放大/缩小的倍数(1表示不放大,可以0~1小数,或>1的数)
#c参数,可设置成需要设置的某个轴的数据,比如:ax.scatter3D(x,y,z,s=1, c=points[:,2:]),等同于ax.scatter3D(x,y,z,s=1, c=z),渐变色默认为viridis
#c可以设置成固定RGB颜色值,则颜色固定,比如:ax.scatter3D(x,y,z,s=1, c=(1.0,0,0))
#cmap为可选参数,参数的值默认用viridis,参数可不写
# c, cmap参数具体使用方法如下
#方法1
#colors = points[:,2:]等同于colors=z,或colors = (1.0,0,0)
#c表示每个点的颜色(固定值则所有点一个颜色,比如c=(1.0,0,0):红色,若是等于和z数据相同长度的数组,则是渐变颜色(颜色默认根据viridis渐变色))
#比如这么写:ax.scatter3D(x,y,z,s=1, c=colors)
#方法2,比较好用
#c可以等于x/y/z表示对x/y/z轴数据进行颜色渐变,可配合cmap使用,可参考文章:https://blog.csdn.net/qq_37851620/article/details/100642566
#cmap的值设置不同,渐变色的区分度也会不同(渐变明显程度,比如使用“Miscellaneous”分类下的,则渐变区分度高)
ax.scatter3D(x,y,z,s=1, c=z, cmap = 'jet')

#设置x轴标签
#plt.xlabel("x-axis")
#plt.ylabel("y-axis")

plt.show()

你可能感兴趣的:(Windows,camera,Python,python,matplotlib,3d)