Python 和 16 位 PGM
我有 16 位 PGM 图像,我正在尝试用 Python 读取它们。好像(?)PIL不支持这种格式?
import Image
im = Image.open('test.pgm')
im.show()
大致显示图像,但不正确。整个过程中都有暗带,据报道 img 具有 mode=L
。我认为这与我早期关于 16 位 TIFF 文件 的问题有关。难道 16 位如此罕见以至于 PIL 不支持它吗?关于如何使用 PIL 或其他标准库或自制代码在 Python 中读取 16 位 PGM 文件,有什么建议吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您需要
"L;16"
模式;然而,在加载 PGM 时,PIL 似乎有一种"L"
模式硬编码到 File.c 中。如果你想能够,你必须编写自己的解码器读取 16 位 PGM。然而,16 位图像支持似乎仍然不稳定:
我认为 PIL 能够读取 16 位图像,但实际上存储和操作它们仍然处于实验阶段。
看,它只是将
0xCAFE
值解释为0xFE
,这并不完全正确。You need a mode of
"L;16"
; however it looks like PIL has a mode of"L"
hardcoded into File.c when loading a PGM. You’d have to write your own decoder if you want to be able to read a 16-bit PGM.However, 16-bit image support still seems flaky:
I think PIL is capable of reading images with 16 bits, but actually storing and manipulating them is still experimental.
See, it just interpreted the
0xCAFE
value as0xFE
, which isn’t exactly correct.以下仅依赖numpy来加载图像,可以是8位或16位位原始 PGM/PPM。我还展示了几种不同的查看图像的方式。使用PIL(
导入图像
)的要求首先将数据转换为8位。使用说明
我最终弄清楚了“它如何决定字节序”——它实际上是将图像作为大字节序(而不是本机)存储在内存中。这种方案可能会减慢任何重要的图像处理速度——尽管 Python 的其他性能问题可能会将此问题归为琐事(见下文)。
我在此处提出了一个与字节顺序相关的问题。我还遇到了一些与字节序相关的有趣的困惑,因为我正在通过使用 pnmdepth 65535 预处理图像来进行测试,这对于测试字节序来说(本身)并不好,因为低字节和高字节可能最终会出现是相同的(我没有立即注意到,因为
print(array)
输出十进制)。我还应该应用pnmgamma
来避免一些混乱。由于 Python 速度太慢,
numpy
试图偷偷摸摸聪明地了解如何应用某些操作(请参阅 广播)。使用 numpy 提高效率的第一条经验法则是让 numpy 为您处理迭代(或者换句话说,不要编写自己的for
循环)。上面代码中有趣的是,在执行“示例图像处理”时,它仅部分遵循此规则,因此该行的性能极大地依赖于为reshape
提供的参数.下一个大
numpy
字节序之谜:为什么newbyteorder()
似乎返回一个数组,当记录返回dtype.如果您想使用
dst.pixels=dst.pixels.byteswap(True).newbyteorder()
转换为本机字节序,这是相关的。移植到 Python 3 的提示:带有 ASCII 文本标头的二进制输入,从标准输入读取
The following depends only on numpy to load the image, which can be 8-bit or 16-bit raw PGM/PPM. I also show a couple different ways to view the image. The one that uses PIL (
import Image
) requires that the data first be converted to 8-bit.Usage notes
I eventually figured out "how it decides about endianness" -- it is actually storing the image in memory as big-endian (rather than native). This scheme might slow down any non-trivial image processing -- although other performance issues with Python may relegate this concern to a triviality (see below).
I asked a question related to the endianness concern here. I also ran into some interesting confusion related to endianness with this because I was testing by preprocessing the image with
pnmdepth 65535
which is not good (by itself) for testing endianness since the low and high bytes might end up being the same (I didn't notice right away becauseprint(array)
outputs decimal). I should have also appliedpnmgamma
to save myself some confusion.Because Python is so slow,
numpy
tries to besneakyclever about how it applies certain operations (see broadcasting). The first rule of thumb for efficiency withnumpy
is let numpy handle iteration for you (or put another way don't write your ownfor
loops). The funny thing in the code above is that it only partially follows this rule when doing the "example image processing", and therefore the performance of that line has an extreme dependency on the parameters that were given toreshape
.The next big
numpy
endianness mystery: Why doesnewbyteorder()
seem to return an array, when it's documented to return adtype
. This is relevant if you want to convert to native endian withdst.pixels=dst.pixels.byteswap(True).newbyteorder()
.Hints on porting to Python 3: binary input with an ASCII text header, read from stdin
这是一个通用的 PNM/PAM 基于NumPy 和 PyPNG< 中未记录的函数/a>.
当然编写这种图像格式通常不需要库的帮助......
Here's a generic PNM/PAM reader based on NumPy and an undocumented function in PyPNG.
Of course writing this image format generally doesn't require the assistance of a library...