N-Cloth 复现——环境相关

N-Cloth 复现——环境相关

原论文名字是 《N-Cloth: Predicting 3D Cloth Deformation with Mesh-Based Networks》 ,这里记录一下论文复现遇到的一些问题、难点。本篇主要关于环境配置

配置环境

N-Cloth 依赖的库主要如下:

  1. python 3.8
  2. pytorch 1.7.0
  3. torch-geometric 1.6.3
  4. psbody-mesh 0.4

其中 pytorch、torch-geometric 请务必保证版本一致,否则可能需要改写部分代码,或者无法加载作者给出的训练好的神经网络模型(因为新版本的 torch-geometric 中部分图神经网络的结构被更改过,所以无法正常加载作者提供的模型数据)。

如果是 Windows 平台下,那么 psbody-mesh 官方版本是无法正常安装的(至少需要较大的改动,成本较大),可以用别人已经改好的 0.3 版本进行安装。目前经过测试运行没有遇到大问题,0.3 的 psbody-mesh 是可以正常使用的。原作者运行的环境是 Ubuntu,所以如果是在 Win 上运行代码的话需要踩一系列坑。

psbody-mesh 库在 Win 系统上的安装

因为 psbody-mesh 库在 Windows 上安装比较麻烦,所以这里单独记录一下。

Boost 安装与配置

首先进行 Boost 的安装,从官网下载源代码:

20220915124652

解压到要安装的路径之后例如C:\dev\boost_1_80_0,然后运行bootstrap.bat,运行后在命令行用 b2.exe 编译 boost。

.\b2.exe --address-model=64

编译完成后添加环境变量即可:

20220915143324

Mesh 库的编译与安装

首先 git clone 别人魔改过的版本到硬盘上,然后在该目录运行指令:

pip install --no-deps --install-option="--boost-location=<path_to_your_boost>" --verbose --no-cache-dir .

其中<path_to_your_boost>替换成你安装的 Boost 路径。

之后,先将 setup.py 第 203 行左右有“visibility”的行注释掉,再运行指令:

python setup.py sdist

以及

python setup.py --verbose build_ext --boost-location=<path_to_your_boost>

这一步可能会提示 fatal error C1083: Cannot open include file: 'CGAL/AABB_tree.h',具体解决方法看下面的 一些坑 一节,解决了之后重新运行这一行指令即可。

最后

python setup.py install

安装成功后,运行 pip list,如果看到列出的包中包含 psbody-mesh,那么安装就成功了:

20220915152807

安装特殊 PyOpenGL

随后我们需要安装魔改过的 PyOpenGL,选择对应你的 Python 版本的 wheel 安装即可。据作者解释是因为 Win 下用 MeshViewer 的话需要调用特殊的 DLL,而这些 DLL 在默认通过 PYPI 安装的 PyOpenGL 中是没有的。

注意如果安装过旧版本的 PyOpenGL 的话需要进行一次卸载:

pip uninstall pyOpenGL
pip install <the-name-of-your-wheel-file>

安装完成后,如果你需要进行测试来确保安装成功了的话:

python -m unittest -v

如果安装成功,那么最终可以看到这个窗口:

20220915144311

一些坑

理论上是应该像上面的指示那样顺利的,但是偶尔我们会遇到一些错误,这里整理了一些常见的错误以及解决方法。

fatal error C1083: Cannot open include file: 'CGAL/AABB_tree.h'

即在 python setup.py sdist 的时候提示找不到 CGAL/AABB_tree.h 文件。

直接将 mesh-master\build\temp.win-amd64-3.X\CGAL-4.7 复制到 mesh-master\build\temp.win-amd64-3.X\Release\CGAL-4.7 即可解决。如果还不行的话那么可以把 mesh-master\mesh\thirdparty 下的 CGAL-4.7.tar.gz 解压,并重命名为 CGAL 文件夹,放到 mesh-master\mesh\src 目录下。

ShengbinWei 描述,还需要修改 CGAL/Origin.h 内容:

// 注释的就是原代码,改成没注释的样子
//CGAL_EXPORT extern const Origin ORIGIN;
CGAL_EXPORT const Origin ORIGIN;
//CGAL_EXPORT extern const Null_vector NULL_VECTOR;
CGAL_EXPORT const Null_vector NULL_VECTOR;

但是我自己实验实际上没改也是可以的。

(可选)CMake 编译库

如果你要用到 MeshViewer 的话可能需要这一步,编译 mesh 生成 MeshViewer 运行所需的 .lib。

cd mesh-master/mesh/cmake/
cmake ..

然后会看到生成了一个 .sln VS 工程文件以及一堆其他的文件,直接 Release 版本编译方案生成库即可。最后将生成库:

20220915152052

把这些库放到对应的目录下即可:

spatialsearch -> mesh-master/geometry
plyutils -> mesh-master/mesh/serialization
spatialsearch -> mesh-master/mesh
loadobj -> mesh-master/mesh/serialization

Win 环境下改写部分源代码

首先是 os.path.join() 相关部分,因为原作者用到了类似"{:0>4}_00.obj"的变量来指代最终用到的、要输出的文件名,而且直接传入给os.path.join()。类似于:

cloth_file = "{:0>4}_00.obj"
cloth_file_path = osp.join(dataset_path, "train_test", "mesh", cloth_file)

# 在用到的地方才进行 format
cloth = Obj(filename=cloth_file_path.format(233))

这么做在 Linux 系列系统下是没有问题的,但是在 Win下因为禁止使用{}:>之类的特殊字符作为变量名,所以原作者的代码无法直接在 Win 下运行,必须先进行 format 变成正常的命名之后再进行 os.path.join()

cloth_file = "{:0>4}_00.obj"
# 传入参数前先进行 format
cloth_file_path = osp.join(dataset_path, "train_test", "mesh", cloth_file.format(233))

cloth = Obj(filename=cloth_file_path)

这样才能得到正确的路径。

此外,运行原作者代码的时候可能会遇到这种错误:

AttributeError: Can't pickle local object 'DataLoader.__init__.<locals>.collate'

这是因为原作者的 DataLoader 中用到了匿名函数,这是个 PyTorch 的 bug,把匿名函数改成单独的函数即可:

原本:

class DataLoader(torch.utils.data.DataLoader):

    def __init__(self,
                 dataset,
                 batch_size=1,
                 shuffle=False,
                 follow_batch=None,
                 **kwargs):
        if follow_batch is None:
            follow_batch = []

        def collate(batch):
            elem = batch[0]
            if isinstance(elem, list):
                return batch
            elif isinstance(elem, torch.Tensor):
                return default_collate(batch)
            elif isinstance(elem, float):
                return torch.tensor(batch, dtype=torch.float)
            elif isinstance(elem, int_classes):
                return torch.tensor(batch)
            elif isinstance(elem, string_classes):
                return batch

            raise TypeError('DataLoader found invalid type: {}'.format(
                type(elem)))

        super(DataLoader, self).__init__(dataset,
                                         batch_size,
                                         shuffle,
                                         collate_fn=lambda batch: collate(batch),
                                         **kwargs)

改成:

class DataLoader(torch.utils.data.DataLoader):

    def __init__(self,
                 dataset,
                 batch_size=1,
                 shuffle=False,
                 follow_batch=None,
                 **kwargs):
        if follow_batch is None:
            follow_batch = []

        super(DataLoader, self).__init__(dataset,
                                         batch_size,
                                         shuffle,
                                         collate_fn=collate,
                                         **kwargs)

def collate(batch):
    elem = batch[0]
    if isinstance(elem, list):
        return batch
    elif isinstance(elem, torch.Tensor):
        return default_collate(batch)
    elif isinstance(elem, float):
        return torch.tensor(batch, dtype=torch.float)
    elif isinstance(elem, int_classes):
        return torch.tensor(batch)
    elif isinstance(elem, string_classes):
        return batch

    raise TypeError('DataLoader found invalid type: {}'.format(
        type(elem)))

当然也可以让 num_workers 变成 0,单线程加载数据,但是那样就会让整个网络读取数据的速度变慢,最终拖累整体的运行速度。

参考

installation of Windows 10?
Mesh and Meshviewer cannot be used
AttributeError: Can't pickle local object 'main.<locals>.<lambda>'

posted @ 2024-04-29 15:40  夜溅樱  阅读(15)  评论(0编辑  收藏  举报