Source code for tike.align.solvers.farneback

"""Implements a 2D alignmnent algorithm by Gunnar Farneback."""

import numpy as np
from cv2 import calcOpticalFlowFarneback


def _rescale_8bit(a, b, hi=None, lo=None):
    """Return a, b rescaled into the same 8-bit range.

    The images are rescaled into the range [lo, hi] if provided; otherwise, the
    range is decided by clipping the histogram of all bins that are less than
    0.5 percent of the fullest bin.

    """

    if hi is None or lo is None:
        h, e = np.histogram(b, 1000)
        stend = np.where(h > np.max(h) * 0.005)
        st = stend[0][0]
        end = stend[0][-1]
        lo = e[st]
        hi = e[end + 1]

    # Force all values into range [0, 255]
    a = (255 * (a - lo) / (hi - lo))
    b = (255 * (b - lo) / (hi - lo))
    a[a < 0] = 0
    a[a > 255] = 255
    b[b < 0] = 0
    b[b > 255] = 255
    assert np.all(a >= 0), np.all(b >= 0)
    assert np.all(a <= 255), np.all(b <= 255)
    return a, b


[docs]def farneback( op, original, unaligned, pyr_scale=0.5, levels=5, winsize=19, num_iter=16, poly_n=5, poly_sigma=1.1, flow=None, hi=None, lo=None, **kwargs, ): """Find the flow from unaligned to original using Farneback's algorithm For parameter descriptions see https://docs.opencv.org/4.3.0/dc/d6b/group__video__track.html Parameters ---------- original, unaligned (L, M, N) The images to be aligned. flow : (L, M, N, 2) float32 The inital guess for the displacement field. References ---------- Farneback, Gunnar "Two-Frame Motion Estimation Based on Polynomial Expansion" 2003. """ shape = original.shape assert original.dtype == 'float32', original.dtype assert unaligned.dtype == 'float32', unaligned.dtype if flow is None: flow = np.zeros((*shape, 2), dtype='float32') else: flow = flow[..., ::-1].copy() # NOTE: Passing a reshaped view as any of the parameters breaks OpenCV's # Farneback implementation. for i in range(len(original)): flow[i] = calcOpticalFlowFarneback( *_rescale_8bit( original[i], unaligned[i], hi=hi[i] if hi is not None else None, lo=lo[i] if lo is not None else None, ), flow=flow[i], pyr_scale=pyr_scale, levels=levels, winsize=winsize, iterations=num_iter, poly_n=poly_n, poly_sigma=poly_sigma, flags=4, ) return {'flow': flow[..., ::-1], 'cost': -1}