首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FFmpeg不能识别每个32位的3个通道

FFmpeg不能识别每个32位的3个通道
EN

Stack Overflow用户
提问于 2022-04-03 10:53:37
回答 1查看 233关注 0票数 2

我正在编写游戏的线性化深度缓冲区,使用openEXR使用FFmpeg。不幸的是,FFmpeg没有完全遵守openEXR文件规范(就像允许一个通道使用无符号整数),所以我正在为openEXR编写一个浮动通道,该通道使用这个命令-f rawvideo -pix_fmt grayf32be -s %WIDTH%x%HEIGHT% -r %FPS% -i - -vf %DEFVF% -preset ultrafast -tune zerolatency -qp 6 -compression zip1 -pix_fmt gbrpf32le %NAME%_depth_%d.exr放入绿色通道。

浮子范围从0F到1F,是线性的。通过在搅拌机上测试16位整数(每像素分量) PNG,可以确定计算和线性化是正确的。16位整数数据与此short s = (short) (linearzieDepth(depth) * (Math.pow(2,16) - 1))类似,而对于浮点数,线性化的值直接写入OpenEXR,而不与值相乘。

但是,当查看openEXR文件时,它不具有与16位png相同的“梯度”.当并排查看它们时,在0附近的值似乎不是线性的,而且它们也不像16位png中应该的那样暗。(是的,我将图像节点设置为线性),并将其与游戏中的3d跟踪数据进行比较,我无法再现深度,也无法像使用png那样使用深度缓冲区来掩盖内容。

线性浮动范围怎么可能与图像中的线性整数范围如此不同?

更新:

现在我用下面的代码向ffmpeg写了3个通道

代码语言:javascript
复制
float f2 = this.linearizeDepth(depth);

buffer.putFloat(f2);
buffer.putFloat(0);
buffer.putFloat(0);

字节缓冲区的大小为width * height * 3 * 4 -> 3通道,每4个字节。命令现在是-f rawvideo -pix_fmt gbrpf32be -s %WIDTH%x%HEIGHT% -r %FPS% -i - -vf %DEFVF% -preset ultrafast -tune zerolatency -qp 6 -compression zip1 -pix_fmt gbrpf32le %NAME%_depth_%d.exr,这意味着输入(字节缓冲区)期望32位浮动有3个通道。

FFmpeg以某种方式分裂了频道或者什么的..。可能是窃听器,可能是我的错?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-03 22:11:46

问题是从grayf32begbrpf32le的颜色转换。

假设源像素范围为0,1我们可以在将像素格式转换为gbrpf32le之前添加格式转换过滤器:gbrpf32le

看起来FFmpeg也忽略了range参数,修复是添加刻度过滤器:scale=in_range=full:out_range=full

更新命令:

代码语言:javascript
复制
ffmpeg -y -f rawvideo -pix_fmt grayf32be -src_range 1 -s 192x108 -i in.raw -vf "scale=in_range=full:out_range=full,format=rgb48le" -vcodec exr -compression zip1 -pix_fmt gbrpf32le -dst_range 1 out.exr

可复制的例子:

  • 创建16位Tiff图像(用作参考):

-y -f lavfi -i testsrc=size=192x108:rate=1:duration=1 -pix_fmt gray16le in.tif

  • 将Tiff转换为浮动(大端):

-y -src_range 1 -i in.tif -pix_fmt grayf32be -dst_range 1 -f rawvideo in.raw

  • 将原始格式转换为OpenEXR格式:

-y -f rawvideo -pix_fmt grayf32be -src_range 1 -s 192x108 -i in.raw -vf "scale=in_range=full:out_range=full,format=rgb48le“-vcodec exr -compression zip1 -pix_fmt gbrpf32le 1 -dst_range

用于比较不同之处的Python代码:

代码语言:javascript
复制
img1 = cv2.imread('in.tif', cv2.IMREAD_UNCHANGED)
img2 = cv2.imread('out.exr', cv2.IMREAD_UNCHANGED)

green_ch = img2[:, :, 1]  # Green channel

max_abs_diff = np.max(np.abs(green_ch*65535 - img1.astype(float)))

最大的差异是3 (在65535级中)。

我们可能得考虑一下过滤器的论点.

由于FFmpeg颜色转换和范围转换存在问题(看起来是这样),在解决问题之前,您将无法获得所需的结果。

更新:

看起来,当输入的像素格式是grayf32be (三色通道平面格式)时,它就可以工作了。

测试:

  • 创建16位Tiff图像(用作参考):

-y -f lavfi -i testsrc=size=192x108:rate=1:duration=1 -pix_fmt gray16le in.tif

  • 将Tiff转换为浮动(大端):

-y -src_range 1 -i in.tif -pix_fmt grayf32be -dst_range 1 -f rawvideo in.raw

  • 三次复制“灰度平面”以获得三个相同的颜色平面(使用"concat协议“以避免任何颜色转换问题):

-y -f rawvideo -pix_fmt grayf32be -s 192x108 -i "concat:in.raw|in.raw|in.raw“-f rawvideo 3.原始

  • 从3个颜色通道原始转换为OpenEXR格式:

-y -f rawvideo -pix_fmt gbrpf32be -s 192x108 -i -y 3.原始-vcodec exr -compression zip1 -pix_fmt gbrpf32le out.exr

用于比较差异的Python代码(比较3个颜色通道):

代码语言:javascript
复制
img1 = cv2.imread('in.tif', cv2.IMREAD_UNCHANGED)
img2 = cv2.imread('out.exr', cv2.IMREAD_UNCHANGED)

blue_ch = img2[:, :, 0]  # Blue channel
green_ch = img2[:, :, 1]  # Green channel
red_ch = img2[:, :, 2]  # Red channel

max_red_abs_diff = np.max(np.abs(red_ch*65535 - img1.astype(float)))
max_green_abs_diff = np.max(np.abs(green_ch*65535 - img1.astype(float)))
max_blue_abs_diff = np.max(np.abs(blue_ch*65535 - img1.astype(float)))

最大差异是0.001953125 (可忽略不计)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71725213

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档