【问题标题】:How do I merge a EXR image with jpg images in opencv-python?如何在 opencv-python 中将 EXR 图像与 jpg 图像合并?
【发布时间】:2020-12-22 23:13:44
【问题描述】:

你好,我正在为一个游戏做纹理打包,想合并法线贴图的 R、G 通道、遮挡贴图(AO 和腔贴图的乘积,但由于我不知道如何乘积OpenCV 中的图像正确我只是使用腔贴图)和 EXR 中的置换贴图。法线和遮挡贴图是 JPEG,而位移是 EXR,所以我想合并它们,同时保持我认为的位深度。此外,我想以受支持的格式导出它,该格式既能保留位深度,又能与 UE4、Unity 等引擎兼容。这是我目前所得到的:

normal = cv2.imread('{subdir}/{code}_4K_Normal.jpg'.format(subdir=subdir, code=code), cv2.IMREAD_UNCHANGED)
ao = cv2.imread('{subdir}/{code}_4K_AO.jpg'.format(subdir=subdir, code=code), cv2.IMREAD_UNCHANGED)
cavity = cv2.imread('{subdir}/{code}_4K_Cavity.jpg'.format(subdir=subdir, code=code), cv2.IMREAD_UNCHANGED)
height = cv2.imread('{subdir}/{code}_4K_Displacement.exr'.format(subdir=subdir, code=code), cv2.IMREAD_ANYCOLOR | cv2.IMREAD_ANYDEPTH)

normal_b, normal_g, normal_r = cv2.split(normal)
ao_b, ao_g, ao_r = cv2.split(ao)
cavity_b, cavity_g, cavity_r = cv2.split(cavity)
height_b, height_g, height_r = cv2.split(height)

noh = cv2.merge((cavity_r, normal_g, normal_r, height_r))

cv2.imwrite('{subdir}/{code}_4K_NOH_2.tga'.format(subdir=subdir, code=code), noh)

但是执行上述操作会给我这个错误:

noh = cv2.merge((cavity_r, normal_g, normal_r, height_r))
cv2.error: OpenCV(4.4.0) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-h4wtvo23\opencv\modules\core\src\merge.dispatch.cpp:129: error: (-215:Assertion failed) mv[i].size == mv[0].size && mv[i].depth() == depth in function 'cv::merge'

以下是我要问的问题:

  1. 如何合并不同位深度的通道,但仍保持高位深度。
  2. 将图像导出为适合游戏引擎的良好格式。

【问题讨论】:

  • 您将无法使用 TGA 文件保留高位深度,是吗?你希望写什么RGB888 +D32?
  • @MarkSetchell 我当时导出到另一种文件格式没有问题,认为 TGA 足够高。谢谢(你的)信息。将编辑帖子
  • @MarkSetchell 你问的第二个问题是什么意思?对文件格式了解不够。
  • 输出文件中需要哪些组件(红色、绿色、蓝色、深度、其他?)以及每个组件应该具有什么位深度?您打算将输出文件用于/与什么一起使用?
  • @MarkSetchell 输出有4个通道,法线的r和g,遮挡的r为b,位移的r为a。如果只有 alpha 通道(位移)处于高位深度,我会更喜欢,尽管我再次知道如何做到这一点。

标签: python opencv image-processing opencv-python


【解决方案1】:

我对 Unity 或 UE4 一无所知,所以如果有人更了解,请说,我会很乐意删除这些猜测/提示。

您尚未指定 “高位深度” 的含义 - 每个样本可能是 15、16、31、32 或 64 位。请澄清。

您似乎想要一个 4 通道 RGBA 输出文件。

所以,鉴于上述情况,我只能建议:

  • 如果每个样本 16 位或更少,则可能会写入 PNG,或者
  • 否则为 TIFF。

在合并之前,您需要确保所有通道的位深度相同。您可能还需要将它们缩放到足够亮,以便在其新的高位深度范围内可见。因此,如果您有一个来自 JPEG 的 8 位通道,并且您希望将其设为 16 位以与其他一些 16 位通道合并,请尝试:

HiDepthChannel = LoDepthChannel.astype(np.uint16)*256

【讨论】:

  • 好的,所以对于我的 jpeg 频道,我执行上面的代码 sn-p,但是对于我的 exr 频道呢?我就让它保持原样吗?
  • 我不知道。你还没有告诉我们你的深度数据的位深度。你需要做print(height.dtype)
  • 好的,我明白了,jpeg 有 uint8,而 exr 有 float32。
  • 那么channel.astype(np.float32)*x,x 还是 256 吗?或者我不需要乘任何东西?
  • 嗯,uint8 的范围是 0..255。 float32 的范围是 +/- 3.4 x10^38。因此,您要么必须将两者都缩放为uint16 并另存为 PNG,要么将两者都缩放为 float32 并另存为 TIFF。再说一次,你还没有说你想走哪条路。
猜你喜欢
  • 2015-09-13
  • 2011-01-08
  • 2019-03-01
  • 2022-07-01
  • 2017-08-12
  • 1970-01-01
  • 1970-01-01
  • 2011-12-13
  • 2023-04-04
相关资源
最近更新 更多