Numpy 和 16 位 PGM
使用 numpy 在 Python 中读取 16 位 PGM 图像的有效且清晰的方法是什么?
由于 PIL 错误,我无法使用 PIL 加载 16 位 PGM 图像。我可以使用以下代码读取标题:
dt = np.dtype([('type', 'a2'),
('space_0', 'a1', ),
('x', 'a3', ),
('space_1', 'a1', ),
('y', 'a3', ),
('space_2', 'a1', ),
('maxval', 'a5')])
header = np.fromfile( 'img.pgm', dtype=dt )
print header
这将打印正确的数据: ('P5', ' ', '640', ' ', '480', ' ', '65535')
但我有一种感觉,这并不是最好的方法。除此之外,我很难弄清楚如何以 size(header)
的偏移量按 16 位读取 x x y(在本例中为 640x480)的以下数据。
编辑:添加图像
用于读取和显示图像的 MATLAB 代码为:
I = imread('foo.pgm');
imagesc(I);
看起来像这样:
What is an efficient and clear way to read 16-bit PGM images in Python with numpy?
I cannot use PIL to load 16-bit PGM images due to a PIL bug. I can read in the header with the following code:
dt = np.dtype([('type', 'a2'),
('space_0', 'a1', ),
('x', 'a3', ),
('space_1', 'a1', ),
('y', 'a3', ),
('space_2', 'a1', ),
('maxval', 'a5')])
header = np.fromfile( 'img.pgm', dtype=dt )
print header
This prints the correct data: ('P5', ' ', '640', ' ', '480', ' ', '65535')
But I have a feeling that is not quite the best way. And beyond that, I'm having trouble how to figure out how to read in the following data of x by y (in this case 640x480) by 16-bit with the offset of size(header)
.
EDIT: IMAGE ADDED
MATLAB code to read and display the image is:
I = imread('foo.pgm');
imagesc(I);
And looks like this:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我不太熟悉 PGM 格式,但一般来说,您只需使用 numpy.fromfile 即可。
fromfile
将从您传递给它的文件指针所在的位置开始,因此您可以简单地查找(或读取)到标头的末尾,然后使用fromfile
读取其余部分。您需要使用
infile.readline()
而不是next(infile)
。顺便说一句,您在评论中指向的“foo.pgm”文件似乎在标题中指定了错误的行数。
如果您要读取大量可能存在该问题的文件,则可以用零填充数组或截断它,如下所示。
<罢工>
I'm not terribly familar with the PGM format, but generally speaking you'd just use
numpy.fromfile
.fromfile
will start at whatever position the file pointer you pass to it is at, so you can simply seek (or read) to the end of the header, and then usefromfile
to read the rest in.You'll need to use
infile.readline()
instead ofnext(infile)
.On a side note, the "foo.pgm" file you pointed to in your comment appears to specify the wrong number of rows in the header.
If you're going to be reading in a lot of files that potentially have that problem, you can just pad the array with zeros or truncate it, like this.
事实上,标头后面的“字符串”是文件中的二进制文件。我解决了下面的问题(发现以下内容: ndarray: [2047 2047 2047 ..., 540 539 539]),但还有另一个问题:文件不够长;仅计算 289872 个数字,而不是 640*480...
我为自己的夸张行为感到非常抱歉,为它创建了一个类...
编辑:Joe Kington 的好主意,用零填充图像!
Indeed, the 'string' after the header is a binary in your file. I solved that below (found the following:
ndarray: [2047 2047 2047 ..., 540 539 539]
) but there is another problem: the file is not long enough; counts only 289872 numbers instead of 640*480...I am terribly sorry for my exageration by making a class for it...
edit: great Idea from Joe Kington to fill image with zeros!
从这里我知道标题信息可以用空格、回车符或其他分隔。如果您的数据以空格分隔(如果不是,请告诉我)您可以这样做:
您的数据现在是 int16 格式的数组!
假设您仍然对标题信息感兴趣,您可以这样做:
以便您可以根据读取的行检查图像数据:
编辑:图像数据为二进制,文件必须以“rb”打开并从标头信息之后读取:
from here I understand that the header information can be separated by either spaces, carriage returns or others. If yours is separated by spaces (inform me if otherwise) you can do:
your data is now an array in int16 format!
Suppose you are still interested in the header information, you can do:
so that you can check the image data against the read lines:
Edit: with the image data being binary, the file has to be opened as 'rb' and read from after the header information:
感谢@joe-kington 的回答帮助解决这个问题。解决方案如下。
需要做一些额外的工作才能不对已知的标头长度(17 个字节)进行硬编码
这种情况),而是从标题中确定它。 PGM 标准规定标头通常以换行符结尾,但也可以以任何空格结尾。我认为这段代码会在使用非换行符空格作为标头末尾分隔符的 PGM 上崩溃。在这种情况下,标头大小将由保存宽度、高度和最大大小的变量的大小确定,加上两个字节的“P5”,再加上 4 个字节的空白。
其他可能会中断的情况是宽度或高度大于整数(非常大的图像)。或者,如果 PGM 是 8 位而不是 16 位(可以根据 maxval 以及可能的宽度、高度和文件大小确定)。
Thanks to the answer by @joe-kington for helping figure this out. The solution follows.
There is a little bit of extra work to not hard-code the known header length (17 bytes in
this case), but to determine it from the header. The PGM standard says that the header usually ends with a newline but can end with any whitespace. I think this code will break on a PGM that uses non-newline whitespace for the end-of-header delimeter. Header size in this case would be determined by the size of variables holding width, height, and maxsize, plus two bytes for 'P5', plus 4 bytes of whitespace.
Other cases where this might break are if the width or height are larger than an int (very big image). Or if the PGM is 8-bit rather than 16-bit (which can be determined from maxval, and possible width, height, and the filesize).