|
| 1 | +import numpy as np |
| 2 | +import cv2 as cv |
| 3 | +from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas |
| 4 | +import matplotlib.pyplot as plt |
| 5 | + |
| 6 | + |
| 7 | +def get_pixel_derivatives(im_t0, im_t1): |
| 8 | + t0, t1 = im_t0.astype(np.float32), im_t1.astype(np.float32) |
| 9 | + ix, iy = np.zeros(t0.shape, dtype=np.float32), np.zeros(t0.shape, dtype=np.float32) |
| 10 | + ix[1:-1, 1:-1, ...] = t0[1:-1, 2:, ...] - t0[1:-1, :-2, ...] |
| 11 | + iy[1:-1, 1:-1, ...] = t0[2:, 1:-1, ...] - t0[:-2, 1:-1, ...] |
| 12 | + return ix, iy, (t0 - t1).astype(np.float32) |
| 13 | + |
| 14 | + |
| 15 | +def lucas_kanade(im0, im1, k_shape=(5, 5)): |
| 16 | + ix, iy, it = get_pixel_derivatives(im0, im1) |
| 17 | + grad_prods = [ix * ix, ix * iy, iy * iy, ix * it, iy * it] |
| 18 | + grad_prods = [np.sum(grad_prod, axis=2) for grad_prod in grad_prods] if len(im0.shape) == 3 else grad_prods |
| 19 | + wgps = [cv.GaussianBlur(grad_prod, k_shape, 0) for grad_prod in grad_prods] |
| 20 | + wgps = np.concatenate([wgp[:, :, np.newaxis] for wgp in wgps], axis=2) |
| 21 | + m_flow = np.zeros(im0.shape[:2] + (2,), dtype=np.float32) |
| 22 | + (w_h, w_l) = map(lambda x: (x - 1) // 2, k_shape) |
| 23 | + for i in range(w_h, im0.shape[0] - w_h): |
| 24 | + for j in range(w_l, im0.shape[1] - w_l): |
| 25 | + a = [[wgps[i, j, 0], wgps[i, j, 1]], [wgps[i, j, 1], wgps[i, j, 2]]] |
| 26 | + b = [[-wgps[i, j, 3]], [-wgps[i, j, 4]]] |
| 27 | + uv, _, rank, _ = np.linalg.lstsq(a, b, rcond=0.1) |
| 28 | + m_flow[i, j, 0] = uv[0] if rank == 2 else 0 |
| 29 | + m_flow[i, j, 1] = uv[1] if rank == 2 else 0 |
| 30 | + return -m_flow |
| 31 | + |
| 32 | + |
| 33 | +def get_flow_arrows(flow, gap=None, show_arrows_on_plt=False): |
| 34 | + gap = [gap, flow.shape[0] // 30][gap is None] |
| 35 | + x = np.arange(0, flow.shape[1], 1) |
| 36 | + y = np.arange(0, flow.shape[0], 1) |
| 37 | + x, y = np.meshgrid(x, y) |
| 38 | + fig = plt.figure() |
| 39 | + axs = fig.add_axes([0, 0, 1, 1], frameon=False) |
| 40 | + fig.patch.set_alpha(0) |
| 41 | + axs.patch.set_alpha(0) |
| 42 | + canvas = FigureCanvas(fig) |
| 43 | + plt.quiver(x[::gap, ::gap], y[::-gap, ::-gap], flow[::gap, ::gap, 0], -flow[::gap, ::gap, 1], color='red') |
| 44 | + axs.axis('off') |
| 45 | + axs.margins(0) |
| 46 | + canvas.draw() |
| 47 | + image_from_plot = np.frombuffer(fig.canvas.tostring_argb(), dtype=np.uint8) |
| 48 | + image_from_plot = image_from_plot.reshape(fig.canvas.get_width_height()[::-1] + (4,)) |
| 49 | + if not show_arrows_on_plt: |
| 50 | + plt.close(fig) |
| 51 | + return cv.resize(image_from_plot, dsize=flow.shape[1::-1]) |
| 52 | + |
| 53 | + |
| 54 | +def add_flow_over_im(im, flow, show_arrows_on_plt=False): |
| 55 | + im = im.copy() |
| 56 | + if len(im.shape) == 2: |
| 57 | + im = cv.cvtColor(im, cv.COLOR_GRAY2RGB) |
| 58 | + arrows_arbg = get_flow_arrows(flow, show_arrows_on_plt=show_arrows_on_plt) |
| 59 | + alpha = arrows_arbg[:, :, 0] |
| 60 | + for i in range(3): |
| 61 | + im[:, :, i] = (alpha / 255.0) * arrows_arbg[:, :, 1 + i] + ((255.0 - alpha) / 255.0) * im[:, :, i] |
| 62 | + return im |
| 63 | + |
| 64 | + |
| 65 | +def reduce(im): |
| 66 | + im_blur = cv.GaussianBlur(im, (5, 5), 0) |
| 67 | + return im_blur[::2, ::2, ...] |
| 68 | + |
| 69 | + |
| 70 | +def expand(im, dst_size): |
| 71 | + return cv.GaussianBlur(cv.resize(im, dst_size[1::-1], interpolation=cv.INTER_NEAREST), (5, 5), 0) |
| 72 | + |
| 73 | + |
| 74 | +def gaussian_pyramid(im, max_l=np.PINF): |
| 75 | + levels = min(int(np.log2(min(im.shape[:2])) + 1), max_l) |
| 76 | + g_pyr = [im] |
| 77 | + [g_pyr.append(reduce(g_pyr[-1])) for i in range(levels-1)] |
| 78 | + return g_pyr |
| 79 | + |
| 80 | + |
| 81 | +def laplacian_pyramid(im, max_l=np.PINF): |
| 82 | + levels = min(int(np.log2(min(im.shape[:2])) + 1), max_l) |
| 83 | + l_pyr = [im] |
| 84 | + for i in range(levels - 1): |
| 85 | + tmp = reduce(l_pyr[-1]) |
| 86 | + l_pyr[-1] = l_pyr[-1].astype(np.int32) - expand(tmp, l_pyr[-1].shape).astype(np.int32) |
| 87 | + l_pyr.append(tmp) |
| 88 | + return l_pyr |
| 89 | + |
| 90 | + |
| 91 | + |
0 commit comments