Ejemplo n.º 1
0
def discetize_derivatives(img1, img2, smoothingSigma, derivSigma):
    Ix1, Iy1 = gaussderiv(img1, derivSigma)
    Ix2, Iy2 = gaussderiv(img2, derivSigma)
    Ix, Iy = np.mean([Ix1, Ix2], axis=0), np.mean([Iy1, Iy2], axis=0)
    It = gausssmooth(img2 - img1, smoothingSigma)

    return Ix, Iy, It
Ejemplo n.º 2
0
def genereate_response_2():
    responses = np.zeros((100, 100), dtype=np.float32)
    responses[20, 20] = 1
    responses[50, 50] = 4
    responses[80, 20] = 2
    responses[80, 80] = 3
    responses[20, 80] = 0.5
    return gausssmooth(responses, 10)
Ejemplo n.º 3
0
def superimpose_field(u, v, img):
    """
    Superimpose quiver plot onto specified image and return result as numpy array
    
    Args:
        u (numpy.ndarray): Delta values in the x direction.
        v (numpy.ndarray): Delta values in the y direction.
        img (numpy.ndarray): Image on which to superimpose the quiver plot.
    
    Returns:
        (numpy.ndarray): Resulting image in the form of a numpy array.
    """

    # Set scaling.
    scaling = 0.11
    u = cv2.resize(gausssmooth(u, 1.5), (0, 0), fx=scaling, fy=scaling)
    v = cv2.resize(gausssmooth(v, 1.5), (0, 0), fx=scaling, fy=scaling)

    # Normalize magnitudes.
    # u = u / np.sqrt(u**2 + v**2);
    # v = v / np.sqrt(u**2 + v**2);

    # Create plot.
    x_ = (np.array(list(range(1, u.shape[1] + 1))) - 0.5) / scaling
    y_ = (np.array(list(range(1, u.shape[0] + 1))) - 0.5) / scaling
    x, y = np.meshgrid(x_, y_)
    fig = plt.figure()
    ax = plt.gca()
    ax.axis('off')
    ax.quiver(x, y, u, -v, color='r', scale=30)
    ax.imshow(img)
    fig.canvas.draw()
    plt.close()

    # Get plot in shape of numpy array and return it.
    data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')
    return data.reshape(fig.canvas.get_width_height()[::-1] + (3, ))
def gaussian_pyramid(im):
    """
    Compte Gaussian pyramid for specified image and return levels as list of numpy arrays (matrices).
    Author: Jernej Vivod ([email protected])

    Args:
        im (numpy.ndarray): Image for which to compute the Gaussian pyramid.

    Returns:
        (list): List of numpy arrays (matrices) representing the Gaussian level pyramids.
    """

    # Set sigma for Gaussian smoothing.
    SIGMA = 1.0

    # Ensure image image dimensions are even integers.
    im_formatted = im[:im.shape[0] - np.mod(im.shape[0], 2), :im.shape[1] -
                      np.mod(im.shape[1], 2)]

    # Initialize results list.
    res = []

    # Add original image to results array.
    res.append(im_formatted)

    # While image represented by matrix whose lowest dimension larger than 2 ...
    im_nxt = im_formatted.copy()
    while np.min(im_nxt.shape) > 1:

        # Smooth image using Gaussian kernel and subsample.
        im_nxt = gausssmooth(
            im_nxt[:im_nxt.shape[0] -
                   np.mod(im_nxt.shape[0], 2), :im_nxt.shape[1] -
                   np.mod(im_nxt.shape[1], 2)],
            sigma=SIGMA)[:-1:2, :-1:2]

        # Add subsampled image to results list.
        res.append(im_nxt.copy())

    # Return list of Gaussian pyramid stages.
    return list(reversed(res))
Ejemplo n.º 5
0
def horn_schunck(im1, im2, n_iters, conv=False, lmbd=0.5, sigma1=1.0, u_init=None, v_init=None, derivative_smoothing=False, sigma2=1.0):
    """
    Compute the Horn-Schunck optical flow estimation.
    Author: Jernej Vivod ([email protected])

    Args:
        im1 (np.ndarray): First frame.
        im2 (np.ndarray): First frame.
        n_iters (int): Number of iterations to perform.
        conv (bool): Flag specifying whether to use convergence criterion to stop iteration or not.
        sigma1 (float): Standard deviation of the Gaussian smoothing filter used in computing
        the spatial derivatives.
        u_init (numpy.ndarray): Initialization for the u array.
        v_init (numpy.ndarray): Initialization for the v array.
        derivative_smoothing (bool): Boolean flag indicating whether to use smoothing of spatial and the
        temporal derivative.
        sigma2 (float): Standard deviation of the Gaussian smoothing filter used in smoothing
        the temporal derivative.

    Returns:
        (tuple): tuple of matrices of changes in spatial
        coordinates for each pixel.

    """

    # If initial values of u and v are given.
    if not u_init is None and not v_init is None:
        u = u_init
        v = v_init
    else:
        # Else initialize with zeros.
        u = np.zeros(im1.shape, dtype=im1.dtype)
        v = np.zeros(im1.shape, dtype=im1.dtype)

    # Smooth and compute derivatives of first image.
    im_df_dx_t1, im_df_dy_t1 = gaussderiv(im1, sigma=sigma1)

    # Compute temporal derivative
    im_df_dt = im2 - im1
    
    # If option to smooth derivatives selected, average the spatial
    # derivatives and smooth the temporal derivative using a gaussian.
    if derivative_smoothing:
        im_df_dx_t2, im_df_dy_t2 = gaussderiv(im2, sigma=sigma1)
        im_df_dx = 0.5*(im_df_dx_t1 + im_df_dx_t2)
        im_df_dy = 0.5*(im_df_dy_t1 + im_df_dy_t2)
        im_df_dt = gausssmooth(im2, sigma2) - gausssmooth(im1, sigma2)
    else:
        im_df_dx = im_df_dx_t1
        im_df_dy = im_df_dy_t1
    
    # Define residual Laplacian kernel.
    res_lap = np.array([[0, 1/4, 0], [1/4, 0, 1/4], [0, 1/4, 0]])
    
    # u and v matrices for previous iteration (used to check for convergence).
    u_prev = u
    v_prev = v

    # Convergence criterion.
    CONV_THRESH = 1.0e-1

    # Iteratively perform Horn-Schunck method.
    for iter_count in np.arange(n_iters):

        # Convolve u and v values with residual Laplacian kernel.
        u_a = cv2.filter2D(u, ddepth=-1, kernel=res_lap)
        v_a = cv2.filter2D(v, ddepth=-1, kernel=res_lap)
        
        # Compute the new values of u and v.
        p = (im_df_dx*u_a + im_df_dy*v_a + im_df_dt)/(im_df_dx**2 + im_df_dy**2 + lmbd)
        u = u_a - im_df_dx*p
        v = v_a - im_df_dy*p
        
        # If using convergence criterion, check for convergence.
        if conv:
            if np.trace(np.matmul(u - u_prev, (u - u_prev).T)) < CONV_THRESH and np.trace(np.matmul(v - v_prev, (v - v_prev).T)) < CONV_THRESH:
                break

        # Set new previous u and v values.
        u_prev = u
        v_prev = v


    # Return approximated changes in spatial coordinates as
    # a tuple of numpy arrays (matrices).
    return -u, -v
Ejemplo n.º 6
0
def generate_responses_1():
    responses = np.zeros((100, 100), dtype=np.float32)
    responses[70, 50] = 1
    responses[50, 70] = 0.5
    return gausssmooth(responses, 10)
Ejemplo n.º 7
0
def generate_responses_2():
    responses = np.zeros((100, 100), dtype=np.float32)
    responses[60, 60] = 1
    responses[40, 40] = 0.4
    return gausssmooth(responses, 10)
def lucas_kanade(im1,
                 im2,
                 n=3,
                 sigma1=1.0,
                 derivative_smoothing=False,
                 sigma2=1.0):
    """
    Compute the Lucas-Kanade optical flow estimation.
    Author: Jernej Vivod ([email protected])

    Args:
        im1 (np.ndarray): First frame.
        im2 (np.ndarray): First frame.
        n (int): Size of neighborhood to use in computations.
        sigma1 (float): Standard deviation of the Gaussian smoothing filter used in computing
        the spatial derivatives.
        derivative_smoothing (bool): Boolean flag indicating whether to use smoothing of spatial and the
        temporal derivative.
        sigma2 (float): Standard deviation of the Gaussian smoothing filter used in smoothing
        the temporal derivative.

    Returns:
        (tuple): tuple of matrices of changes in spatial
        coordinates for each pixel.
    """

    # Smooth and compute derivatives of first image.
    im_df_dx_t1, im_df_dy_t1 = gaussderiv(im1, sigma=sigma1)

    # Compute temporal derivative
    im_df_dt = im2 - im1

    # If option to smooth derivatives selected, average the spatial
    # derivatives and smooth the temporal derivative using a gaussian.
    if derivative_smoothing:
        im_df_dx_t2, im_df_dy_t2 = gaussderiv(im2, sigma=sigma1)
        im_df_dx = 0.5 * (im_df_dx_t1 + im_df_dx_t2)
        im_df_dy = 0.5 * (im_df_dy_t1 + im_df_dy_t2)
        im_df_dt = gausssmooth(im2, sigma2) - gausssmooth(im1, sigma2)
    else:
        im_df_dx = im_df_dx_t1
        im_df_dy = im_df_dy_t1

    # Initialize kernel for computing the neighborhood sums.
    sum_ker = np.ones((n, n), dtype=float)

    # Compute required neighborhood sums.
    sum_x_squared = cv2.filter2D(np.square(im_df_dx),
                                 ddepth=-1,
                                 kernel=sum_ker)
    sum_y_squared = cv2.filter2D(np.square(im_df_dy),
                                 ddepth=-1,
                                 kernel=sum_ker)
    sum_xy = cv2.filter2D(im_df_dx * im_df_dy, ddepth=-1, kernel=sum_ker)
    sum_xt = cv2.filter2D(im_df_dx * im_df_dt, ddepth=-1, kernel=sum_ker)
    sum_yt = cv2.filter2D(im_df_dy * im_df_dt, ddepth=-1, kernel=sum_ker)

    # Compute determinant of the A matrix.
    det = sum_x_squared * sum_y_squared - np.square(sum_xy)

    # Set minimum determinant value and get indices of pixels where
    # determinant above set threshold.
    DET_THRESH = 1e-5
    det_idx = np.abs(det) > DET_THRESH

    # Compute the approximated changes in spatial coordinates.
    u = np.zeros(im1.shape, dtype=float)
    v = np.zeros(im2.shape, dtype=float)
    u[det_idx] = -(sum_y_squared * sum_xt - sum_xy * sum_yt)[det_idx] / (
        det[det_idx])
    v[det_idx] = -(sum_x_squared * sum_yt - sum_xy * sum_xt)[det_idx] / (
        det[det_idx])

    # Return approximated changes in spatial coordinates as
    # a tuple of numpy arrays (matrices).
    return -u, -v