我使用此代码https://www.programmersought.com/article/8773686326/通过整合RGB和深度图像来创建RGBD 现在我想知道 RGBD 文件是否可以保存为 single 图像(jpeg、png...) 我尝试过,但没有成功,通过使用 imageio.imwrite()、plt.imsave()、cv2.imwrite()...可能是由于尺寸 [4,64,1216],那么有没有办法实现它?
scale = (64, 1216)
resize_img = transforms.Resize(scale, Image.BILINEAR)
resize_depth = transforms.Resize(scale, Image.NEAREST)
to_tensor = transforms.ToTensor()
img_id = 0
# load image and resize
img = Image.open('RGB_image.jpg')
img = resize_img(img)
img = np.array(img)
# load depth and resize
depth = Image.open('depth_image.png')
depth = resize_depth(depth)
depth = np.array(depth)
depth = depth[:, :, np.newaxis]
# tensor shape and value, normalization
img = Image.fromarray(img).convert('RGB')
img = to_tensor(img).float()
depth = depth / 65535
depth = to_tensor(depth).float()
rgbd = torch.cat((img, depth), 0)
print("\n\nRGBD shape")
print(rgbd.shape)
我们可以将深度保存为 RGBA 像素格式的图像的 Alpha 通道。
Alpha通道应用透明通道,但我们可以将其用作第四通道来存储RGB和深度。
由于深度可能需要高精度 - 可能需要
float32
精度,我建议使用 OpenEXR 图像格式。float32
。
注:
以下代码示例使用 OpenCV 而不是 Pillow。
我以为 OpenCV 支持 EXR 文件格式,但我的 OpenCV Python 版本不支持 EXR。我用 ImageIO 包代替。
将 RGB 和深度转换并写入 EXR 文件的阶段:
加载 RGB 图像,调整其大小并转换为浮点数:
img = cv2.imread('RGB_image.jpg') # The channels order is BGR due to OpenCV conventions.
img = cv2.resize(img, scale, interpolation=cv2.INTER_LINEAR)
img = img.astype(np.float32) / 255 # Convert to float in range [0, 1]
加载深度图像,调整大小并转换为浮动:
depth = cv2.imread('depth_image.png', cv2.IMREAD_UNCHANGED) # Assume depth_image.png is 16 bits grayscale.
depth = cv2.resize(depth, scale, interpolation=cv2.INTER_NEAREST)
depth = depth.astype(np.float32) / 65535 # Convert to float in range [0, 1]
合并
img
(3 个通道)和 depth
(1 个通道)至 4 个通道:(1216, 64, 4)
(应用 OpenCV BGRA 颜色约定)。
bgrd = np.dstack((img, depth))
将
bgrd
写入 EXR 文件:cv2.imwrite('rgbd.exr', bgrd)
。 rgbd = cv2.cvtColor(bgrd, cv2.COLOR_BGRA2RGBA)
imageio.imwrite('rgbd.exr', rgbd)
代码示例(将 RGB 和 Range 转换为 RGBA EXR 文件,然后读取并转换回来):
import numpy as np
import cv2
import imageio
scale = (64, 1216)
# load image and resize
img = cv2.imread('RGB_image.jpg') # The channels order is BGR due to OpenCV conventions.
img = cv2.resize(img, scale, interpolation=cv2.INTER_LINEAR)
img = img.astype(np.float32) / 255 # Convert to float in range [0, 1]
# load depth and resize
depth = cv2.imread('depth_image.png', cv2.IMREAD_UNCHANGED) # Assume depth_image.png is 16 bits grayscale.
depth = cv2.resize(depth, scale, interpolation=cv2.INTER_NEAREST)
if depth.ndim == 3:
depth = depth[:, :, 0] # Keep one channel if depth has 3 channels? depth = depth[:, :, np.newaxis]
depth = depth.astype(np.float32) / 65535 # Convert to float in range [0, 1]
# Use the depth channel as alpha channel (the channel order is BGRA - applies OpenCV conventions).
bgrd = np.dstack((img, depth))
print("\n\nRGBD shape")
print(bgrd.shape)
# Save the data to exr file (the color format of the exr file is RGBA).
# Error: cv::initOpenEXR imgcodecs: OpenEXR codec is disabled.
#cv2.imwrite('rgbd.exr', bgrd)
# https://stackoverflow.com/questions/45482307/save-float-array-to-image-with-exr-format
rgbd = cv2.cvtColor(bgrd, cv2.COLOR_BGRA2RGBA)
imageio.imwrite('rgbd.exr', rgbd)
################################################################################
# Reading the data:
#bgrd = cv2.imread('rgbd.exr') # Error: cv::initOpenEXR imgcodecs: OpenEXR codec is disabled.
rgbd = imageio.imread('rgbd.exr')
img = bgrd[:, :, 0:3] # First 3 channels are the image.
depth = bgrd[:, :, 3] # Last channel is the depth
img = (img*255).astype(np.uint8) # Convert back to uint8
#depth = (depth*65535).astype(np.uint16) # Convert back to uint16 (if required).
# Show images for testing:
cv2.imshow('img', cv2.cvtColor(img, cv2.COLOR_RGBA2RGB))
cv2.imshow('depth', depth)
cv2.waitKey()
cv2.destroyAllWindows()
注:
64x1216
或1216x64
),并且不确定代码depth = depth[:, :, np.newaxis]
。depth_image.png
的格式有误。将 16 位 RGBA 保存为 PNG 文件:
而不是使用 EXR 文件和
float32
像素格式...uint16
像素格式。
PNG 文件的像素格式将是 RGBA(RGB 和 Alpha - 透明通道)。
每个颜色通道将为 16 位(2 字节)。
Alpha 通道存储深度图(以
uint16
格式)。
将
img
转换为 uint16
(我们可以选择不缩放 256):
img = img.astype(np.uint16)*256
合并
img
(3 个通道)和 depth
(1 个通道)至 4 个通道:
bgrd = np.dstack((img, depth))
将合并后的图像保存为PNG文件:
cv2.imwrite('rgbd.png', bgrd)
代码示例(第二部分读取并显示以供测试):
import numpy as np
import cv2
scale = (64, 1216)
# load image and resize
img = cv2.imread('RGB_image.jpg') # The channels order is BGR due to OpenCV conventions.
img = cv2.resize(img, scale, interpolation=cv2.INTER_LINEAR)
# Convert the image to from 8 bits per color channel to 16 bits per color channel
# Notes:
# 1. We may choose not to scale by 256, the scaling is used only for viewers that expects [0, 65535] range.
# 2. Consider that most image viewers refers the alpha (transparency) channel, so image is going to look strange.
img = img.astype(np.uint16)*256
# load depth and resize
depth = cv2.imread('depth_image.png', cv2.IMREAD_UNCHANGED) # Assume depth_image.png is 16 bits grayscale.
depth = cv2.resize(depth, scale, interpolation=cv2.INTER_NEAREST)
if depth.ndim == 3:
depth = depth[:, :, 0] # Keep one channel if depth has 3 channels? depth = depth[:, :, np.newaxis]
if depth.dtype != np.uint16:
depth = depth.astype(np.uint16) # The depth supposed to be uint16, so code should not reach here.
# Use the depth channel as alpha channel (the channel order is BGRA - applies OpenCV conventions).
bgrd = np.dstack((img, depth))
print("\n\nRGBD shape")
print(bgrd.shape) # (1216, 64, 4)
# Save the data to PNG file (the pixel format of the PNG file is 16 bits RGBA).
cv2.imwrite('rgbd.png', bgrd)
# Testing:
################################################################################
# Reading the data:
bgrd = cv2.imread('rgbd.png', cv2.IMREAD_UNCHANGED)
img = bgrd[:, :, 0:3] # First 3 channels are the image.
depth = bgrd[:, :, 3] # Last channel is the depth
#img = (img // 256).astype(np.uint8) # Convert back to uint8
# Show images for testing:
cv2.imshow('img', img)
cv2.imshow('depth', depth)
cv2.waitKey()
cv2.destroyAllWindows()
我已遵循此操作,但图片变黑并将其加载到全局映射器不会给出任何内容,但波段仍显示 4