当前位置: 首页 > news >正文

mlq移动最小二乘方法

Image Deformation Using Moving Least Squares

  1. 移动最小二乘的移动是指, 所有traindata 对 每个grid point的影响(weight)是不一样的。
  2. 文中介绍三种变换: 仿射,相似,刚体变换
  3. 对应的代码: https://github.com/Jarvis73/Moving-Least-Squares

https://github.com/search?q=Moving+Least+Squares

  1. 问题:

当有一些点聚在一起,会产生大的影响,即使 偏移很小。?
因此点应该均匀?

  1. 对于起始点固定的情况比较友好,可以提前计算出A,然后每次目标变化的时候A也是不变的。

  2. 注意边界
    clip 应该到 h-1, w-1更好,而不是设为0
    在这里插入图片描述

    其次不取整,采用cv2.remap更好:下面通过光流warp 图像

    def flow_warp(im1, im2, flow):
     """
     :param im1: pre image
     :param im2: next image
     :param flow: optical flow ,im1 to im2, h, w, 2,  0:(x),1:(y)
     :return:
     """
     h, w, c = im1.shape
     hh = np.arange(0, h)
     ww = np.arange(0, w)
     xx, yy = np.meshgrid(ww, hh)
    
     # tx = xx - flow[..., 0]
     # ty = yy - flow[..., 1]
     tx = flow[..., 0]
     ty = flow[..., 1]
     mask = ((tx < 0) + (ty < 0) + (tx > w - 1) + (ty > h - 1)) > 0
     # print(mask.shape, mask.dtype, np.sum(mask))
     # out = interp_linear(image, tx, ty)
     # warped im1, should compare with im2
     out = cv2.remap(im1, tx.astype(np.float32), ty.astype(np.float32), interpolation=cv2.INTER_LINEAR)
     out[mask] = 0
     return out
    
  3. 画网格:

import cv2
import numpy as np

import matplotlib.pyplot as plt
from PIL import Image

from matplotlib.collections import LineCollection

def plot_grid(x,y, ax=None, **kwargs):

    ax = ax or plt.gca()

    segs1 = np.stack((x,y), axis=2)

    segs2 = segs1.transpose(1,0,2)

    ax.add_collection(LineCollection(segs1, **kwargs))

    ax.add_collection(LineCollection(segs2, **kwargs))

    ax.autoscale()

    ax.invert_yaxis()  # y轴反向

if __name__ == "__main__":
    import os

    os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
    image = np.array(Image.open("images/toy.jpg"))


    plt.figure()
    ax = plt.subplot(121)
    ax.imshow(cv2.resize(image, (100, 100)))
    # h, w, c = 100, 100, 3
    # hh, ww = np.arange(h), np.arange(w)
    # xx, yy = np.meshgrid(ww, hh)
    f = lambda x, y: (x + 6 * np.exp(-x ** 2 - y ** 2), y)
    grid_x, grid_y = np.meshgrid(np.linspace(0, 100, 40), np.linspace(0, 100, 40))
    plot_grid(grid_x, grid_y, color="lightgrey")
    distx, disty = f(grid_x, grid_y)
    plot_grid(distx, disty, color="C0")
    ax.invert_yaxis()  # y轴反向
    plt.show()
  1. affine 我的实现
import time

import cv2
import numpy as np
import torch
from PIL import Image
from matplotlib import pyplot as plt
from torchvision.utils import flow_to_image

from img_utils import mls_affine_deformation
from plot_grid import plot_grid





def mls_affine():
    image = np.array(Image.open("images/toy.jpg"))

    height, width, _ = image.shape
    gridX = np.arange(width, dtype=np.int16)
    gridY = np.arange(height, dtype=np.int16)
    xx, yy = np.meshgrid(gridX, gridY)
    # print(xx[:4,:4], yy[:4,:4])
    # affine = mls_affine_deformation(vy, vx, p, q, alpha=1)

    eps = 1e-8
    alpha = 2
    q = np.array([
        [155, 30], [155, 125], [155, 225],
        [235, 100], [235, 160], [295, 85], [293, 180]
    ])
    p = np.array([
        [211, 42], [155, 125], [100, 235],
        [235, 80], [235, 140], [295, 85], [295, 180]
    ])
    n = len(p)
    q = q.astype(np.float32).reshape(n, 1, 1, 2)
    p = p.astype(np.float32).reshape(n, 1, 1, 2)
    v = np.vstack((yy.reshape(1, height, width), xx.reshape(1, height, width))).astype(np.float32)
    # v = np.dstack((yy, xx)).transpose(2, 0, 1) # python速度提升的方法, 第一个是对输入明确类型, 第二个是尽量不要用dstack

    v = v.transpose(1, 2, 0).reshape(-1, height, width, 2)
    print(p.shape, v.shape)
    w = 1 / (np.sum((p.reshape(-1, 1, 1, 2) - v) ** alpha, axis=-1) + eps) # n, h, w
    print(w.shape)
    w_norm = w / np.sum(w, axis=0, keepdims=True)   # n, h, w
    p_star = np.sum(p.reshape(-1, 1, 1, 2) * w_norm.reshape(-1, height, width, 1), axis=0) # 1, h, w, 2
    q_star = np.sum(q.reshape(-1, 1, 1, 2) * w_norm.reshape(-1, height, width, 1), axis=0) # 1, h, w, 2

    p_hat = p.reshape(-1, 1, 1, 2) - p_star  # n, h, w, 2
    q_hat = q.reshape(-1, 1, 1, 2) - q_star  # n, h, w, 2

    A_1row = np.sum(p_hat[..., 0][..., None] * p_hat * w_norm[..., None], axis=0, keepdims=True)  # 1, h, w, 2
    A_2row = np.sum(p_hat[..., 1][..., None] * p_hat * w_norm[..., None], axis=0, keepdims=True)  # 1, h, w, 2

    b_1row = np.sum(p_hat[..., 0][..., None] * q_hat * w_norm[..., None], axis=0, keepdims=True)  # 1, h, w, 2
    b_2row = np.sum(p_hat[..., 1][..., None] * q_hat * w_norm[..., None], axis=0, keepdims=True)  # 1, h, w, 2

    A = np.transpose(np.hstack((A_1row, A_2row)), [1, 2, 0, 3]).reshape(height, width, 2, 2)
    b = np.transpose(np.hstack((b_1row, b_2row)), [1, 2, 0, 3]).reshape(height, width, 2, 2)
    print(A.shape, b.shape,  A[:1,:1, :, :])

    # a11 = A[..., 0, 0]
    # a12 = A[..., 0, 1]
    # a21 = A[..., 1, 0]
    # a22 = A[..., 1, 1]
    # A_det = a11 * a22 - a12 * a21
    # A_inv = np.dstack((a22, -a12, -a21, a11)) / A_det[..., None]
    # A_inv = A_inv.reshape(height, width, 2, 2)
    A_inv = np.linalg.inv(A)
    M = np.einsum("ijmk,ijkn->ijmn", A_inv, b)

    x = v.reshape(height, width, 1, 2) - p_star.reshape(height, width, 1, 2)
    flow = np.einsum("ijmk,ijkn->ijmn", x, M) + q_star.reshape(height, width, 1, 2)

    flow = np.transpose(flow.reshape(height, width, 2), (2, 0, 1))
    flow[flow < 0] = 0
    flow[0][flow[0] > height - 1] = height - 1
    flow[1][flow[1] > width - 1] = width - 1
    return flow


def mls_affine2(xx, yy, p, q):
    start = time.time()
    height, width = xx.shape

    eps = 1e-8
    alpha = 2
    # start = time.time()
    n = len(p)
    q = q.astype(np.float32).reshape(n, 2, 1, 1)
    p = p.astype(np.float32).reshape(n, 2, 1, 1)
    v = np.vstack((yy.reshape(1, height, width), xx.reshape(1, height, width))).astype(np.float32)
    # v = np.dstack((yy, xx)).transpose(2, 0, 1) # python速度提升的方法, 第一个是对输入明确类型, 第二个是尽量不要用dstack

    p = p.transpose(0, 2, 3, 1)
    q = q.transpose(0, 2, 3, 1)
    v = v.transpose(1, 2, 0).reshape(-1, height, width, 2)
    print(p.shape, v.shape)
    w = 1 / (np.sum((p.reshape(-1, 1, 1, 2) - v) ** alpha, axis=-1) + eps) # n, h, w
    print(w.shape)
    end = time.time()
    print('run time:', end-start)
    w_norm = w / np.sum(w, axis=0, keepdims=True)   # n, h, w
    p_star = np.sum(p.reshape(-1, 1, 1, 2) * w_norm.reshape(-1, height, width, 1), axis=0) # 1, h, w, 2
    q_star = np.sum(q.reshape(-1, 1, 1, 2) * w_norm.reshape(-1, height, width, 1), axis=0) # 1, h, w, 2

    p_hat = p.reshape(-1, 1, 1, 2) - p_star  # n, h, w, 2
    q_hat = q.reshape(-1, 1, 1, 2) - q_star  # n, h, w, 2
    end = time.time()
    print('run time1:', end - start)
    A_1row = np.sum(p_hat[..., 0][..., None] * p_hat * w_norm[..., None], axis=0, keepdims=True)  # 1, h, w, 2
    A_2row = np.sum(p_hat[..., 1][..., None] * p_hat * w_norm[..., None], axis=0, keepdims=True)  # 1, h, w, 2

    b_1row = np.sum(p_hat[..., 0][..., None] * q_hat * w_norm[..., None], axis=0, keepdims=True)  # 1, h, w, 2
    b_2row = np.sum(p_hat[..., 1][..., None] * q_hat * w_norm[..., None], axis=0, keepdims=True)  # 1, h, w, 2
    end = time.time()
    print('run time2:', end - start)
    A = np.transpose(np.hstack((A_1row, A_2row)), [1, 2, 0, 3]).reshape(height, width, 2, 2)
    b = np.transpose(np.hstack((b_1row, b_2row)), [1, 2, 0, 3]).reshape(height, width, 2, 2)
    print(A.shape, b.shape,  A[:1,:1, :, :])
    end = time.time()
    print('run time3:', end - start)
    # a11 = A[..., 0, 0]
    # a12 = A[..., 0, 1]
    # a21 = A[..., 1, 0]
    # a22 = A[..., 1, 1]
    # A_det = a11 * a22 - a12 * a21
    # A_inv = np.dstack((a22, -a12, -a21, a11)) / A_det[..., None]
    # A_inv = A_inv.reshape(height, width, 2, 2)
    A_inv = np.linalg.inv(A)
    M = np.einsum("ijmk,ijkn->ijmn", A_inv, b)

    x = v.reshape(height, width, 1, 2) - p_star.reshape(height, width, 1, 2)
    flow = np.einsum("ijmk,ijkn->ijmn", x, M) + q_star.reshape(height, width, 1, 2)
    end = time.time()
    print('run time4:', end - start)
    flow = np.transpose(flow.reshape(height, width, 2), (2, 0, 1))
    flow[flow < 0] = 0
    flow[0][flow[0] > height - 1] = height - 1
    flow[1][flow[1] > width - 1] = width - 1
    end = time.time()
    print('run time5:', end - start)
    return flow.astype(np.int16)

def flow_warp(im1, im2, flow):
    """
    :param im1: pre image
    :param im2: next image
    :param flow: optical flow ,im1 to im2, h, w, 2,  0:(x),1:(y)
    :return:
    """
    h, w, c = im1.shape
    hh = np.arange(0, h)
    ww = np.arange(0, w)
    xx, yy = np.meshgrid(ww, hh)

    # tx = xx - flow[..., 0]
    # ty = yy - flow[..., 1]
    tx = flow[..., 0]
    ty = flow[..., 1]
    mask = ((tx < 0) + (ty < 0) + (tx > w - 1) + (ty > h - 1)) > 0
    # print(mask.shape, mask.dtype, np.sum(mask))
    # out = interp_linear(image, tx, ty)
    # warped im1, should compare with im2
    out = cv2.remap(im1, tx.astype(np.float32), ty.astype(np.float32), interpolation=cv2.INTER_LINEAR)
    out[mask] = 0
    return out

def mls_affine_my(image, p, q):
    '''
    其实给定p和 q, 完整的flow就已经确定
    Parameters
    ----------
    image: h, w, c
    p : n*2, (x, y)
    q : n*2, (x, y)
    Returns
    -------
    return flow:p->q, shape like image,  h*w*2: (x, y)
    '''
    eps = 1e-8
    height, width, _ = image.shape
    gridX = np.arange(width, dtype=np.int16)
    gridY = np.arange(height, dtype=np.int16)
    xx, yy = np.meshgrid(gridX, gridY)

    n = len(p)
    q = q.astype(np.float32).reshape(n, 1, 1, 2)
    p = p.astype(np.float32).reshape(n, 1, 1, 2)
    v = np.dstack((xx, yy))

    w = 1.0 / (np.sum((p - v) ** 2, axis=-1) + eps) ** 1
    w_norm = w / np.sum(w, axis=0, keepdims=True)

    p_star = np.sum(p * w_norm.reshape(-1, height, width, 1), axis=0)  # 1, h, w, 2
    q_star = np.sum(q * w_norm.reshape(-1, height, width, 1), axis=0)  # 1, h, w, 2

    p_hat = p - p_star  # n, h, w, 2
    q_hat = q - q_star  # n, h, w, 2
    print(p_hat.shape, q_hat.shape, w_norm.shape)

    A_1row = np.sum(p_hat[..., 0][..., None] * p_hat * w_norm[..., None], axis=0)  # 1, h, w, 2
    A_2row = np.sum(p_hat[..., 1][..., None] * p_hat * w_norm[..., None], axis=0)  # 1, h, w, 2

    b_1row = np.sum(p_hat[..., 0][..., None] * q_hat * w_norm[..., None], axis=0)  # 1, h, w, 2
    b_2row = np.sum(p_hat[..., 1][..., None] * q_hat * w_norm[..., None], axis=0)  # 1, h, w, 2

    A = np.dstack((A_1row, A_2row)).reshape(height, width, 2, 2)
    b = np.dstack((b_1row, b_2row)).reshape(height, width, 2, 2)
    print(A.shape, b.shape, A[:1, :1, :, :])

    # a11 = A[..., 0, 0]
    # a12 = A[..., 0, 1]
    # a21 = A[..., 1, 0]
    # a22 = A[..., 1, 1]
    # A_det = a11 * a22 - a12 * a21
    # A_inv = np.dstack((a22, -a12, -a21, a11)) / A_det[..., None]
    # A_inv = A_inv.reshape(height, width, 2, 2)
    A_inv = np.linalg.inv(A)
    M = np.einsum("ijmk,ijkn->ijmn", A_inv, b)

    x = v.reshape(height, width, 1, 2) - p_star.reshape(height, width, 1, 2)
    y = np.einsum("ijmk,ijkn->ijmn", x, M) + q_star.reshape(height, width, 1, 2)

    flow = y.reshape(height, width, 2) - v

    print(flow.shape, flow.dtype)

    return flow

def load_flow_to_numpy(path):
    with open(path, 'rb') as f:
        magic = np.fromfile(f, np.float32, count=1)
        assert (202021.25 == magic), 'Magic number incorrect. Invalid .flo file'
        w = np.fromfile(f, np.int32, count=1)[0]
        h = np.fromfile(f, np.int32, count=1)[0]
        data = np.fromfile(f, np.float32, count=2 * w * h)
    data2D = np.reshape(data, (h, w, 2))
    # print(data2D[:10,:10,0])
    return data2D
def flow_to_image_torch(flow):
    flow = torch.from_numpy(np.transpose(flow, [2, 0, 1]).astype(np.float32))
    flow_im = flow_to_image(flow)
    img = np.transpose(flow_im.numpy(), [1, 2, 0])

    #print(img.shape)
    return img

"""
箭头图
"""
def draw_flow(im, flow, step=40, norm=1):
    # 在间隔分开的像素采样点处绘制光流
    h, w = im.shape[:2]
    y, x = np.mgrid[step/2:h:step, step/2:w:step].reshape(2, -1).astype(int)

    if norm:
        fx, fy = flow[y, x].T / flow[y, x].max() * step // 2.00001
    else:
        fx, fy = flow[y, x].T  # / flow[y, x].max() * step // 2
    # 创建线的终点
    lines = np.vstack([x, y, x+fx, y+fy]).T.reshape(-1, 2, 2)
    lines = np.int32(lines)
    # 创建图像并绘制
    vis = im  #cv2.cvtColor(im, cv2.COLOR_GRAY2BGR)
    for (x1, y1), (x2, y2) in lines:
      cv2.line(vis, (x1, y1), (x2, y2), (0, 255, 0), 2)
      cv2.circle(vis, (x1, y1), 2, (0, 0, 255), -1)
    return vis
if __name__ == "__main__":
    import os

    os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
    image = np.array(Image.open("images/toy.jpg"))
    #
    # flow = mls_affine()
    # c, h, w = flow.shape
    # flow = np.transpose(flow, (1, 2, 0))[..., ::-1]
    # out = flow_warp(image, image, flow)
    # plt.figure()
    # plt.imshow(np.hstack((image, out)))
    # plt.show()
    # print('dd')


    q = np.array([
        [155, 30], [155, 125], [155, 225],
        [235, 100], [235, 160], [295, 85], [293, 180]
    ])
    p = np.array([
        [211, 42], [155, 125], [100, 235],
        [235, 80], [235, 140], [295, 85], [295, 180]
    ])
    q = q.reshape(-1, 2)[..., ::-1]
    p = p.reshape(-1, 2)[..., ::-1]

    h, w, c = image.shape
    hh = range(h)
    ww = range(w)
    xx, yy = np.meshgrid(ww, hh)

    flow = mls_affine_my(image, p, q)




    flow_im = flow_to_image_torch(flow)
    flow_im2 = draw_flow(image, flow, step=20, norm=1)
    plt.figure()
    plt.subplot(121)
    plt.imshow(flow_im)
    plt.subplot(122)
    plt.imshow(flow_im2)
    plt.show()

    xy = np.dstack((xx, yy)).astype(np.float32)
    newxy = xy + flow
    out = flow_warp(image, image, newxy)
    plt.figure()
    plt.imshow(np.hstack((image, out)))
    plt.show()

    plt.figure()
    xx = xx[::20, ::20]
    yy = yy[::20, ::20]
    plot_grid(xx, yy, color="lightgrey")

    newxy = xy - flow
    xx = newxy[..., 0]
    yy = newxy[..., 1]
    xx = xx[::20, ::20]
    yy = yy[::20, ::20]
    plot_grid(xx, yy, color="C0")
    plt.show()

    # aug2 = np.ones_like(image)
    # aug2[yy, xx] = image[tuple(flow[..., ::-1])]
    # plt.figure()
    # plt.imshow(np.hstack((image, aug2)))
    # plt.show()

    # 我的版本 和 他不一样?
    xx, yy = np.meshgrid(range(5), range(5))
    p1 = np.array([[1, 1], [3, 0.9], [3, 1.1], [3, 1], [3.1, 1], [2.9, 1], [3,1], [3,1], [3,1]])
    p2 = np.array([[1, 1], [4, 0.9], [4, 1.1], [4, 1], [4.1, 1], [3.9, 1], [4,1], [4,1], [4,1]]) # 0.5

    # p1 = np.array([[1, 1], [3, 0.9], [3, 1.1], [3, 1]])
    # p2 = np.array([[1, 1], [4, 0.9], [4, 1.1], [4, 1]]) # 0.5

    # p1 = np.array([[1, 1], [3, 0.9], [3, 1.1]]) # 0.5
    # p2 = np.array([[1, 1], [4, 0.9], [4, 1.1]])

    # p1 = np.array([[1, 1], [3.0, 0.9]])
    # p2 = np.array([[1, 1], [4.0, 1.1]])  # -1.04504478
    flow = mls_affine_my(xx[..., None], p1, p2)

    print(flow[1, 2, 0], flow[..., 0])
    flow = mls_affine_deformation(xx, yy, p2[...,::-1], p1[...,::-1])# 2,h,w        (r,c)
    print(flow.shape)
    flow = np.transpose(flow, (1,2,0))[..., ::-1] - np.dstack((xx, yy))
    print('ss2:', flow[1, 2, 0], flow[..., 0])

正确性待验证,包括仓库里的代码正确性也不保证。

  1. 关于weight 是否有更好的方式,来应对其他应用

    更好的weight计算方法,比如考虑图像内容差异。双边weight等。

  2. 就是一些特殊情况,边界情况,求逆有问题的情况等需要考虑

  3. 最好阅读原文Image Deformation Using Moving Least Squares,其他一些blog也可以参考

    https://blog.csdn.net/u011426016/article/details/125243631
    https://blog.csdn.net/DIAJEY/article/details/114322764

  4. 可以用在曲面拟合上, 3Dlut拟合, 光流图,深度图拟合优化等
    比如光流:

    import numpy as np
import scipy.optimize
import torch
from scipy import sparse
from matplotlib import pyplot as plt
from scipy.optimize import minimize
from scipy.sparse import csc_matrix
from torchvision.utils import flow_to_image
from tqdm import tqdm

from movelq import mls_affine_deformation
def generate_data(pic=False):

    s = np.random.uniform(0, 1, [24, 2])
    t = np.random.uniform(0, 1, [24])
    print(s)
    print(t, t* np.arange(24))
    t = t* np.arange(24)

    monotonic_e = False
    if monotonic_e:
        s = np.sort(s, axis=0)
        t = np.sort(t, axis=0)
        t[:6] = t[6:12][::-1]
    # 拟合spline
    z1 = np.polyfit(s[..., 0], t, 4)
    p1 = np.poly1d(z1)

    z2 = np.polyfit(s[..., 1], t, 4)
    p2 = np.poly1d(z2)

    xx = np.linspace(0, 1, 1000)
    z1 = p1(xx)
    z2 = p2(xx)

    if pic:
        # 画散点图
        fig = plt.figure()
        ax = fig.gca(projection='3d')
        ax.scatter(s[..., 0], s[..., 1], t, label="random points")

        ax.plot(xx, np.zeros_like(xx), z1, label=' x spline')
        ax.plot(np.zeros_like(xx), xx, z2, label=' y spline')

        ax.set_xlabel('X label')  # 画出坐标轴
        ax.set_ylabel('Y label')
        ax.set_zlabel('Z label')
        ax.legend()
        plt.show()

    # merge spline
    h = xx
    w = xx
    ww, hh = np.meshgrid(w, h)

    z = p1(ww) + p2(hh)

    z = 100 * (z - z.min()) / z.max()
    if pic:
        # 画散点图
        fig = plt.figure()
        ax = fig.gca(projection='3d')
        ax.scatter(s[..., 0], s[..., 1], t, label="random points")

        ax.plot(xx, np.zeros_like(xx), z1 , label=' x spline')
        ax.plot(np.zeros_like(xx), xx, z2 , label=' y spline')

        ax.plot_surface(ww, hh, z, cmap='rainbow')
        ax.set_xlabel('X label')  # 画出坐标轴
        ax.set_ylabel('Y label')
        ax.set_zlabel('Z label')
        ax.legend()
        plt.show()
    return ww, hh, z

def flow_to_image_torch(flow):
    flow = torch.from_numpy(np.transpose(flow, [2, 0, 1]).astype(np.float32))
    flow_im = flow_to_image(flow)
    img = np.transpose(flow_im.numpy(), [1, 2, 0])

    #print(img.shape)
    return img

def generate_flow():
    def load_flow_to_numpy(path):
        with open(path, 'rb') as f:
            magic = np.fromfile(f, np.float32, count=1)
            assert (202021.25 == magic), 'Magic number incorrect. Invalid .flo file'
            w = np.fromfile(f, np.int32, count=1)[0]
            h = np.fromfile(f, np.int32, count=1)[0]
            data = np.fromfile(f, np.float32, count=2 * w * h)
        data2D = np.reshape(data, (h, w, 2))
        # print(data2D[:10,:10,0])
        return data2D
    file = r'C:\Users\rp\source\repos\dis_flow\dis_flow\frame_0001.flo'
    flow_gt = load_flow_to_numpy(file)

    return flow_gt
if __name__ == "__main__":
    import os

    os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
    flow_gt = generate_flow()
    print(flow_gt.shape, flow_gt.dtype, flow_gt.min(), flow_gt.max())
    flow_gt_im = flow_to_image_torch(flow_gt)
    plt.figure()
    plt.imshow(flow_gt_im)
    #plt.show()

    # 计算 match point
    h, w, c = flow_gt.shape
    hh = np.arange(0, h)
    ww = np.arange(0, w)
    xx, yy = np.meshgrid(ww, hh)

    tx = xx + flow_gt[..., 0]
    ty = yy + flow_gt[..., 1]
    pp = np.hstack((yy.reshape(-1, 1), xx.reshape(-1, 1)))
    qq = np.hstack((ty.reshape(-1, 1), tx.reshape(-1, 1)))
    print(pp[100:105, :], qq[100:105, :])
    train_index = np.random.randint(0, len(pp), 2127)
    p = pp[train_index]
    q = qq[train_index]

    ret = mls_affine_deformation(xx, yy, p, q, alpha=1.0, eps=1e-8) # 2, h, w
    ret = ret.transpose(1, 2, 0)     # h, w, 2.  先r后c

    flow = np.dstack((yy, xx)) - ret
    flow = flow[..., ::-1]
    print('dd', flow_gt[100:105,100:105, 0], flow[100:105,100:105, 0])
    print(flow_gt[100:105, 100:105, 1], flow[100:105, 100:105, 1])
    pic = 1
    if pic:
        # 画散点图
        fig = plt.figure()
        ax1 = fig.gca(projection='3d')
        ax1.scatter(p[..., 0], p[..., 1], q[..., 0]-p[..., 0], )
        ax1.scatter(p[..., 0], p[..., 1], q[..., 1]-p[..., 1], )

        z = ret.reshape(-1, 2)[train_index]
        ax2 = fig.gca(projection='3d')
        ax2.scatter(p[..., 0], p[..., 1], p[..., 0] - z[..., 0], marker='+', c='r')
        ax2.scatter(p[..., 0], p[..., 1], p[..., 1] - z[..., 1], marker='+', c='k')

        plt.show()


    flow_im = flow_to_image_torch(flow.astype(np.float32))
    plt.figure()
    plt.imshow(flow_im)
    plt.show()

相关文章:

  • 【Spring6】| Spring IoC注解式开发
  • 数据库+加密算法参考材料-2023.3.29
  • fastp软件介绍
  • 别再光靠工资过日子,外国程序员教你如何通过副业赚钱
  • 海心沙元宇宙音乐会虚拟主持人玩法再升级,虚拟动力技术全程助力
  • spark通过connector的方式读写starrocks
  • python实战应用讲解-【numpy专题篇】实用小技巧(六)(附python示例代码)
  • chatGPT陪你读源码
  • 37了解高可用技术方案,如冗余、容灾
  • 细思极恐,第三方跟踪器正在获取你的数据,如何防范?
  • 如何同时处理多个聊天
  • 一些idea操作
  • 【Java 并发编程】一文读懂线程、协程、守护线程
  • C++/MFC工程[4]——绘制直线段
  • 人民大学与加拿大女王大学金融硕士——你终究会成为你想成为的人
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 「面试题」如何实现一个圣杯布局?
  • AWS实战 - 利用IAM对S3做访问控制
  • css系列之关于字体的事
  • Java超时控制的实现
  • java第三方包学习之lombok
  • java概述
  • JS 面试题总结
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • MYSQL 的 IF 函数
  • node-glob通配符
  • Python十分钟制作属于你自己的个性logo
  • springMvc学习笔记(2)
  • Spring框架之我见(三)——IOC、AOP
  • 从零开始在ubuntu上搭建node开发环境
  • 关于使用markdown的方法(引自CSDN教程)
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 前端知识点整理(待续)
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 实习面试笔记
  • 实现简单的正则表达式引擎
  • 算法系列——算法入门之递归分而治之思想的实现
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 微服务核心架构梳理
  • puppet连载22:define用法
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • (arch)linux 转换文件编码格式
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第2节(共同的基类)
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (十八)SpringBoot之发送QQ邮件
  • (十三)Maven插件解析运行机制
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (算法二)滑动窗口
  • (五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置
  • (五)网络优化与超参数选择--九五小庞
  • (转)负载均衡,回话保持,cookie
  • * 论文笔记 【Wide Deep Learning for Recommender Systems】
  • *** 2003