You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

247 lines
1.3 MiB

{
"cells": [
{
"cell_type": "markdown",
"source": [
"# Demo LoFTR-DS on a single pair of images\n",
"\n",
"This notebook shows how to use the loftr matcher with default config(dual-softmax) and the pretrained weights."
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 20,
"source": [
"import os\n",
"os.chdir(\"..\")\n",
"from copy import deepcopy\n",
"\n",
"import torch\n",
"import cv2\n",
"import numpy as np\n",
"import matplotlib.cm as cm\n",
"from src.utils.plotting import make_matching_figure"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"## Indoor Example"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 9,
"source": [
"from src.loftr import LoFTR, default_cfg\n",
"\n",
"# The default config uses dual-softmax.\n",
"# The outdoor and indoor models share the same config.\n",
"# You can change the default values like thr and coarse_match_type.\n",
"_default_cfg = deepcopy(default_cfg)\n",
"_default_cfg['coarse']['temp_bug_fix'] = True # set to False when using the old ckpt\n",
"matcher = LoFTR(config=_default_cfg)\n",
"matcher.load_state_dict(torch.load(\"weights/indoor_ds_new.ckpt\")['state_dict'])\n",
"matcher = matcher.eval().cuda()"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 10,
"source": [
"# Load example images\n",
"img0_pth = \"assets/scannet_sample_images/scene0711_00_frame-001680.jpg\"\n",
"img1_pth = \"assets/scannet_sample_images/scene0711_00_frame-001995.jpg\"\n",
"img0_raw = cv2.imread(img0_pth, cv2.IMREAD_GRAYSCALE)\n",
"img1_raw = cv2.imread(img1_pth, cv2.IMREAD_GRAYSCALE)\n",
"img0_raw = cv2.resize(img0_raw, (640, 480))\n",
"img1_raw = cv2.resize(img1_raw, (640, 480))\n",
"\n",
"img0 = torch.from_numpy(img0_raw)[None][None].cuda() / 255.\n",
"img1 = torch.from_numpy(img1_raw)[None][None].cuda() / 255.\n",
"batch = {'image0': img0, 'image1': img1}\n",
"\n",
"# Inference with LoFTR and get prediction\n",
"with torch.no_grad():\n",
" matcher(batch)\n",
" mkpts0 = batch['mkpts0_f'].cpu().numpy()\n",
" mkpts1 = batch['mkpts1_f'].cpu().numpy()\n",
" mconf = batch['mconf'].cpu().numpy()"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 11,
"source": [
"# Draw\n",
"color = cm.jet(mconf)\n",
"text = [\n",
" 'LoFTR',\n",
" 'Matches: {}'.format(len(mkpts0)),\n",
"]\n",
"fig = make_matching_figure(img0_raw, img1_raw, mkpts0, mkpts1, color, text=text)"
],
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 750x450 with 2 Axes>"
],
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<!-- Created with matplotlib (https://matplotlib.org/) -->\n<svg height=\"273.15pt\" version=\"1.1\" viewBox=\"0 0 714.4 273.15\" width=\"714.4pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <metadata>\n <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n <cc:Work>\n <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\n <dc:date>2021-08-18T00:38:02.543658</dc:date>\n <dc:format>image/svg+xml</dc:format>\n <dc:creator>\n <cc:Agent>\n <dc:title>Matplotlib v3.3.4, https://matplotlib.org/</dc:title>\n </cc:Agent>\n </dc:creator>\n </cc:Work>\n </rdf:RDF>\n </metadata>\n <defs>\n <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\n </defs>\n <g id=\"figure_1\">\n <g id=\"patch_1\">\n <path d=\"M 0 273.15 \nL 714.4 273.15 \nL 714.4 0 \nL 0 0 \nz\n\" style=\"fill:none;\"/>\n </g>\n <g id=\"axes_1\">\n <g id=\"patch_2\">\n <path d=\"M 7.2 265.95 \nL 352.2 265.95 \nL 352.2 7.2 \nL 7.2 7.2 \nz\n\" style=\"fill:#ffffff;\"/>\n </g>\n <g clip-path=\"url(#p3eb01edfe0)\">\n <image height=\"259.2\" id=\"image4d3edb621c\" transform=\"scale(1 -1)translate(0 -259.2)\" width=\"345.6\" x=\"7.2\" xlink:href=\"data:image/png;base64,\n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
"image/png": "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
},
"metadata": {}
}
],
"metadata": {}
},
{
"cell_type": "markdown",
"source": [
"## Outdoor Example"
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 16,
"source": [
"from src.loftr import LoFTR, default_cfg\n",
"\n",
"# The default config uses dual-softmax.\n",
"# The outdoor and indoor models share the same config.\n",
"# You can change the default values like thr and coarse_match_type.\n",
"matcher = LoFTR(config=default_cfg)\n",
"matcher.load_state_dict(torch.load(\"weights/outdoor_ds.ckpt\")['state_dict'])\n",
"matcher = matcher.eval().cuda()"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 19,
"source": [
"default_cfg['coarse']"
],
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"{'d_model': 256,\n",
" 'd_ffn': 256,\n",
" 'nhead': 8,\n",
" 'layer_names': ['self',\n",
" 'cross',\n",
" 'self',\n",
" 'cross',\n",
" 'self',\n",
" 'cross',\n",
" 'self',\n",
" 'cross'],\n",
" 'attention': 'linear',\n",
" 'temp_bug_fix': True}"
]
},
"metadata": {},
"execution_count": 19
}
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 17,
"source": [
"# Load example images\n",
"img0_pth = \"assets/phototourism_sample_images/united_states_capitol_26757027_6717084061.jpg\"\n",
"img1_pth = \"assets/phototourism_sample_images/united_states_capitol_98169888_3347710852.jpg\"\n",
"img0_raw = cv2.imread(img0_pth, cv2.IMREAD_GRAYSCALE)\n",
"img1_raw = cv2.imread(img1_pth, cv2.IMREAD_GRAYSCALE)\n",
"img0_raw = cv2.resize(img0_raw, (img0_raw.shape[1]//8*8, img0_raw.shape[0]//8*8)) # input size shuold be divisible by 8\n",
"img1_raw = cv2.resize(img1_raw, (img1_raw.shape[1]//8*8, img1_raw.shape[0]//8*8))\n",
"\n",
"img0 = torch.from_numpy(img0_raw)[None][None].cuda() / 255.\n",
"img1 = torch.from_numpy(img1_raw)[None][None].cuda() / 255.\n",
"batch = {'image0': img0, 'image1': img1}\n",
"\n",
"# Inference with LoFTR and get prediction\n",
"with torch.no_grad():\n",
" matcher(batch)\n",
" mkpts0 = batch['mkpts0_f'].cpu().numpy()\n",
" mkpts1 = batch['mkpts1_f'].cpu().numpy()\n",
" mconf = batch['mconf'].cpu().numpy()"
],
"outputs": [],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": 18,
"source": [
"# Draw\n",
"color = cm.jet(mconf)\n",
"text = [\n",
" 'LoFTR',\n",
" 'Matches: {}'.format(len(mkpts0)),\n",
"]\n",
"fig = make_matching_figure(img0_raw, img1_raw, mkpts0, mkpts1, color, text=text)"
],
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 750x450 with 2 Axes>"
],
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<!-- Created with matplotlib (https://matplotlib.org/) -->\n<svg height=\"272.470866pt\" version=\"1.1\" viewBox=\"0 0 714.4 272.470866\" width=\"714.4pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <metadata>\n <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n <cc:Work>\n <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\n <dc:date>2021-08-18T00:41:19.149192</dc:date>\n <dc:format>image/svg+xml</dc:format>\n <dc:creator>\n <cc:Agent>\n <dc:title>Matplotlib v3.3.4, https://matplotlib.org/</dc:title>\n </cc:Agent>\n </dc:creator>\n </cc:Work>\n </rdf:RDF>\n </metadata>\n <defs>\n <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\n </defs>\n <g id=\"figure_1\">\n <g id=\"patch_1\">\n <path d=\"M 0 272.470866 \nL 714.4 272.470866 \nL 714.4 0 \nL 0 0 \nz\n\" style=\"fill:none;\"/>\n </g>\n <g id=\"axes_1\">\n <g id=\"patch_2\">\n <path d=\"M 7.2 238.945357 \nL 352.2 238.945357 \nL 352.2 33.525509 \nL 7.2 33.525509 \nz\n\" style=\"fill:#ffffff;\"/>\n </g>\n <g clip-path=\"url(#pc05f72b92d)\">\n <image height=\"205.44\" id=\"image0a21b05d4c\" transform=\"scale(1 -1)translate(0 -205.44)\" width=\"345.6\" x=\"7.2\" xlink:href=\"data:image/png;base64,\n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
"image/png": "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
},
"metadata": {}
}
],
"metadata": {}
},
{
"cell_type": "code",
"execution_count": null,
"source": [],
"outputs": [],
"metadata": {}
}
],
"metadata": {
"kernelspec": {
"name": "python3",
"display_name": "Python 3.8.8 64-bit ('svcnn': conda)"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.8"
},
"orig_nbformat": 2,
"interpreter": {
"hash": "5b8911f875a754a9ad2a8804064d078bf6a1985972bb0389b9d67771213c8e20"
}
},
"nbformat": 4,
"nbformat_minor": 2
}