Python是否具有标准的PTS阅读器或解析器?

问题描述 投票:2回答:1

我有以下文件:

version: 1
n_points:  68
{
55.866278 286.258077
54.784191 315.123248
62.148364 348.908294
83.264019 377.625584
102.690421 403.808995
125.495327 438.438668
140.698598 471.379089
158.435748 501.785631
184.471278 511.002579
225.857960 504.171628
264.555990 477.159805
298.168768 447.523374
332.502678 411.220089
350.641672 372.839985
355.004106 324.781552
349.265206 270.707703
338.314674 224.205227
33.431075 238.262266
42.204378 227.503948
53.939564 227.904931
68.298209 232.202002
82.271511 239.951519
129.480996 229.905585
157.960824 211.545631
189.465597 204.068108
220.288164 208.206246
249.905282 218.863196
110.089281 266.422557
108.368067 298.896910
105.018473 331.956957
102.889410 363.542719
101.713553 379.256535
114.636047 383.331785
129.543556 384.250352
140.033133 375.640569
152.523364 366.956846
60.326871 270.980865
67.198221 257.376350
92.335775 259.211865
102.394658 274.137548
86.227917 277.162353
68.397650 277.343621
165.340638 263.379230
173.385917 246.412765
198.024842 240.895985
223.488685 247.333206
207.218336 260.967007
184.619159 265.379884
122.903148 418.405102
114.539655 407.643816
123.642553 404.120397
136.821841 407.806210
149.926926 403.069590
196.680098 399.302500
221.946232 394.444167
203.262878 417.808844
164.318232 440.472370
145.915650 444.015386
136.436942 442.897031
125.273506 429.073840
124.666341 420.331816
130.710965 421.709666
141.438004 423.161457
155.870784 418.844649
213.410389 396.978046
155.870784 418.844649
141.438004 423.161457
130.710965 421.709666
}

文件扩展名是.pts

此文件是否有标准阅读器?

我尝试读取的代码(从某些github下载)是

landmark = np.loadtxt(image_landmarks_path)

失败的原因

{{ValueError}无法将字符串转换为float:'version:'

这很有意义。

我无法更改文件,想知道我是否必须编写自己的解析器,或者这是某些标准吗?

python file point-clouds
1个回答
1
投票

[它似乎是一个2D点云文件,我认为它是Landmark PTS格式,我可以找到的最接近的Python参考是3D-morphable face model-fitting library issue,它引用了sample file that matches yours。大多数.pts点云工具希望可以使用3D文件,因此可能无法立即使用该文件。

所以不,似乎没有为此的标准阅读器;我最接近读取格式的库是this GitHub repository,但是它有一个缺点:它将所有数据读入内存,然后将其手动解析为Python浮点值。

但是,格式是非常简单(如所提及的问题注释),因此您可以仅使用numpy.loadtxt()来读取数据;简单的方法是仅将所有这些非数据行命名为注释:

def read_pts(filename):
    return np.loadtxt(filename, comments=("version:", "n_points:", "{", "}"))

或者,如果不确定一堆这样的文件的有效性,并且希望确保只读取有效的文件,则可以对文件进行预处理以读取标题(包括点数和版本)验证,允许comments and image size info):

from pathlib import Path
from typing import Union
import numpy as np

def read_pts(filename: Union[str, bytes, Path]) -> np.ndarray:
    """Read a .PTS landmarks file into a numpy array"""
    with open(filename, 'rb') as f:
        # process the PTS header for n_rows and version information
        rows = version = None
        for line in f:
            if line.startswith(b"//"):  # comment line, skip
                continue
            header, _, value = line.strip().partition(b':')
            if not value:
                if header != b'{':
                    raise ValueError("Not a valid pts file")
                if version != 1:
                    raise ValueError(f"Not a supported PTS version: {version}")
                break
            try:
                if header == b"n_points":
                    rows = int(value)
                elif header == b"version":
                    version = float(value)  # version: 1 or version: 1.0
                elif header not in {b"image_size_x", b"image_size_y"}:
                    # returning the image_size_* data is left as an excercise
                    # for the reader.
                    raise ValueError
            except ValueError:
                raise ValueError("Not a valid pts file")

        # if there was no n_points line, make sure the closing } line
        # is not going to trip up the numpy reader by marking it as a comment
        points = np.loadtxt(f, max_rows=rows, comments="}")

    if rows is not None and len(points) < rows:
        raise ValueError(f"Failed to load all {rows} points")
    return points

除了提供完整的测试套件之外,该功能已尽可能实现生产就绪。

这使用n_points:行告诉np.loadtxt()要读取多少行,并将文件位置向前移动到{打开器之后。如果不存在ValueError行或标头中除了version: 1version: 1以外的任何内容,它也会以n_points: <int>退出。

两者都产生一个float64值的68x2矩阵,但应该能够处理任何点的尺寸。

回到那个EOS库参考,他们的demo code to read the data手动解析行,也首先将所有行读入内存。我也发现了this Facebook Research PTS dataset loading code(对于每行3个值的.pts文件),就像手动一样。

© www.soinside.com 2019 - 2024. All rights reserved.