在Python中读取PFM格式

4
我想在 Python 中读取 PFM 格式的图像。我尝试使用 imageio.read,但出现了错误。请问有什么建议吗?
img = imageio.imread('image.pfm')

这是一个相当简单的格式 - 描述在这里http://www.pauldebevec.com/Research/HDR/PFM/,Python二进制访问在这里https://www.johnny-lin.com/cdat_tips/tips_fileio/bin_array.html。 - Mark Setchell
谢谢。使用imageio.imread('image.pfm')不就可以了吗? - Rajesh
3个回答

6
下面是Python 3的实现,用于解码.pfm文件。
Paul Devebec's page下载示例memorial.pfm
from pathlib import Path
import numpy as np
import struct


def read_pfm(filename):
    with Path(filename).open('rb') as pfm_file:

        line1, line2, line3 = (pfm_file.readline().decode('latin-1').strip() for _ in range(3))
        assert line1 in ('PF', 'Pf')
        
        channels = 3 if "PF" in line1 else 1
        width, height = (int(s) for s in line2.split())
        scale_endianess = float(line3)
        bigendian = scale_endianess > 0
        scale = abs(scale_endianess)

        buffer = pfm_file.read()
        samples = width * height * channels
        assert len(buffer) == samples * 4
        
        fmt = f'{"<>"[bigendian]}{samples}f'
        decoded = struct.unpack(fmt, buffer)
        shape = (height, width, 3) if channels == 3 else (height, width)
        return np.flipud(np.reshape(decoded, shape)) * scale


import matplotlib.pyplot as plt
image = read_pfm('memorial.pfm')
plt.imshow(image)
plt.show()

1

我对Python完全不熟悉,但是这里有一些关于阅读PFM便携式浮点映射)文件的建议。


选项 1

ImageIO 文档 这里建议您可以下载并使用 FreeImage 阅读器。


选项2

我自己拼凑了一个简单的阅读器,似乎在我找到的一些示例图像上以及用ImageMagick生成的图像上都可以正常工作。它可能包含低效或不良实践,因为我不会说Python。

#!/usr/local/bin/python3
import sys
import re
from struct import *

# Enable/disable debug output
debug = True

with open("image.pfm","rb") as f:
    # Line 1: PF=>RGB (3 channels), Pf=>Greyscale (1 channel)
    type=f.readline().decode('latin-1')
    if "PF" in type:
        channels=3
    elif "Pf" in type:
        channels=1
    else:
        print("ERROR: Not a valid PFM file",file=sys.stderr)
        sys.exit(1)
    if(debug):
        print("DEBUG: channels={0}".format(channels))

    # Line 2: width height
    line=f.readline().decode('latin-1')
    width,height=re.findall('\d+',line)
    width=int(width)
    height=int(height)
    if(debug):
        print("DEBUG: width={0}, height={1}".format(width,height))

    # Line 3: +ve number means big endian, negative means little endian
    line=f.readline().decode('latin-1')
    BigEndian=True
    if "-" in line:
        BigEndian=False
    if(debug):
        print("DEBUG: BigEndian={0}".format(BigEndian))

    # Slurp all binary data
    samples = width*height*channels;
    buffer  = f.read(samples*4)

    # Unpack floats with appropriate endianness
    if BigEndian:
        fmt=">"
    else:
        fmt="<"
    fmt= fmt + str(samples) + "f"
    img = unpack(fmt,buffer)

选项 3

如果您无法在 Python 中读取您的 PFM 文件,您可以使用命令行中的 ImageMagick 将它们转换为另一种格式(例如 TIFF),该格式可以存储浮点样本。 ImageMagick 已安装在大多数 Linux 发行版上,并可用于 macOS 和 Windows:

magick input.pfm output.tif

-2
img = imageio.imread('image.pfm')

就这样做吧。为了方便使用,它可以转换为numpy数组。

img = numpy.asarray(img)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接