Last active
May 24, 2023 00:00
-
-
Save sergeyprokudin/a27ad1d43922eafa5f1926359ced222e to your computer and use it in GitHub Desktop.
llff_poses_to_pytorch3d_camera.ipynb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"nbformat": 4, | |
"nbformat_minor": 0, | |
"metadata": { | |
"colab": { | |
"name": "llff_poses_to_pytorch3d_camera.ipynb", | |
"provenance": [], | |
"collapsed_sections": [], | |
"authorship_tag": "ABX9TyMyjz0uGdMV9GYZ/oRD7OmW", | |
"include_colab_link": true | |
}, | |
"kernelspec": { | |
"name": "python3", | |
"display_name": "Python 3" | |
}, | |
"language_info": { | |
"name": "python" | |
}, | |
"accelerator": "GPU", | |
"gpuClass": "standard" | |
}, | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "view-in-github", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"<a href=\"https://colab.research.google.com/gist/sergeyprokudin/a27ad1d43922eafa5f1926359ced222e/llff_poses_to_pytorch3d_camera.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# This is a small code snippet investigating the way to convert LLFF dataset \n", | |
"# format (pose_bounds.npy) to Pytorch3d camera data \n", | |
"#\n", | |
"# Sergey Prokudin (sergey.prokudin@gmail.com)\n", | |
"# Zürich, August, 2022\n", | |
"\n", | |
"\n", | |
"# Some useful links utilised during the investigation:\n", | |
"\n", | |
"# LLFF conversion:\n", | |
"# https://github.com/Fyusion/LLFF/blob/master/llff/poses/pose_utils.py\n", | |
"\n", | |
"# \"OpenCV camera to PyTorch3D PerspectiveCameras\"\n", | |
"# https://github.com/facebookresearch/pytorch3d/issues/522\n", | |
"\n", | |
"# \"How to convert LLFF camera poses to Pytorch3D cameras? \"\n", | |
"# https://github.com/facebookresearch/pytorch3d/issues/1125\n", | |
"\n", | |
"# \"Great work! How to convert original camera pose from NeRF to Pytorch3d style?\"\n", | |
"# https://github.com/facebookresearch/pytorch3d/issues/883\n", | |
"\n", | |
"# NeRF Fern LLFF data:\n", | |
"# https://drive.google.com/drive/folders/1McCFABesPQxXDimpudJHd7xw-0IlWSba?usp=sharing\n", | |
"\n", | |
"# NeRF Fern data pytorch3d format:\n", | |
"# https://dl.fbaipublicfiles.com/pytorch3d_nerf_data/fern.pth\n", | |
"\n", | |
"# LLFF pose format description\n", | |
"# https://github.com/Fyusion/LLFF" | |
], | |
"metadata": { | |
"id": "Aj8Zt9ubqsye" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# install pytorch3d\n", | |
"\n", | |
"import os\n", | |
"import sys\n", | |
"import torch\n", | |
"need_pytorch3d=False\n", | |
"try:\n", | |
" import pytorch3d\n", | |
"except ModuleNotFoundError:\n", | |
" need_pytorch3d=True\n", | |
"if need_pytorch3d:\n", | |
" if torch.__version__.startswith(\"1.10.\") and sys.platform.startswith(\"linux\"):\n", | |
" # We try to install PyTorch3D via a released wheel.\n", | |
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n", | |
" version_str=\"\".join([\n", | |
" f\"py3{sys.version_info.minor}_cu\",\n", | |
" torch.version.cuda.replace(\".\",\"\"),\n", | |
" f\"_pyt{pyt_version_str}\"\n", | |
" ])\n", | |
" !pip install fvcore iopath\n", | |
" !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html\n", | |
" else:\n", | |
" # We try to install PyTorch3D from source.\n", | |
" !curl -LO https://github.com/NVIDIA/cub/archive/1.10.0.tar.gz\n", | |
" !tar xzf 1.10.0.tar.gz\n", | |
" os.environ[\"CUB_HOME\"] = os.getcwd() + \"/cub-1.10.0\"\n", | |
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'\n", | |
"\n", | |
"# also clone the pytorch3d repo for some auxiliary functions\n", | |
"!git clone https://github.com/facebookresearch/pytorch3d/" | |
], | |
"metadata": { | |
"id": "1WpOczawV62g" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"import torch\n", | |
"import sys\n", | |
"import numpy as np\n", | |
"from pytorch3d.renderer import PerspectiveCameras\n", | |
"\n", | |
"sys.path.insert(0, '/content/pytorch3d/pytorch3d')\n", | |
"from implicitron.dataset.load_llff import load_llff_data\n", | |
"\n", | |
"\n", | |
"# Copyright (c) Meta Platforms, Inc. and affiliates.\n", | |
"# All rights reserved.\n", | |
"#\n", | |
"# This source code is licensed under the BSD-style license found in the\n", | |
"# LICENSE file in the root directory of this source tree.\n", | |
"\n", | |
"\n", | |
"# the function is taken from:\n", | |
"# https://github.com/facebookresearch/pytorch3d/blob/bd93e9ce21a0b73f1097181e6e6c0bc32e71b7ef/pytorch3d/implicitron/dataset/single_sequence_dataset.py#L163\n", | |
"\n", | |
"def _interpret_blender_cameras(\n", | |
" poses: torch.Tensor, focal: float):\n", | |
" \"\"\"\n", | |
" Convert 4x4 matrices representing cameras in blender format\n", | |
" to PyTorch3D format.\n", | |
"\n", | |
" Args:\n", | |
" poses: N x 3 x 4 camera matrices\n", | |
" focal: ndc space focal length\n", | |
" \"\"\"\n", | |
" pose_target_cameras = []\n", | |
" for pose_target in poses:\n", | |
" pose_target = pose_target[:3, :4]\n", | |
" mtx = torch.eye(4, dtype=pose_target.dtype)\n", | |
" mtx[:3, :3] = pose_target[:3, :3].t()\n", | |
" mtx[3, :3] = pose_target[:, 3]\n", | |
" mtx = mtx.inverse()\n", | |
"\n", | |
" # flip the XZ coordinates.\n", | |
" mtx[:, [0, 2]] *= -1.0\n", | |
"\n", | |
" Rpt3, Tpt3 = mtx[:, :3].split([3, 1], dim=0)\n", | |
"\n", | |
" focal_length_pt3 = torch.FloatTensor([[focal, focal]])\n", | |
" principal_point_pt3 = torch.FloatTensor([[0.0, 0.0]])\n", | |
"\n", | |
" cameras = PerspectiveCameras(\n", | |
" focal_length=focal_length_pt3,\n", | |
" principal_point=principal_point_pt3,\n", | |
" R=Rpt3[None],\n", | |
" T=Tpt3,\n", | |
" )\n", | |
" pose_target_cameras.append(cameras)\n", | |
" return pose_target_cameras\n", | |
"\n", | |
"# A functional simplified version of the following data loader:\n", | |
"# https://github.com/facebookresearch/pytorch3d/blob/a0f786f4cf600a8b1741ef8b5b24bc99272ab0e7/pytorch3d/implicitron/dataset/load_llff.py#L307\n", | |
"\n", | |
"def load_llff_data_pytorch3d(basedir, factor=None):\n", | |
"\n", | |
" images, poses, bds = load_llff_data(basedir, factor=factor)\n", | |
"\n", | |
" hwf = poses[0, :3, -1]\n", | |
" poses = poses[:, :3, :4]\n", | |
"\n", | |
" i_test = np.arange(images.shape[0])[::8]\n", | |
" i_test_index = set(i_test.tolist())\n", | |
" i_train = np.array(\n", | |
" [i for i in np.arange(images.shape[0]) if i not in i_test_index]\n", | |
" )\n", | |
" i_split = (i_train, i_test, i_test)\n", | |
" H, W, focal = hwf\n", | |
" focal_ndc = 2 * focal / min(H, W)\n", | |
" images = torch.from_numpy(images)#.permute(0, 3, 1, 2)\n", | |
" poses = torch.from_numpy(poses)\n", | |
"\n", | |
" poses = _interpret_blender_cameras(poses, focal_ndc)\n", | |
"\n", | |
" return images, poses, bds" | |
], | |
"metadata": { | |
"id": "nYNcWK1qMbmL" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# download the data for comparison: original NeRF fern data \n", | |
"\n", | |
"%cd /content\n", | |
"!gdown 1pQzsS29cJjgoum9kJQo95rJfTObOlp1M\n", | |
"!unzip /content/fern_nerf_original.zip" | |
], | |
"metadata": { | |
"id": "MnCSEUDLovXF" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# use our loader\n", | |
"images, poses, bds = load_llff_data_pytorch3d('/content/fern', factor=None)" | |
], | |
"metadata": { | |
"id": "h4j27hUooZpB" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# now let's load the already preprocessed data from Meta and compare the results\n", | |
"# (with poses already converted to the correct camera mats):\n", | |
"\n", | |
"!wget https://dl.fbaipublicfiles.com/pytorch3d_nerf_data/fern.pth\n", | |
"\n", | |
"data_pytorch3d = torch.load('/content/fern.pth')" | |
], | |
"metadata": { | |
"colab": { | |
"base_uri": "https://localhost:8080/" | |
}, | |
"id": "7wAK4vCcLEnT", | |
"outputId": "63240cbe-6e74-4c5a-d379-e503d1474e9e" | |
}, | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"name": "stdout", | |
"text": [ | |
"--2022-08-06 10:09:20-- https://dl.fbaipublicfiles.com/pytorch3d_nerf_data/fern.pth\n", | |
"Resolving dl.fbaipublicfiles.com (dl.fbaipublicfiles.com)... 104.22.74.142, 172.67.9.4, 104.22.75.142, ...\n", | |
"Connecting to dl.fbaipublicfiles.com (dl.fbaipublicfiles.com)|104.22.74.142|:443... connected.\n", | |
"HTTP request sent, awaiting response... 200 OK\n", | |
"Length: 4021 (3.9K) [application/zip]\n", | |
"Saving to: ‘fern.pth’\n", | |
"\n", | |
"fern.pth 100%[===================>] 3.93K --.-KB/s in 0s \n", | |
"\n", | |
"2022-08-06 10:09:21 (67.6 MB/s) - ‘fern.pth’ saved [4021/4021]\n", | |
"\n" | |
] | |
} | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"print(\"our code rotation matrix:\\n %s\" % poses[0].R)\n", | |
"\n", | |
"print(\"pytorch3d rotation matrix:\\n %s\" % data_pytorch3d['cameras']['R'][0])" | |
], | |
"metadata": { | |
"colab": { | |
"base_uri": "https://localhost:8080/" | |
}, | |
"id": "VXEbpSzupSNn", | |
"outputId": "9484b621-74e2-4ba0-eff5-3eb7354a5e87" | |
}, | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"name": "stdout", | |
"text": [ | |
"converted rotation matrix:\n", | |
" tensor([[[-0.9957, -0.0208, 0.0903],\n", | |
" [-0.0250, 0.9986, -0.0460],\n", | |
" [-0.0892, -0.0481, -0.9948]]])\n", | |
"pytorch3d rotation matrix:\n", | |
" tensor([[-0.9957, -0.0208, 0.0903],\n", | |
" [-0.0250, 0.9986, -0.0460],\n", | |
" [-0.0892, -0.0481, -0.9948]])\n" | |
] | |
} | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"print(\"our code translation vector:\\n %s\" % poses[0].T)\n", | |
"\n", | |
"print(\"pytorch3d translation vector:\\n %s\" % data_pytorch3d['cameras']['T'][0])" | |
], | |
"metadata": { | |
"colab": { | |
"base_uri": "https://localhost:8080/" | |
}, | |
"id": "ROWXvFgKp3Wg", | |
"outputId": "271ce7df-5613-451a-822d-d9c0cd2133cd" | |
}, | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"name": "stdout", | |
"text": [ | |
"our code rotation matrix:\n", | |
" tensor([[-0.2998, -0.1390, 0.0737]])\n", | |
"pytorch3d rotation matrix:\n", | |
" tensor([-0.2998, -0.1390, 0.0737])\n" | |
] | |
} | |
] | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment