├── jupyter_files ├── overview.pdf ├── overview.png ├── overview.xoj ├── loop_closure.pdf ├── loop_closure.png ├── loop_closure.xoj └── make_png.sh ├── environment.yml ├── .vscode ├── settings.json └── launch.json ├── LICENSE ├── .gitignore ├── README.md ├── video_loop_finder.py └── optical_flow_experiments.ipynb /jupyter_files/overview.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/video-loop-finder/HEAD/jupyter_files/overview.pdf -------------------------------------------------------------------------------- /jupyter_files/overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/video-loop-finder/HEAD/jupyter_files/overview.png -------------------------------------------------------------------------------- /jupyter_files/overview.xoj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/video-loop-finder/HEAD/jupyter_files/overview.xoj -------------------------------------------------------------------------------- /jupyter_files/loop_closure.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/video-loop-finder/HEAD/jupyter_files/loop_closure.pdf -------------------------------------------------------------------------------- /jupyter_files/loop_closure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/video-loop-finder/HEAD/jupyter_files/loop_closure.png -------------------------------------------------------------------------------- /jupyter_files/loop_closure.xoj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbc/video-loop-finder/HEAD/jupyter_files/loop_closure.xoj -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | name: video_loop_finder 2 | channels: 3 | - defaults 4 | - conda-forge 5 | dependencies: 6 | - opencv 7 | - notebook 8 | - matplotlib 9 | - jupyter 10 | - docopt 11 | - schema 12 | - ffmpeg-python 13 | - ffmpeg=4.2=h1a5d6f3_0 14 | 15 | -------------------------------------------------------------------------------- /jupyter_files/make_png.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | case "${1%%.*}" in 4 | overview) 5 | convert -density 400 overview.pdf -resize 25% -crop 55x30+190+180% overview.png 6 | ;; 7 | loop_closure) 8 | convert -density 400 loop_closure.pdf -resize 25% -crop 55x18+180+150% loop_closure.png 9 | ;; 10 | *) 11 | echo " 12 | Usage: ${0##*/} 13 | 14 | " 15 | esac 16 | 17 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.pythonPath": "/hd_data/anaconda3/envs/video_loop_finder/bin/python", 3 | "python.linting.pylintEnabled": false, 4 | "python.linting.flake8Enabled": true, 5 | "python.linting.enabled": true, 6 | "python.linting.flake8Args": ["--max-line-length=88"], 7 | "editor.rulers": [ 8 | 88 9 | ], 10 | "python.formatting.provider": "black" 11 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Florian Schweiger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Python: Current File", 9 | "type": "python", 10 | "request": "launch", 11 | "program": "${file}", 12 | "console": "internalConsole", 13 | // "args": [ 14 | // "/hd_data/Dropbox (BBC)/Videos/VID_2019_09_26_14_02_58_20191015155545.mp4", 15 | // // "--flow-filter=inf", 16 | // "990", 17 | // "1800", 18 | // "-d" 19 | // ], 20 | "args": [ 21 | "/hd_data/Dropbox (BBC)/Videos/Full CBBC capture footage/frames_png/cbbc_frame_%04d.png", 22 | "125", 23 | "2100", 24 | // "--flow-filter=off", 25 | // "--range=$((30*25))", 26 | // "--width=32", 27 | // "-o test.mp4", 28 | // "--ffmpeg-opts=-an -b:v 500" 29 | "-i" 30 | ], 31 | "internalConsoleOptions": "openOnSessionStart", 32 | // "justMyCode": false 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # video-loop-finder 2 | Tool to find matching start and end points in a looping video, e.g. in a concentric mosaic light field dataset 3 | 4 | ## Setup 5 | Install depencencies listed in `environment.yml`. 6 | If Anaconda is set up, simply run: 7 | ```bash 8 | conda env create -f environment.yml 9 | ``` 10 | 11 | ## Usage 12 | Check `video_loop_finder.py --help` for possible options. 13 | 14 |
15 | Video Loop Finder
16 | 
17 | USAGE:
18 |     video_loop_finder.py [options] VIDEO_PATH [START_FRAME_IDX [DURATION_HINT]]
19 | 
20 | ARGUMENTS:
21 |     VIDEO_PATH          Path to a video file or printf-style escaped path to image
22 |                         sequence, e.g. '/path/to/image%04d.png'
23 |     START_FRAME_IDX     Index of first frame of loop [default: 0]
24 |     DURATION_HINT       Estimated duration of loop in frames [default: video duration]
25 | 
26 | OPTIONS:
27 |     -r RANGE --range=RANGE          Search for end frame ±RANGE frames around
28 |                                     START_FRAME + DURATION_HINT [default: 50]
29 |     -w WIDTH --width=WIDTH          Image width in pixels used in computations. Set to 0
30 |                                     to use full original image resolution [default: 256]
31 |     -f PIXELS --flow-filter=PIXELS  Filters out optical flow vectors that,
32 |                                     when chaining forward and backward flows together,
33 |                                     do not map back onto themselves within PIXELS. Set
34 |                                     to 'off' to disable filtering. [default: 0.2]
35 |     -i --interactive                Enable interactive alignment of start and end frames
36 |     -d --debug                      Enable more verbose logging and plot intermediate
37 |                                     results
38 |     -o --outfile=OUTFILE            Save trimmed version of video in OUTFILE
39 |     --ffmpeg-opts=OPTS              Pass options OPTS (one quoted string) to ffmpeg,
40 |                                     e.g. --ffmpeg-opts="-b:v 1000 -c:v h264 -an"
41 |     -h --help                       Show this help text
42 | 
43 | 
44 | 
45 | DESCRIPTION:
46 | 
47 | Finds a loop in a repeating video, such as a concentric mosaic dataset, stored in
48 | VIDEO_PATH.
49 | 
50 | This script will find the best matching frame pair in terms of lowest sum of absolute
51 | pixel differences and localise the end frame relative to the actual beginning/end of the
52 | loop.
53 | 
54 | For example, if in a concentric mosaic video, the first frame is assumed at 0° and the
55 | closest end frame is found at 359.1°, then the relative position of the latter is
56 | 359.1°/360° = 99.75%.
57 | 
58 | -------------------------------------------------------------------------------- /video_loop_finder.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | """Video Loop Finder 4 | 5 | USAGE: 6 | video_loop_finder.py [options] VIDEO_PATH [START_FRAME_IDX [DURATION_HINT]] 7 | 8 | ARGUMENTS: 9 | VIDEO_PATH Path to a video file or printf-style escaped path to image 10 | sequence, e.g. '/path/to/image%04d.png' 11 | START_FRAME_IDX Index of first frame of loop [default: 0] 12 | DURATION_HINT Estimated duration of loop in frames [default: video duration] 13 | 14 | OPTIONS: 15 | -r RANGE --range=RANGE Search for end frame ±RANGE frames around 16 | START_FRAME + DURATION_HINT [default: 50] 17 | -b RANGE --match-brightness=RANGE Adjust START_FRAME (and matching end frame) 18 | position within ±RANGE such that the average 19 | brightness difference between them is mimimum 20 | [default: 0] 21 | -w WIDTH --width=WIDTH Image width in pixels used in computations. Set 22 | to 0 to use full original image resolution 23 | [default: 256] 24 | -f PIXELS --flow-filter=PIXELS Filters out optical flow vectors that, when 25 | chaining forward and backward flows together, do 26 | not map back onto themselves within PIXELS. Set 27 | to 'off' to disable filtering. [default: 0.2] 28 | -i --interactive Enable interactive alignment of start and end 29 | frames 30 | -d --debug Enable more verbose logging and plot interme- 31 | diate results 32 | -o --outfile=OUTFILE Save trimmed version of video in OUTFILE 33 | --ffmpeg-opts=OPTS Pass options OPTS (one quoted string) to ffmpeg, 34 | e.g. --ffmpeg-opts="-b:v 1000 -c:v h264 -an" 35 | -h --help Show this help text 36 | 37 | 38 | 39 | DESCRIPTION: 40 | 41 | Finds a loop in a repeating video, such as a concentric mosaic dataset, stored in 42 | VIDEO_PATH. 43 | 44 | This script will find the best matching frame pair in terms of lowest sum of absolute 45 | pixel differences and localise the end frame relative to the actual beginning/end of the 46 | loop. 47 | 48 | For example, if in a concentric mosaic video, the first frame is assumed at 0° and the 49 | closest end frame is found at 359.1°, then the relative position of the latter is 50 | 359.1°/360° = 99.75%. 51 | """ 52 | 53 | import cv2 54 | import numpy as np 55 | import logging 56 | from enum import Enum 57 | from matplotlib import pyplot as plt 58 | from docopt import docopt 59 | from schema import Schema, Use, And, Or, SchemaError 60 | import ffmpeg 61 | import os 62 | from textwrap import dedent 63 | 64 | 65 | # Set up custom logger 66 | logger = logging.Logger(__name__, level=logging.INFO) 67 | handler = logging.StreamHandler() 68 | handler.setFormatter(logging.Formatter("%(levelname)s\t%(message)s")) 69 | logger.addHandler(handler) 70 | 71 | 72 | class VideoLoopDirection(Enum): 73 | CW = 0 74 | CCW = 1 75 | 76 | 77 | class VideoLoopFinder: 78 | """Main class that contains the loop finding logic 79 | 80 | Typical usage: 81 | 82 | vlf = VideoLoopFinder(, , ) 83 | end_frame_idx = vlf.find_closest_end_frame() 84 | relative_end_frame_position = vlf.localise_end_frame() 85 | """ 86 | 87 | def __init__( 88 | self, 89 | video_path, 90 | start_frame_idx=0, 91 | duration_hint=None, 92 | *, 93 | resolution=256, 94 | flow_filter_threshold=0.2, 95 | match_brightness_range=None, 96 | debug=False, 97 | interactive=False, 98 | ): 99 | """Constructor 100 | 101 | Args: 102 | video_path – Path to video file or printf-style image sequence 103 | start_frame_idx – Index of the frame to match (default: 0) 104 | duration_hint – Expected video_duration of video loop in frames 105 | (defaults to video length) 106 | resolution – Image width in pixels used in computations. Set to 107 | None to use full original image resolution 108 | (default: 256) 109 | flow_filter_threshold – Filter out optical flow vectors that, when chai- 110 | ning forward and backward flows together, do not 111 | map back onto themselves within this number of 112 | pixels. Set to None to disable filtering. 113 | (default: 0.2) 114 | debug — Enable more verbose logging and plot intermediate 115 | results 116 | interactive — Enable interactive alignment of start and end 117 | frames 118 | """ 119 | 120 | self.interactive = interactive 121 | self.debug = debug 122 | if debug: 123 | logger.setLevel(logging.DEBUG) 124 | 125 | self.match_brightness_range = match_brightness_range 126 | 127 | # Open video / image sequence and determine its properties 128 | self.video = cv2.VideoCapture(video_path) 129 | self.video_duration = int(self.video.get(cv2.CAP_PROP_FRAME_COUNT)) 130 | width = int(self.video.get(cv2.CAP_PROP_FRAME_WIDTH)) 131 | height = int(self.video.get(cv2.CAP_PROP_FRAME_HEIGHT)) 132 | 133 | if self.video_duration == 0: 134 | self.video_duration = -1 135 | success = True 136 | while success: 137 | self.video_duration += 1 138 | success, _ = self.video.read() 139 | 140 | if resolution == 0: 141 | resolution = width 142 | self.resolution = (resolution, int(height / width * resolution)) 143 | 144 | if duration_hint is None: 145 | self.end_frame_idx = self.video_duration - 1 146 | else: 147 | self.end_frame_idx = ( 148 | min(self.video_duration, start_frame_idx + duration_hint) - 1 149 | ) 150 | 151 | logger.info(f"Input loaded: video_duration={self.video_duration:.0f}") 152 | 153 | # Seek to start_frame_idx 154 | self.start_frame_idx = 0 if start_frame_idx is None else start_frame_idx 155 | self.start_frame = self._seek(self.start_frame_idx) 156 | 157 | # Initialise optical flow algorithm 158 | self.flow_algo = cv2.optflow.createOptFlow_Farneback() 159 | self.flow_filter_threshold = flow_filter_threshold 160 | 161 | # Determine looping direction 162 | self.loop_direction, self.vertical = self._find_video_direction() 163 | if self.vertical: 164 | logger.info("The camera appears to move vertically") 165 | logger.info( 166 | "Looping direction appears to be " 167 | f"{'down' if self.loop_direction == VideoLoopDirection.CW else 'up'}ward" 168 | ) 169 | else: 170 | logger.info(f"Looping direction appears to be {self.loop_direction.name}") 171 | 172 | # Will be populated by find_closest_end_frame 173 | self.end_frames = None 174 | 175 | def _seek(self, frame_idx, downsample=True, grayscale=True, normalise=True): 176 | self.video.set(cv2.CAP_PROP_POS_FRAMES, frame_idx) 177 | success, frame = self.video.read() 178 | if not success: 179 | logger.error(f"Cannot read frame {frame_idx}") 180 | 181 | if grayscale: 182 | frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) 183 | if downsample: 184 | frame = cv2.resize(frame, self.resolution, interpolation=cv2.INTER_AREA) 185 | if normalise: 186 | frame = cv2.normalize(frame.astype(float), None) 187 | 188 | return frame 189 | 190 | def _compute_pixel_difference(self, other_frame): 191 | """Compute mean absulute pixel difference between start_frame and other_frame""" 192 | return np.abs(self.start_frame - other_frame).mean() 193 | 194 | def _find_video_direction(self, frame1=None, frame2=None): 195 | """Determine the direction the video is spinning in between two frames 196 | 197 | Args: 198 | frame1 – First frame or its index (defaults to start frame) 199 | frame2 – Second frame or its index (defaults to start frame + 1) 200 | 201 | Returns: 202 | VideoDirection.CW or VideoDirection.CCW depending on whether the camera 203 | motion between frame1 and frame2 has a positive or negative horizontal 204 | component 205 | """ 206 | if frame1 is None: 207 | frame1 = self.start_frame 208 | elif isinstance(frame1, (np.integer, int)): 209 | frame1 = self._seek(frame1) 210 | 211 | if frame2 is None: 212 | frame2 = self._seek(self.start_frame_idx + 1) 213 | elif isinstance(frame2, (np.integer, int)): 214 | frame2 = self._seek(frame2) 215 | 216 | flow_forward = self.flow_algo.calc(frame1, frame2, None) 217 | 218 | if self.flow_filter_threshold is not None: 219 | flow_backward = self.flow_algo.calc(frame2, frame1, None) 220 | flow_forward = self.filter_optical_flow( 221 | flow_forward, 222 | flow_backward, 223 | self.flow_filter_threshold, 224 | verbose=self.debug, 225 | ).filled() 226 | 227 | x_flow = np.nanmedian(flow_forward[..., 0]) 228 | y_flow = np.nanmedian(flow_forward[..., 1]) 229 | 230 | vertical_flow = np.abs(x_flow) < np.abs(y_flow) 231 | 232 | if np.nanmedian(flow_forward[..., int(vertical_flow)]) < 0: 233 | return VideoLoopDirection.CW, vertical_flow 234 | else: 235 | return VideoLoopDirection.CCW, vertical_flow 236 | 237 | def find_closest_end_frame(self, search_range=50): 238 | """Find frame most similar to start frame that still lies before it, and sets 239 | end_frame_idx and end_frames member variables where 240 | end_frame_idx ← N-1 241 | end_frames[0] ← frame N-1 242 | end_frames[1] ← frame N 243 | Args: 244 | search_range : int 245 | Number of frames to check around (start_frame_idx + duration_hint) in 246 | both directions (default: 50) 247 | Returns: 248 | Index of the last frame of the loop (i.e. index N-1) 249 | """ 250 | idx_from = max(1, self.end_frame_idx - search_range) 251 | idx_to = min(self.video_duration - 2, self.end_frame_idx + search_range) 252 | end_frame_range = np.arange(idx_from, idx_to + 1) 253 | 254 | # Iterate over video with 3-frame window, searching for closest match 255 | prev_frame = None 256 | curr_frame = self._seek(idx_from - 1) 257 | next_frame = self._seek(idx_from) 258 | min_diff = np.inf 259 | min_idx = idx_from 260 | min_frames = tuple() # 3 frames centered on current minimum 261 | mads = np.empty_like(end_frame_range, dtype=float) 262 | self.end_frame_cache = [] 263 | for i in range(len(end_frame_range)): 264 | # Read new frame 265 | success, frame = self.video.read() 266 | if not success: 267 | msg = f"Failed to read frame {end_frame_range[i]}" 268 | logger.fatal(msg) 269 | raise RuntimeError(msg) 270 | frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) 271 | frame = cv2.resize(frame, self.resolution, interpolation=cv2.INTER_AREA) 272 | frame = cv2.normalize(frame.astype(float), None) 273 | 274 | # Shift frames along 275 | prev_frame = curr_frame 276 | curr_frame = next_frame 277 | next_frame = frame 278 | 279 | # Keep frames for interactive mode 280 | if self.interactive: 281 | self.end_frame_cache.append(curr_frame) 282 | 283 | # Test for minimum MAD 284 | mad = self._compute_pixel_difference(curr_frame) 285 | if self.debug or self.interactive: 286 | mads[i] = mad 287 | if mad and mad < min_diff: 288 | min_diff = mad 289 | min_idx = end_frame_range[i] 290 | min_frames = prev_frame, curr_frame, next_frame 291 | 292 | if self.loop_direction == self._find_video_direction( 293 | min_frames[1], self.start_frame 294 | ): 295 | self.end_frames = [min_frames[1], min_frames[2]] 296 | self.end_frame_idx = min_idx 297 | else: 298 | self.end_frames = [min_frames[0], min_frames[1]] 299 | self.end_frame_idx = min_idx - 1 300 | 301 | if self.debug | self.interactive: 302 | self._plot_dissimilarity( 303 | end_frame_range, mads, "Mean absolute pixel difference" 304 | ) 305 | 306 | return self.start_frame_idx, self.end_frame_idx 307 | 308 | def match_brightness(self): 309 | """Search around start_frame_idx and end_frame_idx for the best match in 310 | brighness""" 311 | 312 | # Set search range as ±match_brightness_range, truncated by video length 313 | search_range = range( 314 | max(1, self.start_frame_idx - self.match_brightness_range) 315 | - self.start_frame_idx, 316 | min( 317 | self.video_duration - 1, 318 | self.end_frame_idx + self.match_brightness_range + 1, 319 | ) 320 | - self.end_frame_idx, 321 | ) 322 | 323 | # Compute average brightness in neighbourhood of start frame 324 | start_brightness = np.empty(len(search_range)) 325 | frame = self._seek( 326 | self.start_frame_idx + search_range[0], 327 | downsample=False, 328 | grayscale=True, 329 | normalise=False, 330 | ) 331 | start_brightness[0] = np.mean(frame) 332 | for i in range(1, len(search_range)): 333 | success, frame = self.video.read() 334 | if not success: 335 | msg = f"Failed to read frame {search_range[i]}" 336 | logger.fatal(msg) 337 | raise RuntimeError(msg) 338 | frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) 339 | start_brightness[i] = np.mean(frame) 340 | 341 | # Compute average brightness in neighbourhood of end frame 342 | end_brightness = np.empty(len(search_range)) 343 | frame = self._seek( 344 | self.end_frame_idx + search_range[0], 345 | downsample=False, 346 | grayscale=True, 347 | normalise=False, 348 | ) 349 | end_brightness[0] = np.mean(frame) 350 | for i in range(1, len(search_range)): 351 | success, frame = self.video.read() 352 | if not success: 353 | msg = f"Failed to read frame {search_range[i]}" 354 | logger.fatal(msg) 355 | raise RuntimeError(msg) 356 | frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) 357 | end_brightness[i] = np.mean(frame) 358 | 359 | # Exhausive search for global minimum of pairwise brightness difference 360 | brightness_difference = np.abs(start_brightness - end_brightness) 361 | min_idx = np.argmin(brightness_difference) 362 | 363 | self.start_frame_idx = self.start_frame_idx + search_range[min_idx] 364 | self.start_frame = self._seek(self.start_frame_idx) 365 | self.end_frame_idx = self.end_frame_idx + search_range[min_idx] 366 | 367 | logger.info( 368 | f"Frame pair closest in brightness: {self.start_frame_idx}, {self.end_frame_idx}" 369 | ) 370 | 371 | if self.interactive: 372 | old_end_frame_idx = self.end_frame_idx 373 | self._plot_dissimilarity( 374 | self.end_frame_idx + search_range - search_range[min_idx], 375 | brightness_difference, 376 | "Absolute average brightness difference", 377 | False, 378 | ) 379 | self.start_frame_idx += self.end_frame_idx - old_end_frame_idx 380 | self.start_frame = self._seek(self.start_frame_idx) 381 | 382 | return self.start_frame_idx, self.end_frame_idx 383 | 384 | def _plot_dissimilarity( 385 | self, end_frame_range, y_values, y_label, show_frame_diff=True 386 | ): 387 | """Plot mean absolute difference of pixels between two frames""" 388 | fig = plt.figure("Dissimilarity with start frame", figsize=(15, 7)) 389 | ax = fig.subplots(1, 2) if show_frame_diff else [plt.axes()] 390 | curve = ax[0].plot(end_frame_range, y_values) 391 | marker = ax[0].plot( 392 | self.end_frame_idx, 393 | y_values[self.end_frame_idx - end_frame_range[0]], 394 | "r.", 395 | ) 396 | ax[0].set_title(f"Start frame idx: {self.start_frame_idx}") 397 | ax[0].set_xlabel(f"end frame index: {self.end_frame_idx}") 398 | ax[0].set_ylabel(y_label) 399 | 400 | if show_frame_diff: 401 | im = ax[1].imshow(np.abs(self.start_frame - self.end_frames[0]), cmap="jet") 402 | plt.colorbar(im) 403 | 404 | if self.interactive: 405 | ax[0].set_title( 406 | f"Start frame idx: {self.start_frame_idx}\n" 407 | "Adjust with Ctrl(+Shift)+Left/Right" 408 | ) 409 | ax[0].set_xlabel( 410 | f"end frame index: {self.end_frame_idx}\n" 411 | "Adjust with (Shift+)Left/Right" 412 | ) 413 | if show_frame_diff: 414 | ax[1].imshow(np.abs(self.start_frame - self.end_frames[0]), cmap="jet") 415 | 416 | def key_handler(event): 417 | if event.key == "left": 418 | self.end_frame_idx -= 1 419 | elif event.key == "shift+left": 420 | self.end_frame_idx -= 10 421 | elif event.key == "right": 422 | self.end_frame_idx += 1 423 | elif event.key == "shift+right": 424 | self.end_frame_idx += 10 425 | 426 | elif event.key == "ctrl+left": 427 | self.start_frame_idx -= 1 428 | elif event.key == "shift+ctrl+left": 429 | self.start_frame_idx -= 10 430 | elif event.key == "ctrl+right": 431 | self.start_frame_idx += 1 432 | elif event.key == "shift+ctrl+right": 433 | self.start_frame_idx += 10 434 | 435 | elif event.key in ["enter", "escape"]: 436 | plt.close() 437 | else: 438 | return 439 | 440 | if "ctrl" in event.key: 441 | self.start_frame_idx %= self.video_duration 442 | self.start_frame = self._seek(self.start_frame_idx) 443 | for i, frame in enumerate(self.end_frame_cache): 444 | y_values[i] = self._compute_pixel_difference(frame) 445 | curve[0].set_ydata(y_values) 446 | ax[0].set_title( 447 | f"Start frame idx: {self.start_frame_idx}\n" 448 | "Adjust with Ctrl(+Shift)+Left/Right" 449 | ) 450 | else: 451 | self.end_frame_idx = np.clip( 452 | self.end_frame_idx, end_frame_range[0], end_frame_range[-1] 453 | ) 454 | self.end_frames = self.end_frame_cache[ 455 | self.end_frame_idx 456 | - end_frame_range[0] : self.end_frame_idx 457 | - end_frame_range[0] 458 | + 2 459 | ] 460 | ax[0].set_xlabel( 461 | f"end frame index: {self.end_frame_idx}\n" 462 | "Adjust with (Shift+)Left/Right" 463 | ) 464 | marker[0].set_data( 465 | self.end_frame_idx, 466 | y_values[self.end_frame_idx - end_frame_range[0]], 467 | ) 468 | if show_frame_diff: 469 | ax[1].imshow( 470 | np.abs(self.start_frame - self.end_frames[0]), cmap="jet" 471 | ) 472 | fig.canvas.draw() 473 | 474 | fig.canvas.mpl_connect("key_press_event", key_handler) 475 | plt.show() 476 | 477 | @staticmethod 478 | def filter_optical_flow(fwd_flow, bwd_flow, threshold, *, verbose=False): 479 | """Remove unreliable flow vectors from fwd_flow 480 | 481 | Follows the flow from the previous to the next frame (fwd_flow) 482 | and from the next back to the previous frame (bwd_flow), and 483 | checks if the final pixel location is within threshold of the 484 | initial location. If not, the fwd_flow vector at this pixel is 485 | set to (None,None) to mark it as unreliable. 486 | 487 | Args: 488 | fwd_flow – optical flow from previous to next frame 489 | which will be filtered 490 | bwd_flow – optical flow from next to previous frame 491 | threshold – maximum deviation in pixels that the 492 | concatenation of fwd_flow aand bwd_flow 493 | may exhibit before classified unreliable 494 | verbose — Show intermediate results 495 | Returns: 496 | A masked_array the same size as fwd_flow with inconsistent flow values masked 497 | out 498 | """ 499 | height, width, depth = fwd_flow.shape 500 | 501 | if bwd_flow.shape != (height, width, depth) or depth != 2: 502 | raise RuntimeError( 503 | "Both input flows must have the same size and have 2 channels" 504 | ) 505 | 506 | fwd_flow = np.ma.masked_array(fwd_flow, copy=True, fill_value=np.nan) 507 | 508 | img_coords_x, img_coords_y = np.meshgrid(np.arange(width), np.arange(height)) 509 | img_coords = np.dstack((img_coords_x, img_coords_y)).astype(np.float32) 510 | coords_in_next = img_coords + fwd_flow 511 | coords_in_prev = ( 512 | cv2.remap( 513 | bwd_flow, 514 | coords_in_next[..., 0], 515 | coords_in_next[..., 1], 516 | cv2.INTER_CUBIC, 517 | None, 518 | ) 519 | + coords_in_next 520 | ) 521 | error = np.linalg.norm(coords_in_prev - img_coords, axis=-1) 522 | if verbose: 523 | plt.figure("Histogram of optical flow relocalisation error") 524 | plt.hist(error.ravel(), bins=100, range=[0, 2]) 525 | plt.xlabel("deviation in pixels") 526 | 527 | fwd_flow.mask = error > threshold 528 | 529 | if fwd_flow.mask.mean() > 0.5: 530 | logger.warning( 531 | "More than 50% of optical flow vectors have been filtered out. " 532 | "Consider increasing --flow-filter threshold" 533 | ) 534 | 535 | return fwd_flow 536 | 537 | def localise_end_frame(self): 538 | """Find exact relative location of end frame on the loop 539 | 540 | Returns: 541 | A float (<= 1.0) that represents the relative location of end frame on the 542 | loop. 543 | For example, 1.0 if the end frame perfectly coincides with the start frame, 544 | or 0.995 if it lies at 99.5%, i.e. 0.5% before the end of the loop. 545 | """ 546 | 547 | if not self.end_frames: 548 | msg = "find_closest_end_frame must be called before localise_end_frame" 549 | logger.fatal(msg) 550 | raise RuntimeError(msg) 551 | 552 | # Compute optical flows 0→(N-1) and 0→N which should point in opposite 553 | # directions 554 | flows = [ 555 | self.flow_algo.calc(self.start_frame, self.end_frames[0], None), 556 | self.flow_algo.calc(self.start_frame, self.end_frames[1], None), 557 | ] 558 | 559 | if self.flow_filter_threshold is not None: 560 | bwd_flows = [ 561 | self.flow_algo.calc(self.end_frames[0], self.start_frame, None), 562 | self.flow_algo.calc(self.end_frames[1], self.start_frame, None), 563 | ] 564 | flows = [ 565 | self.filter_optical_flow( 566 | flows[i], 567 | bwd_flows[i], 568 | self.flow_filter_threshold, 569 | verbose=self.debug, 570 | ).filled() 571 | for i in range(2) 572 | ] 573 | 574 | # We are only interested in the horizontal components 575 | flow_magnitudes = [np.abs(f[..., int(self.vertical)]) for f in flows] 576 | flow_magnitude_sum = sum(flow_magnitudes) 577 | 578 | full_frame_count = self.end_frame_idx - self.start_frame_idx 579 | fractional_frame_count = np.nanmedian( 580 | flow_magnitudes[0][flow_magnitude_sum != 0] 581 | / flow_magnitude_sum[flow_magnitude_sum != 0] 582 | ) 583 | logger.info( 584 | f"Frame {self.start_frame_idx} lies at {100*fractional_frame_count:.0f}%" 585 | f" between frames {self.end_frame_idx} and {self.end_frame_idx + 1}" 586 | ) 587 | if self.debug: 588 | plt.figure("Relative flow from end to start frame") 589 | plt.imshow(flow_magnitudes[0] / flow_magnitude_sum) 590 | plt.colorbar() 591 | plt.figure("Histogram of relative flow measurements") 592 | relative_flow_magnitude = flow_magnitudes[0] / flow_magnitude_sum 593 | plt.hist( 594 | relative_flow_magnitude[~np.isnan(relative_flow_magnitude)], bins=100 595 | ) 596 | plt.xlabel( 597 | f"Relative position of frame {self.start_frame_idx} " 598 | f"between frames {self.end_frame_idx} and {self.end_frame_idx + 1}" 599 | ) 600 | 601 | return full_frame_count / (full_frame_count + fractional_frame_count) 602 | 603 | @staticmethod 604 | def trim_video(in_filepath, from_idx, to_idx, out_filepath, ffmpeg_options): 605 | """Trim input video to [from_idx, to_idx], both inclusive""" 606 | ( 607 | ffmpeg.input(in_filepath) 608 | .trim(start_frame=from_idx, end_frame=to_idx + 1) 609 | .setpts("PTS-STARTPTS") 610 | .output(out_filepath, **ffmpeg_options) 611 | .run() 612 | ) 613 | 614 | 615 | if __name__ == "__main__": 616 | 617 | opts = docopt(__doc__) 618 | schema = Schema( 619 | { 620 | "VIDEO_PATH": Use(str.strip), 621 | "START_FRAME_IDX": Or(None, And(Use(int), lambda f: f >= 0)), 622 | "DURATION_HINT": Or(None, And(Use(int), lambda d: d > 0)), 623 | "--range": And(Use(int), lambda r: r >= 0), 624 | "--match-brightness": And(Use(int), lambda r: r >= 0), 625 | "--width": And(Use(int), lambda w: w >= 0), 626 | "--flow-filter": Or( 627 | And(lambda f: f.lower().strip() == "off", Use(lambda f: None)), 628 | And(Use(float), lambda t: t >= 0), 629 | error="Valid --flow-filter values: 'off' or float > 0", 630 | ), 631 | "--outfile": Or( 632 | None, 633 | And(Use(str.strip), lambda f: not os.path.exists(f)), 634 | error="OUTFILE already exists", 635 | ), 636 | "--ffmpeg-opts": Use( 637 | lambda opts: { 638 | kv[0]: " ".join(kv[1:]) if len(kv) > 1 else None 639 | for opt in opts.split("-") 640 | if len(opt) > 0 641 | for kv in [opt.split()] 642 | } 643 | if opts 644 | else {} 645 | ), 646 | str: object, 647 | } 648 | ) 649 | try: 650 | opts = schema.validate(opts) 651 | except SchemaError as e: 652 | exit(e) 653 | 654 | vlf = VideoLoopFinder( 655 | opts["VIDEO_PATH"], 656 | start_frame_idx=opts["START_FRAME_IDX"], 657 | duration_hint=opts["DURATION_HINT"], 658 | resolution=opts["--width"], 659 | flow_filter_threshold=opts["--flow-filter"], 660 | match_brightness_range=opts["--match-brightness"], 661 | debug=opts["--debug"], 662 | interactive=opts["--interactive"], 663 | ) 664 | 665 | start_frame_idx, end_frame_idx = vlf.find_closest_end_frame( 666 | search_range=opts["--range"] 667 | ) 668 | 669 | if opts["--match-brightness"] > 0: 670 | vlf.match_brightness() 671 | start_frame_idx, end_frame_idx = vlf.find_closest_end_frame(search_range=2) 672 | 673 | end_frame_position = vlf.localise_end_frame() 674 | 675 | print( 676 | dedent( 677 | f""" 678 | Loop detected 679 | Start frame: {start_frame_idx} 680 | End frame: {end_frame_idx} 681 | End frame position: {end_frame_position} 682 | """ 683 | ) 684 | ) 685 | 686 | if opts["--outfile"]: 687 | logger.info(f"Exporting trimmed video to {opts['--outfile']}...") 688 | vlf.trim_video( 689 | opts["VIDEO_PATH"], 690 | start_frame_idx, 691 | end_frame_idx, 692 | opts["--outfile"], 693 | opts["--ffmpeg-opts"], 694 | ) 695 | logger.info("...done") 696 | 697 | if opts["--debug"]: 698 | plt.show() 699 | -------------------------------------------------------------------------------- /optical_flow_experiments.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Optical flow experiments" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Horizontal pixel displacement\n", 15 | "\n", 16 | "\n", 17 | "How much does a 3D point move horizontally relative to the concentric mosaic camera?\n", 18 | "\n", 19 | "![Overview](jupyter_files/overview.png)\n", 20 | "\n", 21 | " $p(\\alpha)=(d+r) \\begin{bmatrix}\\cos(\\alpha)\\\\\\sin(\\alpha)\\\\h\\end{bmatrix}$: 3D point\n", 22 | " \n", 23 | " $d$: distance of point to capture circle\n", 24 | " \n", 25 | " $r$: capture circle radius\n", 26 | " \n", 27 | " $h$: height of 3D point (perpendicular to drawing plane)\n", 28 | " \n", 29 | " $\\alpha$: point's global azimuth angle relative to camera's principal axis\n", 30 | " \n", 31 | " $\\beta$: point's azimuth in camera coordinate frame\n", 32 | " \n", 33 | " $c = (d+r) \\sin(\\alpha)$\n", 34 | " \n", 35 | " $e = (d+r) \\cos(\\alpha)$\n", 36 | " \n", 37 | " $\\tan(\\beta) = \\frac{c}{e-r} = \\frac{(d+r)\\sin(\\alpha)}{(d+r)\\cos(\\alpha)-r}$\n", 38 | " \n", 39 | " " 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "### In equirectangular projection\n", 47 | "\n", 48 | "$$\\beta = \\arctan\\left(\\frac{(d+r)\\sin(\\alpha)}{(d+r)\\cos(\\alpha)-r}\\right)$$" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 29, 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "# Vary r and d(>r)\n", 58 | "d = 3.0\n", 59 | "r = 0.5" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 30, 65 | "metadata": {}, 66 | "outputs": [ 67 | { 68 | "data": { 69 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYYAAAEECAYAAAAs+JM2AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAgAElEQVR4nO3deVxVdf7H8dcXBFREcN9SEfd9A8vK8ueSqbnkkjlTTY2NWlPWWGZ7aTZlVpatWk1lU1Nqi2amgpltmvuSu+KeC0IICLJ+f3+cS4KZK3Aul/fz8eDBPedeL5/Hie6b7/me7+cYay0iIiK5/NwuQEREvIuCQURE8lEwiIhIPgoGERHJR8EgIiL5KBhERCSfUm4XUBAqV65sw8PD3S5DRKTYWLVq1VFrbZXTPecTwRAeHs7KlSvdLkNEpNgwxuz5s+d0KklERPJRMIiISD4KBhERyUfBICIi+RRJMBhjpp6yPdPzNTXPvomefQ8URU0iInJ6hRoMxpgwz4f/DXn2DQKirbWDgVXGmG7GmHYAnn2VjDERxpi+xpjHjTF9C7NGERHJr1CDwVqbaK0dAcTm2R0L1Pc8zv3eDYj2PF7h2RYRkT+RlpbBstj4QnnvIp9jsNauBjDG7PRsxwCVgATPSxKB+tbaOdba8dbaOUVdo4iIt8rJsXz50w4O123I5AkfkJiaUeA/o8iDIc9po/qe7Qgg7ALeZ7gxZqUxZmVcXFwBVyki4n1W7zrKgDd+4u45W1ly6bU80asJYWUDC/znuHFV0hBOnjaKBgYBO4EIz74w4KzjI2vtNGttpLU2skqV067qFhHxCQcS03jhqelUbNeKgO1beX5wa26e/SbNBl1bKD/PjWDYCbTzPO6OM+cQA0Tl2RfjQl0iIl7leHoWLyzcSpfnv+WzeH/861zC+ze1YVD7S/DzM4X2cws9GIwxM4EIz6WoEdbaaUCUMSYaCLPWzsoz7zATSMzdFhEpiXJyLDNX7mPCreOoNWYUPZpVY8aTA6i9bjllI9ud/Q0uUqE30fNcgnou+8YWdi0iIt5u+a4Enpq7iQ0HjjEuLZ7r/OK58boGUL5MkdXgE91VRUSKu30JqUz8ahMhH77PJXUiGHbHDfRtfg1+/n7g71+ktSgYRERclJKexWuLd/DO97sIzk5n8frZlKvZnVJt/+VaTQoGEREXZOdYZq3ax4vzNtNp+Xz63HQT9/dqRtioZVCjhqu1KRhERIrYsth4npq7iY2/JnF70mYenfcSDOsEoe0htOjmEv6MgkFEpIjsS0jl3/M2s2jtPjqmH2bK7X3o07InDImCq65yu7zfKRhERApZ3nkEfz/DFxs+oOnKbzFPDwU/P7j6ardLzEfBICJSSHJyLLNW72fSgq2kxB9jQOua3Nu/LdUPhkNsLJQv73aJp6VgEBEpBCt2JzD+S2c9QsdqQbz31hiCsq6Dv3WE0CbQpInbJf4pBYOISAE6kJjGM/M2M3f9QS4pF8DLN7ahb+uamPThcPnlbpd3ThQMIiIFIC0jmzeX7GTqdzuxFv5dM5UbJ4/Fb9A8MAYefNDtEs+ZgkFE5CJYa/ly/UGembeZg8dOcF2rGjzYswmXZCTDF+GQmel2iedNwSAicoE27D/GuC83snLPbzSvWZ4PgnfRYNFnMPRtMGXhm2/cLvGCKBhERM7T0ZR0Js3fyoxV+6gUHMjEgS0Z1L42/i8sg82bISUFQkLcLvOCKRhERM5RRlYO05fu5uWY7aRlZnP75XUZvetbyqQGgl8dGD3a+SripncFTcEgInIOvt16hPFzNxEbd5zOjavw2HXNqF/OH1r2hy5dnEVqxTwQcikYRETOYPfR40z4ahMxm49Qr3Iw793Uls4/fw0V2kGpUvD991C9uttlFigFg4jIaRxPz+JVTxuLAH/Dgz2b8Pcr6hG44Gu4/XaoUAEGDHC9E2phUDCIiORhrWX22l955uvNHE5KZ0C7WjzYOZyq+2OhlB/06uWMEq680u1SC42CQUTEY+Ovx3hyzkZW7P6NlrVCef2v7WlftwL87W8wdy7s3u1cbeTDoQAKBhERElMzeH7hVj76eS9hZQN5dkBLbmhSAT8/47zgoYdg6NBifQnq+VAwiEiJlZ1j+XjFXp5fsJVjaZnc0jGcf3VvRGhOBrRq5Zw2euUVp+GdFze9K2gKBhEpkVbt+Y0n5vzCLweS6FCvIuP6NqdplbLOlUYEwMiR0LGj22W6QsEgIiXK0ZR0Jn69hZmr9lOtfNDJ7qfLlkHHofD119C0KYwZ43aprlEwiEiJkJ1j+fDnPTy/YCupGdmMuCqCu7s2pFyQ52MwIgIaNoScHHcL9QIKBhHxeav2JPDYFxvZdDCJKxtU5sm+zWlQtRx89BFER8N//gPVqjmPRcEgIr4rPiWdZz2njWqElua1v7SjV8vqGOO52ujgQdi+vdg3vStoxlrrdg0XLTIy0q5cudLtMkTES2TnWD5avpdJ87eQmpHN7Z0iuLtLA4ID/OD116FFC+jcGbKznZvo+Pm5XXKRM8asstZGnu45jRhExKes25fIY7N/Yf3+Y1xevxLj+zWnQVXPaCAtDV5+2Wl617mzzzS9K2gKBhHxCcdSM5m0cAsf/ryXKuWCmDK0LX1a1cBkZcFbb8Ftt0GZMk47i2rV3C7XqykYRKRYs9by+ZoD/HveZhKOZ3Dr5eGM7t6IkNIBzguio2H4cKhcGa6/3uc6oRYGBYOIFFs7jiTz6Be/sCw2gXZ1wnj/7x1oXjPUOWW0aj20bw89e8KPP8Lll7tdbrGhYBCRYictI5tXvtnOW9/HUjawFM8MaMmQyNonexuNHJm/6Z1C4bwoGESkWFm89QiPz/6FfQlpDGhXi4d7NaVyuSBITnauMCpXDh5+GG6+WZegXiAFg4gUC4eTTjD+y018teEg9asE879/XEbH+pWcJ48fd5reXXed0/SucWPnSy6IgkFEvFpuK4tJ87eSnp3D/dc04h9XRRBUyh8yMyEgAIKD4Z//hCuucLtcn6BgEBGvtenXJB7+fANr9yXSqWFlnurXgvDKwc6TS5fCkCEwfz40awb33+9usT5EwSAiXictI5uXFm3j7e93EVYm4GQH1NxWFgD16ztdUKXAKRhExKt8ty2OR77YwL6ENIZE1uahXk0IKxvoPPnf/8LChfD++1C1KixY4G6xPkrBICJeIT4lnQlfbebzNQeIqBLMx8Mv47KISvlfdOQI7NmjpneFTE30RMRVuSuXn5q7iZT0LO7o3IA7O9endIC/0+Tu1VehZUunv1EJbnpX0LyuiZ4xZiIQAcRaa8eesm+FtfY5N+oSkaK1LyGVhz/fwPfbj9KuThjPDmxFo2p5RgIZGfDaa9C1qxMManpXJIo8GIwx3QCstYONMVONMRFAWJ59Ez37WgBtgLXW2jlFXaeIFJ7sHMu7P+7ihYXb8DMwvl9zbrq0rrNyOTPTuXHOsGFO07sffoAqVdwuuURxY8TQHVjhebwK6IYTDLm3Tlrh2Xeo6EsTkcK29VAyYz9dz9p9iXRpUpUJ/VtQM6zMyRdERzstLapVg/79nUlmKVJuBEP8Kdv1Pd8TPN8TgShr7TRAIwURH5GRlcNri3fw+rc7CCl9yiWoaWnwyy8QFQW9ejlrFC67zO2SSyw3ZnBicEYNAINxgiLsfN/EGDPcGLPSGLMyLi6uIOsTkQK2bl8ifV75gZcXbadXyxrEjL6afm1qOaFgrdMW+9prnX5HoFBwWZGPGKy1q40xGGOmAquBWM9TEZ7tMP44qjjd+0wDpoFzVVIhlSsiF+FEZjaTo7fx1vexVA0pzX9ujaRLE89NcpKSTja9e/RRuPVWXYLqJVy5KslaOwLAGDPTWjvWGNMOGALMwhlNTHWjLhEpOCt3J/DArPXEHj3O0A61eahXU8rn3jwnt+ld797OVUdqeudV3LgqKQyYiTOX8Az8PooYYoyZiXMJ6+qirktECkZqRhaTFmzlvZ92UyusDB/efilXNKjsPJmRAYGBTtO7UaPU9M5LaYGbiBSYn2PjeeDT9eyJT+WWjnUZe20TgoM8f3/++KPT9G7BAmje3N1CxfsWuImIb0nNyOK5+c4ooU7FsqdvZ9GokbOCWauWvZ6CQUQuyvJdCYyZtY498ancenk4D1zbmLKBno+W6dOddQnTpzuL1L7+2t1i5ZwoGETkgpzIzGbSgq3858dd1K7wJ6OE+HjYv19N74oZzTGIyHlbs/c37pu5jti449x8WV0e7OmZS8jOhilTnCuOunZV0zsvpjkGESkQ6VnZTFm0nTe+3UmN0FOuOALnqqM334Ru3ZxgUNO7YknBICLnZNOvSYyesZYth5IZ3P4SHuvTzFmXkJEBb7/trF7ObXpXufLZ31C8loJBRM4oKzuHqd/F8lLMNkLLBPL2LZF0a1bt5AtiYuCf/4RataBfP3VC9QEKBhH5U7uPHmf0jLWs3ptI75Y1eKp/CyoGB0JqKmzYAJde6jS9W77caYAnPkHBICJ/YK3lo+V7mTB3MwH+Jn8nVIARI+Crr5zbbIaEKBR8jIJBRPI5knyCsbPWs3hrHFc2qMykwa2oEVoGjh1zri4KCYHHHnNupKNLUH2SgkFEfjf/l0M89Nl6UjOyebJPM27pGO7cVS0lxVm13KeP0/SuUSPnS3ySgkFESEnPYvyXG5mxcj/Na5bnpSFtaFgt5GTTu3LlYPRoNb0rIRQMIiXcqj2/8a9P1rLvt1Tu7Fyfe7s1IrCUn3PZaW7TuxYt4N573S5VioiCQaSEysrO4ZVvdvDq4h1UL1+aT4Z3pEO9iidf0LgxtG0LpfQxUdLov7hICbQ3PpV7P1nD6r2JXN+2FuP6NXcWq737rtP07sMPnfUIc+e6Xaq4QMEgUoJYa/ls9QEen/0Lfn6GKUPb0rd1zZMvOHYMjhxR07sSTk30REqIY2mZPPrFL3y57lc6hFdk8o1tqFUuACZPdk4ZdesGOTlO07vc9Qris9RET6SEW7k7gXs+XsuhpBPcf00j7ujcAH8/AydOOH2OrrnGCQZ1QRUUDCI+LSs7h1cX72DKou1cUqEss0Z2pG21svD6a87q5dKlnVtuVqp09jeTEkPBIOKjDiSmce/Ha1ix+zeub1uL8f2aE1I6wLmL2t13Q5060LevOqHKHygYRHzQ1xsOMvbT9eRYmDykNdc3qgBrV8Fll0HPnrByJbRv73aZ4qUUDCI+JC0jm/FzN/G/5XtpfUkoU4a2pW6lYLjpJpg372TTO4WCnIGCQcRHbD2UzF0frWb7kRRGXl2f0VFVCQzIdp584glnTkGXoMo5UDCIFHO5LbLHf7mJkNIBfDCsA51qlIGmTeG66+CNN6BhQ+dL5BwoGESKsWNpmTz82Qa+2nCQTg0r82K/plSpXN55cswYNb2TC6JgECmm1uz9jbv/t4ZDx07wYM8mDOcAfi0bw8KFTovsUaPcLlGKKQWDSDGTk2N5+4dYnpu/leqhpZkxsiPt6lSAo6HOndSCgtwuUYo5LXMUKUYSjmcw7P0V/HveFro3q8bC8jto98AdYK2zHmHOHN1ARy6agkGkmPg5Np6eL3/Hjzvieapfc17/azvKZqRBQgIcP+52eeJDFAwiXi47x/LKou0MfWsZ5fwN37Ocm1O2Y4xxVjAvWODcYU2kgGiOQcSLxSWn869P1vLDjqP0a1OTp3s2pNyl/4SUBOjeXU3vpFAoGES81E87j3LPx2s5kXyczzLW0HbAw5jAQPjpJ6hY8exvIHKB9OeGiJfJzrG8HLOdm97+mZDSpZjXMpN2k8dhFixwXqBQkEKmEYOIF4lLTufeT9awZtN+7glL4fa7ehAcVAqarXZupiNSBBQMIl5i6c54Rn28hqS0TBZs/pC6Py/B/GsgBIUoFKRIKRhEXJaTY3lt8Q7embuaSyqX44O7OhGe0hAOH1bTO3GFgkHERfEp6dz7yVpWbdzHT9NHETywPwHVewPloUEDt8uTEkrBIOKS5bsSuG/6Mg5nGsbd2IHQeo9irrzS7bJEFAwiRS0nxzL1u1iWvP0ps2c/S8LnX9KgQx3ocLfbpYkACgaRIvXb8QxGz1jL4q1x3NCpPSFJnahYt6rbZYnk4zXBYIyZCEQAK6y1z7ldj0hBW733N6LvGc8NW1bS5Z3p3NQxHDOiq9tlifyBVyxwM8a0A7DWDgYqGWMijDF9jTGPG2P6ulyeyEWx1vL297Hc8OZSgnKyuLJaEDe3quL0OhLxQn86YjDGdAW6A8uttZ8ZY9oAWGvXFkId3YBoz+MVnu1DhfBzRIrUsaRUFg8bwxK/6nTp3ZPbHnmekLKBoFAQL3amEYO11j4I7DLGvIFzmifKGPOGMSa8gOuoBCR4HicC9a21c6y14621cwr4Z4kUiQ37jzHgle9o+c0cHrC7mHpze0KDgxQK4vXONMdQAcBau8YYE2ut/Sz3CWPM7cDbBVhH2Pn+A2PMcGA4QJ06dQqwFJGLY1NTWfXQM9xSpgOhoWVJXvwdbVrVc7sskXP2pyMGa+2nxpiuxpguwNRTnt5VwHXsxBmRgBMS8Wf7B9baadbaSGttZJUqVQq4HJELk5KexZvj/kPklAn8I3UbX43qpFCQYueMVyVZaxcBGGPaGmMqAAbnA/ysH9znKQYYAszCmdc4NYhEvFtyMnsWL+W2bYHs9qtH2LTZ3DOsD35+Om0kxc85Xa5qrV2TZ3ORMaaeZ3I6viAmo621q40xQ4wxM4FYa+3qi31PkaK0Z/AthC6JIXvMh3x4+xV0rF/J7ZJELtgFrWOw1u6igE8nWWvHFuT7iRS6+HhSc+CxxftZUbc3V9/Tm5ljrqFqSGm3KxO5KF6zwE2kWElJIat5C76JiOKzq0dw96CruKdrQ/x16kh8gIJB5HykpUGZMny+PZEN7QaysV5Lpv+9A50a6gII8R0KBpFztWQJdvBgXh77Oi/FlaFD378yZWhbqofq1JH4FgWDyNlYC8awq3o4B2o05fNtv3Hn9S0Y3b0Rpfy9oquMSIFSMIicyZtvQkwMsx95iYc/30zgwEd4cUgb/q+xOqKK71IwiJxB5ol0du46wkMfLKNZw5q88pe21Agt43ZZIoVKwSCSV2YmTJwIUVHEtruCu2wbNnWrz4jO9bn/msYE6NSRlAAKBpG8cnLgo4/YuW0ffX+0BJTy493bOvB/TXTqSEoO/fkjkpoKzz8PmZmc8CvFkw+9TdeafWlSozzzRnVSKEiJoxGDyJIlMGYMB2uGc9uRqmw5lMzIq+tz3zWNdOpISiQFg5RMSUmwbh106gQ9exL9cTT3bMyidEA6790WRWdddSQlmIJBSqY77oCvv+b49lgeX7SHT9ek06FeRabcqAVrIgoGKTmOHoWAAAgNhfHj2fWXYdz+3lpijx5nVNeGjOrSQAvWRNDks5QUycnQsiU88ADWWj6IK0WPpekkncjiw2GXahWzSB4aMYhvS02FsmUhJASeeILk9h0Y+9Fq5m04xFWNqvDiDa2pXC7I7SpFvIr+RBLf9e23UKeOM8kMrOo5hGsXJbJw42Ee7NmE926NUiiInIZGDOJ7PE3vaNUKunQhJ7gcb367gxcWbqNGaGlmjuxI2zoV3K5SxGtpxCC+5fXXYcAAJxwqVuTw29O5+ds4npu/lWtbVGfePZ0UCiJnoRGD+BZrITsbUlNZvO84981cR2pGFhMHtuSGyNoYozusiZyNRgxSvGVkwLhxsGCBs33nnZyY9RlPLtrNbe+toGpIEHPvvpIhUXUUCiLnSCMGKd6shU8+gZQU6NGD7UdSuPt/a9hyKJlbLw/nwZ5NKB3g73aVIsWKgkGKn9RUePVVuPdeCAqCZcuwISF8uGwPE77aRHBgKf5zayRdmlRzu1KRYknBIMXPd9/B2LHQvDn07k2Cf2kemL6KmM2H6dSwMi/c0JqqIWprIXKhFAxSPCQmwvr1cNVVcO21sHEjNGvG99vjuG/GOhJTM3m0d1P+fkU9/Pw0lyByMRQMUjzceSfMnw9790K5cqQ3asykuZt4+4ddNKhajndvi6J5zVC3qxTxCQoG8V5xcU7Tu7AwePppGD0aypVj66Fk7vnYmWC+pWNdHurZlDKBmmAWKSgKBvFOuU3v+vWDqVOhXj1y6obz3g+7eHb+FkKCSvHO3yLp2lQTzCIFTcEg3uX4cQgOdprejRvn3EgHOHTsBGNmreP77Ufp2qQqzw5sRZUQ9TkSKQwKBvEeixfDoEGwaBG0aQMjRgAwd/2vPPL5L2Rk5fD09S34SwctVhMpTAoGcV9u07vWraF7d+dGOsCxtEyenLORz9ccoHXtMCbf0JqIKuVcLlbE9ykYxF2vvgoxMfD551CxInz8MQA/7jjKmJnrOJyczj1dG3JXlwYE6EY6IkVCwSDu8vNzRgupqRAczInMbCbO38K7P+4monIwn95xOW1qh7ldpUiJomCQopWRARMmQMeO0LMn3HGH82UMa/clMnrGWmLjjnPr5eGMvbaJLkMVcYGCQYqWtfDpp5Ce7gSDMWRm5/DKom289u1OqoYE8d9hl3Jlw8puVypSYikYpPAdPw5TpsB99/3e9I6QEAC2HErivhnr2PhrEgPa1eKJPs0JLRPgcsEiJZuCQQrfd9/Bww87Vx316gUhIWRl5zDt+1heit5O+TKlmHpze3o0r+52pSKCgkEKS2IirF0LnTs7p4w2bYKmTQHYcSSF+2euY+2+RHq1rM6E/i2pGBzobr0i8jsFgxSOU5re0bQp2TmWd36I5fmF2ygb6M+UoW3p06qGFquJeBkFgxScw4edOYTcpnf33eeEArAzLoUxM9exem8i3ZtV4+nrW+ieCSJeSsEgBSM5GVq1cpreTZsG9epBvXr5RgllAvyZPKQ1/dvU0ihBxIspGOTipKQ4o4KQEGeUcOWVvz+140gyY2atZ03uKKF/C6qW1yhBxNu5EgzGmIlABBBrrR17yr4V1trn3KhLztOiRU7Tu8WLnaZ3t98OQFZ2DlO/i+XlmO2UDfLn5Rvb0Ld1TY0SRIqJIg8GY0w3AGvtYGPMVGNMBBCWZ99Ez74WQBtgrbV2TlHXKWeQ2/SuXTvn8tMKFX5/atOvSYz9dD0bDhyjV8vqjOvbQu2xRYoZN0YM3YEVnsergG44wRDt2bfCs+9Q0ZcmZzVlCkRHw5w5TiB8+CEA6VnZvPbNDl7/didhZQN4/a/t6NWyhsvFisiFcCMY4k/Zru/5nuD5nghEWWunARopeJuAAAgM/L3pHcDqvb8xdtZ6th9JYUDbWjx2XTMqaF2CSLHlRh/jGJxRA8BgnKA47/aZxpjhxpiVxpiVcXFxBVmf5JWeDo88AvPmOdsjRzq9joKDOZ6exbgvNzLwjZ84np7Fu7dG8eKQNgoFkWKuSEYMp04sG2MwxkwFVgOxnpdFeLbD+OOo4g88I4ppAJGRkbZQChfH7NmQk+PMJ3gmkJdsi+ORzzew/7c0bulYlweubUK5IF3kJuILiuT/5Nwrj/JsjwAwxsy01o41xrQDhgCzcEYTU4uiLvkTKSnw8sswZoxz2mjZst8XqiUcz2DC3E18tuYAEVWCmTmyI1HhFV0uWEQKkhtXJYUBM3HmEp4BsNauNsYMMcbMxLmEdXVR1yUe1sIPP8BjjzlXHV17LZQrh7WW2Wt/ZfzcTSSlZTKqSwPu/L8GlA7Q/RJEfE2RB4O1NpGTcwx59489zculqCQkwJo10KWLEwZbtkCjRgDsjU/lkS828P32o7SpHcazA1vSpHp5lwsWkcKik8Li+Oc/YcGCk03vGjUiKzuHd37YxeSYbfgbw7i+zbnpsrr4+2mhmogvUzCUZAcPQunSznqEZ56BsWN/n0tYty+Rhz7bwKaDSXRrWo3x/ZpTM6yMywWLSFFQMJRUycnOjXP693ea3oWHO7tPZPLCwm1MX7qbKiFBvHlTO3o0r652FiIliIKhpElOdhrehYQ4owRP0ztrLQs2HuKJORs5kpzOzZfV5f4ejSlfWrfZFClpFAwlyaJFMHAgfPONc8XRsGEA7EtI5ck5G1m05QhNa5Rn6s2RtKl93msORcRHKBhKgrxN7/r0gcqVAcj0TC6/HLMdY+CRXk257YpwSvm7sSBeRLyFgsHXTZ7sjBBym9598AEAK3Yn8Ojnv7D1cDLdm1Xjyb7NqaXJZRFBweD7ypSBsmUhLQ3KliXheAbPfr2ZGSv3UyusDNNubs81zau7XaWIeBEFg685cQKefBI6dYLevWHECBg5kpwcy4zle3l2/hZSTmQx4uoI7unakLKB+hUQkfz0qeBr/PycTqj+/k4wGMOmX5N49IsNrN6bSIfwijzVvwWNq4e4XamIeCkFgy9ISoKXXnIWqAUFwdKlEBxM0olMXvSsSahQNpAXBrdmQLtaWpMgImekYPAFS5c6p4+ioqBnT2zZssxec4Cn523maEo6f720DmOuaUJoWa1JEJGzUzAUV/HxsHYtdO0KPXrA1q3QsCFbDyXz2OxfWL4rgdaXhPLO3yJpdYnWJIjIuVMwFFd33QULFzpN74KDSa4dzstzN/HuT7sJKV2KZwa0ZEhkbfzU8E5EzpOCoTj59Vfn8tMKFeDZZ+Ghh34/bfTveZuJS0nnxqjajOnRhIq6vaaIXCAFQ3GRt+ndW29B3bpsPpjEE9OWsXxXAq0uCeWtWyJprVYWInKRFAzeLikJypd3mt5NmgRXXMGxtEwmR2/jg2V7CCldin9f35IhUbV1nwQRKRBqiuPNoqOhdm1Y7dzpNOeWvzEjsTRdnv+W95fuZmiH2iy+rzN/ubSOQkFECoxGDN4ot+ldVBRcfz1Urcq6fYk8Pmcj6/Yl0r5uBd7v24EWtULdrlREfJCCwdu8+CLExMBXX0FYGEdfncpz87cwY+U6KpcL4sUbWnN9Wy1SE5HCo2DwNsHBEBpKZspxPlgXx+SYbaRlZDP8qgju7tKAEN04R0QKmYLBbSdOwOOPw1VXwXXXwYgR/Nh1IE++tYrtR1Lo1LAyT/RpToOq5dyuVERKCAWD2/z8YMECCAxk3+VdePqrzczfeIg6Fcvy1i2RdGtaVaeNRKRIKRjckJTkzCU89BAEBZG65HveWH6QqUB3RU8AAAcpSURBVC8uwd8Y7r+mEbd3iqB0gL/blYpICaRgcMPSpfDUU9hLL2VOjVY8+/UWDh47Qb82NXmwZxNqhOpOaiLiHgVDUYmLc5rede8OPXqw5bvVPLr+OCuXrKV5zfJMGdqWqPCKblcpIqJgKDKjRsHChcRt3M7zP+xnxqr9VAoOZOLAlgxqr1XLIuI9FAyF6cABp+ldxYpkPP0Ms3vcwrg3VnAiM5thV9RjVLeGlNflpyLiZRQMhcXT9M7278+i0U/z9Lzd7DqaQ5cmlXmkd1PqV9HlpyLinRQMBe3YMQgNhZAQDj0+gUnHq/Dp9JXUrxLMe7dF0blxVbcrFBE5IwVDQYqOhoEDSfpqAS8khPDfQ3UIDvTniT6NuOmyugT4q2ehiHg/BUNByMkBPz8y27Vnd6ce3PnFLnYGhvLXS+vyr+6NdNMcESlWFAwXa9IkWLSIb196nwnztrCj5a1c0aASr1zXjCbVy7tdnYjIeVMwXKQjJoidxwwj3/qB6tUrqo2FiBR7CobzdeIEPPIIKR2v4PnAxvw3vj5letzLfV0a8rfLwwkspXkEESneFAznKdNC8pyvmbnqMNM7DmVohzqM7t6ISuWC3C5NRKRAKBjOxbFj8MILLBn8D56KjmVf3wlENq3JPM0jiIgPUjCcgwPzF1P96X/zzpZSZHe4iteGXUFXzSOIiI9SMPyZI0dIXraC521d/rsukIZ3vcOgQZ24paPmEUTEtykYTiMjK4d9fxlGxZ++Y9Yd/+HGKxsxuntXzSOISIlQJMFgjJlqrR2RZ3um52FC7n5jzEQgAlhhrX2uKOo6ld27lyX7Uxn/0yFONBpAp6v/ymf/uIbG1UPcKEdExBWFek7EGBNmjJkK3JBn3yAg2lo7GFhljOlmjGkH4NlXyRgTYYzpa4x53BjTtzBrzLVtxwFSmrXk0B33gIGn7u7Fs48OUSiISIlTqCMGa20iMMIYE5lndywQ5Xlc37PdDYj27Fvh2T5UmLXlit93iOdXxPHJir3ceM1I2g7tzYIBV6qvkYiUWEX+6WetXQ1gjNnp2Y4BKgEJnpckAvWttXOsteOttXMKo47M7By+mvQuZerXY/OX33BLx3Ae+O9TDB58lUJBREq0Ip98znPaqL4xZqIxJgIIu4D3GQ4MB6hTp8751wG8k1mVkI49eOm+3oS3aHDe7yEi4osK/E9jz4f9TGPMA3/ykiGcPG0UDQwCduJMPIMTEvFn+znW2mnW2khrbWSVKlXOu85S/n68+69ruGrJFwoFEZE8CnzEYK0de5aX7ATaATFAd5w5hVicwJjl2Te1oOs6ndAyuq2miMipCv1kuufS1AjPKCLCWjsNiDLGRANh1tpZeeYdZgKJudsiIlL0Cn2OwXMJ6rnsO9tIQ0REioAuvxERkXwUDCIiko+CQURE8lEwiIhIPgoGERHJx1hr3a7hohlj4oA9F/jPKwNHC7AcX6fjdX50vM6Pjtf5uZjjVddae9rVwT4RDBfDGLPSWht59lcK6HidLx2v86PjdX4K63jpVJKIiOSjYBARkXwUDDDN7QKKGR2v86PjdX50vM5PoRyvEj/HICIi+WnEICIi+ZSYYPDcezrv9kzP19Q8+852L4kSJ88xmXiafTpOp6Hjc3b6vTp3bnx2+XwwGGPCPAfwhjz7BgHRni6vq4wx3fLcWW4wUMkYE2GM6WuMedwY09ed6t1ljOkGvx+TMM8x0XE6Ax2fs9Pv1blx87PL54PBWptorR2BczOgXLFAfc/j3O/dOHlnuRWe7ZIu90ZKAKtwjomO05np+Jydfq/OgZufXUV+z2dvYK1dbYwZYozZCcyy1sYYY7oDCZ6XJAJRnpsKzXGtUPedeovV3F9EHac/Vwkdn7PR79UFKqrPLp8fMZxOnqFXfc92BM69piW/3NuvAgzG+R9ax+nMdHzOTr9XF6ioPrt8MhjOYSJmCCeHXtHAIJx7UUd49oXxx79qSoS8xy7PLVenAqtxhrE6Tmem43MW+r26KEXy2eWTwWCtHWutHWytfe5PXrITaOd53B3nFzMGiMqzL6Zwq/ROpx47a+0Iz3nOCGvtLHSczkbH5xzo9+qCFclnl08Gw6mMMTOBCM9fwhGe829RxphoIMxaOyvPXzEzgcTc7ZLMc1VEtOeYPAP5/trTcToNHZ+z0+/VuXPrs0srn0VEJJ8SMWIQEZFzp2AQEZF8FAwiIpKPgkFERPJRMIiISD4KBhERyadE9koSKWyeDqJhQEVgJRBrrU10tyqRc6NgEClgxpgwYISnDXLuwqNPgFmuFiZyjnQqSaTgDedkPxtw+tjE/slrRbyOgkGkcKzMu6EWD1Kc6FSSSMGbBQwyxoAzxxBjjOlmrVVjOCkW1CtJRETy0akkERHJR8EgIiL5KBhERCQfBYOIiOSjYBARkXwUDCIiko+CQURE8lEwiIhIPv8PR5Rk2q4ZzGMAAAAASUVORK5CYII=\n", 70 | "text/plain": [ 71 | "
" 72 | ] 73 | }, 74 | "metadata": { 75 | "needs_background": "light" 76 | }, 77 | "output_type": "display_data" 78 | } 79 | ], 80 | "source": [ 81 | "import numpy as np\n", 82 | "from matplotlib import pyplot as plt\n", 83 | "import matplotlib\n", 84 | "matplotlib.rc('text', usetex = True)\n", 85 | "\n", 86 | "𝛼 = np.linspace(-np.pi, np.pi, 100)\n", 87 | "\n", 88 | "𝛽 = np.arctan2((d+r)*np.sin(𝛼), (d+r)*np.cos(𝛼)-r)\n", 89 | "\n", 90 | "plt.plot(𝛼, 𝛽)\n", 91 | "ticks = np.r_[-180:181:90]\n", 92 | "plt.xticks(ticks*np.pi/180, [str(t)+'°' for t in ticks])\n", 93 | "plt.yticks(ticks*np.pi/180, [str(t)+'°' for t in ticks])\n", 94 | "plt.xlabel('$\\\\alpha$')\n", 95 | "plt.ylabel('$\\\\beta$')\n", 96 | "plt.plot(𝛼, 𝛼, 'r:')\n", 97 | "plt.show()" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "### In pinhole projection\n", 105 | "\n", 106 | "$$x = f \\frac{c}{e-r} = f \\tan(\\beta) = f \\frac{(d+r)\\sin(\\alpha)}{(d+r)\\cos(\\alpha)-r}, \\quad \\text{$f$: focal length}$$\n" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": 31, 112 | "metadata": {}, 113 | "outputs": [], 114 | "source": [ 115 | "# Vary FOV between, for example, 20° and 180°\n", 116 | "horizontal_fov = 60 /180*np.pi" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 32, 122 | "metadata": {}, 123 | "outputs": [ 124 | { 125 | "data": { 126 | "image/png": "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\n", 127 | "text/plain": [ 128 | "
" 129 | ] 130 | }, 131 | "metadata": { 132 | "needs_background": "light" 133 | }, 134 | "output_type": "display_data" 135 | } 136 | ], 137 | "source": [ 138 | "max_𝛼 = np.arctan2( d * np.tan(horizontal_fov/2), d + r)\n", 139 | "𝛼 = np.linspace(-max_𝛼/2, max_𝛼/2, 100)\n", 140 | "x = (d+r)*np.sin(𝛼)/((d+r)*np.cos(𝛼)-r)\n", 141 | "plt.plot(𝛼, x)\n", 142 | "ticks = np.linspace(-max_α/2, max_α/2, 5)\n", 143 | "plt.xticks(ticks, [f'{t*180/np.pi:.1f}°' for t in ticks])\n", 144 | "plt.yticks(ticks)\n", 145 | "plt.xlabel('$\\\\alpha$')\n", 146 | "plt.ylabel('$x/f$')\n", 147 | "plt.plot([-max_α/2, max_α/2], x[[0,-1]], 'r:')\n", 148 | "plt.show()" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": {}, 154 | "source": [ 155 | "### Summary\n", 156 | "\n", 157 | "In both cases, pinhole and equirecatangular, the horizontal pixel displacement of a uniformly moving 3D point is *not* perfectly linear. Especially for points close to the camera and for wide fields of view, the mapping between relative angular point-camera position and horizontal displacement in the image has a slight S-shape.\n", 158 | "\n", 159 | "For small changes in 𝛼, however, the local behaviour can be approximated with a linear function." 160 | ] 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "metadata": {}, 165 | "source": [ 166 | "## Optical flow as measure for relative angular position\n", 167 | "\n", 168 | "Using any dense optical flow method from OpenCV, test if occlusions and other inconsistencies can be detected by chaining the optical flows $\\texttt{frame}_A \\rightarrow \\texttt{frame}_B$ and $\\texttt{frame}_B\\rightarrow \\texttt{frame}_A$ and testing for small deviations.\n", 169 | "\n", 170 | "Also check if the ratio of horizontal optical flow magnitudes reliably represents the angular position of $\\texttt{frame}_0$ halfway between $\\texttt{frame}_{N-1}$ and $\\texttt{frame}_{N}$, i.e. if\n", 171 | "\n", 172 | "$$\n", 173 | " \\frac{\\left|f^x_{0,N-1}(x,y)\\right|}{\\left|f^x_{0,N}(x,y)\\right|} = \\frac{\\delta}{\\Delta\\alpha-\\delta}\n", 174 | "$$\n", 175 | "or\n", 176 | "$$\n", 177 | " \\frac{\\left|f^x_{0,N-1}(x,y)\\right|}{\\left|f^x_{0,N}(x,y)\\right|+\\left|f^x_{0,N-1}(x,y)\\right|} = \\frac{\\delta}{\\Delta\\alpha}\n", 178 | "$$\n", 179 | "\n", 180 | "![Loop closure](jupyter_files/loop_closure.png)\n", 181 | "\n", 182 | "For reference, in Numpy notation, OpenCV defines the flow $f_{A,B}$ between $\\texttt{frame}_A$ and $\\texttt{frame}_B$ by\n", 183 | "$$\\texttt{frame}_A [y,x,:] \\sim \\texttt{frame}_B \\left[ y + f_{A,B}[y,x,1], x + f_{A,B}[y,x,0], :\\right]$$" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": 33, 189 | "metadata": {}, 190 | "outputs": [ 191 | { 192 | "name": "stdout", 193 | "output_type": "stream", 194 | "text": [ 195 | "The autoreload extension is already loaded. To reload it, use:\n", 196 | " %reload_ext autoreload\n" 197 | ] 198 | } 199 | ], 200 | "source": [ 201 | "%load_ext autoreload" 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "execution_count": 34, 207 | "metadata": { 208 | "pixiedust": { 209 | "displayParams": {} 210 | } 211 | }, 212 | "outputs": [ 213 | { 214 | "name": "stderr", 215 | "output_type": "stream", 216 | "text": [ 217 | "INFO\tInput loaded: video_duration=4511\n", 218 | "INFO\tLooping direction appears to be CW\n" 219 | ] 220 | } 221 | ], 222 | "source": [ 223 | "%autoreload 1\n", 224 | "%aimport video_loop_finder\n", 225 | "\n", 226 | "import cv2\n", 227 | "import numpy as np\n", 228 | "from matplotlib import pyplot as plt\n", 229 | "from video_loop_finder import VideoLoopFinder\n", 230 | "\n", 231 | "\n", 232 | "flow_algo = cv2.optflow.createOptFlow_Farneback()\n", 233 | "\n", 234 | "start_frame_idx = 990\n", 235 | "closest_end_frame_idx = 2790\n", 236 | "video_loop_finder = VideoLoopFinder('/home/florians/Videos/VID_2019_09_26_14_02_58_20191015155545.mp4',\n", 237 | " start_frame_idx=start_frame_idx,\n", 238 | " resolution=256)\n", 239 | "\n", 240 | "# For testing, use frames 999(≙N-1), 1000(≙0), 1000+x(≙N) => expected outcome: Δ𝛼=(1+x)𝛿\n", 241 | "x = 1\n", 242 | "frame_0 = video_loop_finder._seek(1000)\n", 243 | "frame_N = [video_loop_finder._seek(1000 + x), \n", 244 | " video_loop_finder._seek(999)]\n", 245 | "\n", 246 | "# Opt. flow from frame N to 0 and its reverse\n", 247 | "flow_N = (flow_algo.calc(frame_N[0], frame_0, None), \n", 248 | " flow_algo.calc(frame_0, frame_N[0], None))\n", 249 | "# Opt. flow from 0 to N-1 and its reverse\n", 250 | "flow_0 = (flow_algo.calc(frame_0, frame_N[1], None),\n", 251 | " flow_algo.calc(frame_N[1], frame_0, None))" 252 | ] 253 | }, 254 | { 255 | "cell_type": "code", 256 | "execution_count": 35, 257 | "metadata": {}, 258 | "outputs": [], 259 | "source": [ 260 | "def directional_colorbar(axes):\n", 261 | " for angle in np.linspace(-np.pi,np.pi):\n", 262 | " axes.bar(angle, 1, color=colors.hsv_to_rgb((angle/2/np.pi+0.5,1.0,1.0)))\n", 263 | " axes.set_yticks([])\n", 264 | " axes.set_xticklabels([f'{h}°' for h in [*range(0,181, 45), *range(-135,0,45)]])\n", 265 | " axes.set_position([0.55,0.4, 0.2,0.2])" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": 36, 271 | "metadata": { 272 | "scrolled": true 273 | }, 274 | "outputs": [ 275 | { 276 | "data": { 277 | "image/png": "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\n", 278 | "text/plain": [ 279 | "
" 280 | ] 281 | }, 282 | "metadata": { 283 | "needs_background": "light" 284 | }, 285 | "output_type": "display_data" 286 | } 287 | ], 288 | "source": [ 289 | "# Sanity check: visualize flow\n", 290 | "\n", 291 | "from matplotlib import colors\n", 292 | "\n", 293 | "flow_to_plot = flow_0\n", 294 | "\n", 295 | "plt.set_cmap(plt.cm.jet)\n", 296 | "hue = np.arctan2(flow_to_plot[0][...,1], flow_to_plot[0][...,0]) / 2/np.pi + 0.5\n", 297 | "value = np.linalg.norm(flow_to_plot[0], axis=-1)\n", 298 | "rgb = colors.hsv_to_rgb(np.dstack((hue, np.ones_like(hue), 1-np.exp(-value))))\n", 299 | "\n", 300 | "fig = plt.gcf()\n", 301 | "fig.set_figwidth(15)\n", 302 | "fig.set_figheight(8)\n", 303 | "ax = fig.add_subplot(121), fig.add_subplot(122, polar=True)\n", 304 | "im = ax[0].imshow(rgb)\n", 305 | "im.format_cursor_data = lambda d: (f'dir: {(colors.rgb_to_hsv(d)[0]-0.5)*360:.0f}°, '\n", 306 | " f'mag: {colors.rgb_to_hsv(d)[2]:.3f}')\n", 307 | "directional_colorbar(ax[1])\n" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": 37, 313 | "metadata": { 314 | "pixiedust": { 315 | "displayParams": {} 316 | } 317 | }, 318 | "outputs": [ 319 | { 320 | "data": { 321 | "image/png": "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\n", 322 | "text/plain": [ 323 | "
" 324 | ] 325 | }, 326 | "metadata": { 327 | "needs_background": "light" 328 | }, 329 | "output_type": "display_data" 330 | } 331 | ], 332 | "source": [ 333 | "# Visualise filtering result\n", 334 | "\n", 335 | "# Vary threshold\n", 336 | "filter_threshold = 0.2\n", 337 | "\n", 338 | "from video_loop_finder import VideoLoopFinder\n", 339 | "\n", 340 | "filter_optical_flow = VideoLoopFinder.filter_optical_flow\n", 341 | "\n", 342 | "filtered_flow = filter_optical_flow(flow_to_plot[0], flow_to_plot[1], filter_threshold)\n", 343 | "\n", 344 | "hue = np.arctan2(filtered_flow[...,1], filtered_flow[...,0]) / 2/np.pi + 0.5\n", 345 | "value = np.linalg.norm(filtered_flow, axis=-1)\n", 346 | "rgb = colors.hsv_to_rgb(np.dstack((hue, np.ones_like(hue), 1-np.exp(-value))))\n", 347 | "rgb[np.any(filtered_flow.mask, -1),:] = np.nan\n", 348 | "\n", 349 | "fig = plt.gcf()\n", 350 | "fig.set_figwidth(15)\n", 351 | "fig.set_figheight(8)\n", 352 | "ax = fig.add_subplot(121), fig.add_subplot(122, polar=True)\n", 353 | "im = ax[0].imshow(rgb)\n", 354 | "im.format_cursor_data = lambda d: (f'dir: {(colors.rgb_to_hsv(d)[0]-0.5)*360:.0f}°, '\n", 355 | " f'mag: {colors.rgb_to_hsv(d)[2]:.3f}')\n", 356 | "directional_colorbar(ax[1])\n", 357 | "plt.show()" 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": 38, 363 | "metadata": {}, 364 | "outputs": [], 365 | "source": [ 366 | "import pixiedust" 367 | ] 368 | }, 369 | { 370 | "cell_type": "code", 371 | "execution_count": 39, 372 | "metadata": { 373 | "pixiedust": { 374 | "displayParams": {} 375 | } 376 | }, 377 | "outputs": [ 378 | { 379 | "name": "stderr", 380 | "output_type": "stream", 381 | "text": [ 382 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 383 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 384 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 385 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 386 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 387 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 388 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 389 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 390 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 391 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 392 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 393 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 394 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 395 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 396 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 397 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 398 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 399 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 400 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 401 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 402 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 403 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 404 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 405 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 406 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 407 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 408 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 409 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 410 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 411 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 412 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 413 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 414 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 415 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 416 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 417 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 418 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 419 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 420 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 421 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 422 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 423 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 424 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 425 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 426 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n", 427 | "WARNING\tMore than 50% of optical flow vectors have been filtered out. Consider increasing --flow-filter threshold\n" 428 | ] 429 | }, 430 | { 431 | "data": { 432 | "image/png": "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\n", 433 | "text/plain": [ 434 | "
" 435 | ] 436 | }, 437 | "metadata": { 438 | "needs_background": "light" 439 | }, 440 | "output_type": "display_data" 441 | } 442 | ], 443 | "source": [ 444 | "# %%pixie_debugger -b24\n", 445 | "\n", 446 | "filter_thresholds = np.logspace(-4,0)\n", 447 | "filter_optical_flow = VideoLoopFinder.filter_optical_flow\n", 448 | "\n", 449 | "output_ratios = []\n", 450 | "output_std = []\n", 451 | "for filter_threshold in filter_thresholds:\n", 452 | " # Horizontal component of flow from 0 to N-1\n", 453 | " xflow_0_to_end = np.abs(filter_optical_flow(flow_0[0], flow_0[1], filter_threshold)[...,0]).filled()\n", 454 | " \n", 455 | " # Horizontal component of flow from 0 to N\n", 456 | " xflow_0_to_N = np.abs(filter_optical_flow(flow_N[1], flow_N[0], filter_threshold)[...,0]).filled()\n", 457 | "\n", 458 | " xflow_sum = xflow_0_to_N + xflow_0_to_end\n", 459 | " δ_over_Δ𝛼 = np.nanmedian(xflow_0_to_end[xflow_sum != 0] / xflow_sum[xflow_sum != 0])\n", 460 | " \n", 461 | "# print(f'{filter_threshold:0.4f}', δ_over_Δ𝛼)\n", 462 | " output_ratios.append(δ_over_Δ𝛼)\n", 463 | " output_std.append(np.nanstd(xflow_0_to_end[xflow_sum != 0] / xflow_sum[xflow_sum != 0]) / 2)\n", 464 | "plt.errorbar(filter_thresholds, output_ratios, output_std, fmt='.-', ecolor='gray', elinewidth=.2)\n", 465 | "plt.show()\n" 466 | ] 467 | }, 468 | { 469 | "cell_type": "markdown", 470 | "metadata": {}, 471 | "source": [ 472 | "### Summary\n", 473 | "\n", 474 | "The outlier detection based on chaining optical flows in forward and backward direction appears to work.\n", 475 | "\n", 476 | "Determining the ratio of $\\delta$ to $\\Delta\\alpha$ from optical flow ratios works reliably, and appears to give stable results for outlier thresholds above 0.1 pixels." 477 | ] 478 | } 479 | ], 480 | "metadata": { 481 | "file_extension": ".py", 482 | "kernelspec": { 483 | "display_name": "Python 3", 484 | "language": "python", 485 | "name": "python3" 486 | }, 487 | "language_info": { 488 | "codemirror_mode": { 489 | "name": "ipython", 490 | "version": 3 491 | }, 492 | "file_extension": ".py", 493 | "mimetype": "text/x-python", 494 | "name": "python", 495 | "nbconvert_exporter": "python", 496 | "pygments_lexer": "ipython3", 497 | "version": "3.7.3" 498 | }, 499 | "mimetype": "text/x-python", 500 | "name": "python", 501 | "npconvert_exporter": "python", 502 | "pygments_lexer": "ipython3", 503 | "version": 3 504 | }, 505 | "nbformat": 4, 506 | "nbformat_minor": 2 507 | } 508 | --------------------------------------------------------------------------------