我有一些 16 位灰度且未签名的科学数据。我需要广泛的灰度值,并且 C# 已经支持使用
PixelFormat.Format16bppGrayScale
的位图结构格式,我正在对数据进行一些操作并将其保存到 List
中,我想将其写入视频文件中正在观看。
我在那里寻找了许多 FFMPEG 库,我看到
Accord.Video.FFMPEG
确实支持 32 位 ARGB,当我将位图转换为 ARGB 时,它可以工作,我可以像这样编写视频文件:
int height = images[0].Height;
int width = images[0].Width;
var frameRate = 8;
// create instance of video writer
var vFWriter = new VideoFileWriter();
// create new video file
vFWriter.Open(outputVid + ".mp4", width, height, frameRate, VideoCodec.MPEG4);
for(int i=0; i<images.Count; i++)
{
vFWriter.WriteVideoFrame(images[i]); // MAIN LINE OF FOCUS
}
vFWriter.Close();
vFWriter.Dispose();
从代码中可以看出,没有向
VideoFileWriter
提供 Stride 或 PixelFormat,并且根据 文档,类中没有此类属性。
我在 C++ 和 OpenCV2 中看到了类似的问题,其中唯一支持 16 位灰度的编解码器是 FFV1。我知道机会渺茫,但我尝试了:
vFWriter.Open(outputVid + ".mkv", width, height, frameRate, VideoCodec.FFV1);
然而,正如所料,没有任何结果。
问题是抛出一个异常,表明图像被写入
VideoFileWriter
,参数无效:
未处理的异常:System.ArgumentException:参数无效。
在System.Drawing.Bitmap.LockBits(矩形矩形,ImageLockMode标志,PixelFormat格式,BitmapData位图数据)
在System.Drawing.Bitmap.LockBits(矩形矩形,ImageLockMode标志,PixelFormat格式)
在 Accord.Video.FFMPEG.VideoFileWriter.WriteVideoFrame(位图帧,UInt32 帧索引)
这是
PixelFormat
不匹配时的常见错误(视频编写器想要 32 位 ARGB,但它正在接收 16 位灰度)。
我通过将写入代码更新为以下内容来确认情况是这样的:
for(int i=0; i<images.Count; i++)
{
var data = images[i].LockBits(new Rectangle(System.Drawing.Point.Empty, images[i].Size), ImageLockMode.ReadOnly, PixelFormat.Format16bppGrayScale);
vFWriter.WriteVideoFrame(data);
images[i].UnlockBits(data);
}
现在抛出的异常是:
未处理的异常:System.ArgumentException:提供的位图必须是 24 或 32 bpp 彩色图像或 8 bpp 灰度图像。
我无法转换为 32 位 ARGB,因为它只允许 256 级灰度,而我需要整个 16 位范围。
Xabe.FFMPEG
,但它不支持从图像构建视频。
除了
Accord.Video.FFMPEG
之外,是否还有其他库能够从 16 位灰度帧构建视频?
据我所知,还没有好的视频编解码器支持 16 位灰度,我已经看过了。
一个问题是,您通常需要进行某种“窗口调平”来选择要显示的数据部分,而不是仅仅丢弃低 8 位。因此,即使您可以对数据进行编码和解码,您也很难使播放看起来不错。到目前为止,我还没有看到任何公共图像查看器可以很好地处理 16 位灰度数据,更不用说任何视频查看器了。
一些可能的选择:
我们使用 zip 存档作为容器,带有单独的 jpegls 编码帧(png 或 jpeg2000)也可以使用。压缩率不是很高,您需要自定义工具来录制和播放。但它将提供对数据和播放的最佳控制。
虽然完整的 16 位视频似乎几乎不可能,但 h265 和其他一些视频支持 12 位视频。如果这对您来说足够了,它应该提供迄今为止最好的压缩比,并且应该与大多数播放器兼容。一个潜在的问题是我还没有找到任何允许商业使用的免费编码库。
您可以将 16 位灰度值拆分为两个 8 位值,并将它们存储在 RGB 视频中的不同颜色通道中。这将需要无损视频编解码器,但这应该可以通过 h265 或其他最先进的编解码器实现。它应该提供更好的压缩,但在常规视频播放器中观看时看起来很糟糕。
生成常规的 8 位灰度视频文件供人们查看,同时保留另一个包含完整数据的文件以供其他程序使用。