【问题标题】:Reading data from a 16-bit unsigned big endian raw image file in python从python中的16位无符号大端原始图像文件中读取数据
【发布时间】:2014-10-25 08:56:16
【问题描述】:

我有一些图像想要使用 python 脚本进行分析。 它们存储为原始二进制数据文件。它们采用以下格式。 16 位无符号、大端、592x600 像素,带有 520 字节标题。

当我在我的操作系统 (OS X yosemite) 中查看 .dat 文件时,我发现该文件是 710,920 字节

这是有道理的,因为(592 x 600 像素)*(每像素 2 字节)= 710,400 字节。因此剩下的就是 520 字节的头部。

我想编写一个快速的 Python 脚本来生成像素值数组。即我想放弃文件的标题并将其余数据存储为数组,以便我可以使用 PIL 之类的东西快速转换为图像并输出 jpg 或 png。

只是做一些非常快的事情:

myfile = open('test.dat', 'rb') 

data = myfile.read()

len(data)

trimdata = data[520:]

len(trimdata)

这给了我没有标题的原始数据。

从这里我不确定将数据解析为 592x600 数组的最简单方法,然后我可以将其与 PIL 一起使用以导出快速灰度图像。

这里是文件的链接,可以帮助您: test.dat

编辑:感谢所有帮助 - 看来数据毕竟是 Little Endian 而不是 Big Endian。干杯。

【问题讨论】:

  • 您只是对如何转换图像或如何在 Python 中进行转换感兴趣?
  • 我对学习如何在 python 中做这件事特别感兴趣。我一直在用 python 进行大量图像分析和计算,数据相似,但这是我第一次收集原始格式的数据集。能够使用 imagemagick 快速处理它们以吐出 png 或 jpg 非常棒,但最后我希望能够将数据作为像素值数组输入 python,这样我就可以对数据进行一些计算.感谢您提供有关使用 struct 的提示 - 我今晚会研究一下!
  • 测试数据的原始链接已损坏。该数据的样例将有助于增加此问题的价值。

标签: python image image-processing python-imaging-library


【解决方案1】:

您可以在命令行中使用 ImageMagick 的 convert 将它们转换为快速 JPEG,而无需编写任何 Python。

只需告诉 ImageMagick 大小和位深度以及数据偏移量,它就可以为您制作灰度 JPEG 或 16 位 TIFF。

类似的东西,但我没有我的 Mac 可以测试:

convert -size 592x600+520 -depth 16 GRAY:image.dat output.jpg

您可能还需要在第一个文件名之前使用-endian MSB(或 LSB)。

我现在回到我的 Mac,生成此图像的命令是:

convert -size 592x600+520 -depth 16 -endian MSB GRAY:image.dat -auto-level output.jpg

【讨论】:

  • 我在使用 ImageJ 时遇到了同样的问题,因为 imagemagick 似乎在数据中似乎有一些奇怪的斑点(上图的右上角)我实际上能够得到原件将原始数据与 png 一起输出的软件,因此我知道数据没有损坏,因为现在我有一组看起来正确的 png。但是今天之后我不再可以访问原始软件,所以我想找到一种方法让原始数据与另一个软件包一起正确显示
  • 这看起来像是图像中最亮的地方——也许它是被视为符号位的 MSB...
  • @MaxwellGrady 我的技术显示了相同的图像。我可能会尝试几个实验。
【解决方案2】:

PIL 应该能够直接读取该数据,但如果我能弄清楚如何做到这一点,那就见鬼了。不过间接做也不需要太多步骤。

fmt = '>' + str(592*600) + 'H'
pix = struct.unpack(fmt, trimdata)
scaled_pix = ''.join(chr(p/256) for p in pix)
im = Image.fromstring('L', (592,600), scaled_pix, 'raw')

编辑:看起来您的示例图片是小端,而不是大端。这是一些更正的代码。我还加入了自动亮度缩放和伽马校正,因为没有使用完整的 16 位比例。

fmt = '<' + str(592*600) + 'H'
pix = struct.unpack(fmt, trimdata)
lightest = max(pix)
scaled = ''.join(chr(int((float(p) / lightest)**(1/2.2) * 255)) for p in pix)
im = Image.fromstring('L', (592,600), scaled, 'raw')

【讨论】:

  • 感谢您的提示!今晚我会在分析数据时研究这个问题。看起来很简单
  • 谢谢!我刚刚假设数据是基于生成它的机器的大端序,以及 imageJ 在告诉尝试导入为原始大端序时似乎使图像几乎正确的事实......我应该检查这两个选项。感谢大家的帮助!
猜你喜欢
  • 1970-01-01
  • 2012-06-11
  • 2012-06-12
  • 2015-12-13
  • 1970-01-01
  • 2017-07-02
  • 1970-01-01
  • 2017-09-10
  • 2014-09-09
相关资源
最近更新 更多