def get_location_1(box_2d, dimension, rotation_x, rotation_y, rotation_z,
                   proj_matrix):
    """
    方法1 2Dbbox中心与3Dbbox中心重合
    只存在一个中心点间的对应关系。难以约束。
    若是将Z的值替换成真实值,效果还行。Z方向的值与XY相比差距太大。
    """
    R = get_R(rotation_x, rotation_y)

    # format 2d corners
    xmin = box_2d[0]
    ymin = box_2d[1]
    xmax = box_2d[2]
    ymax = box_2d[3]

    h, w, l = dimension[0], dimension[1], dimension[2]

    constraints = [0, -h / 2, 0]
    corners = [(xmin + xmax) / 2, (ymin + ymax) / 2]

    # create pre M (the term with I and the R*X)
    M = np.zeros([4, 4])

    for i in range(0, 4):
        M[i][i] = 1

    # create A, b
    A = np.zeros([2, 3], dtype=np.float)
    b = np.zeros([2, 1])

    RX = np.dot(R, constraints)
    M[:3, 3] = RX.reshape(3)

    M = np.dot(proj_matrix, M)

    A[0, :] = M[0, :3] - corners[0] * M[2, :3]  # [540 0 960] - 1116[0 0 1]
    b[0] = corners[0] * M[2, 3] - M[0, 3]

    A[1, :] = M[1, :3] - corners[1] * M[2, :3]  # [540 0 960] - 1116[0 0 1]
    b[1] = corners[1] * M[2, 3] - M[1, 3]

    loc, error, rank, s = np.linalg.lstsq(A, b, rcond=None)

    # loc = [loc[0][0], loc[1][0] + dimension[0] / 2, loc[2][0]]
    loc = [loc[0][0], loc[1][0], loc[2][0]]
    return loc
def get_location_2(box_2d, dimension, rotation_x, rotation_y, rotation_z,
                   proj_matrix):
    """
    2D框包含3D框作为约束条件
    """
    R = get_R(rotation_x, rotation_y, rotation_z)
    # format 2d corners
    xmin = box_2d[0]
    ymin = box_2d[1]
    xmax = box_2d[2]
    ymax = box_2d[3]

    # left top right bottom
    box_corners = [xmin, ymin, xmax, ymax]
    # get the point constraints
    constraints = []

    left_constraints = []
    right_constraints = []
    top_constraints = []
    bottom_constraints = []

    # using a different coord system ; 原数据集中第一个是height(车高度),第二个是width(车两侧的距离),第三个是length(车头到车尾)
    dx = dimension[2] / 2  # length
    dy = dimension[0] / 2  # height
    dz = dimension[1] / 2  # width

    left_mult = 1
    right_mult = -1

    switch_mult = -1  # -1

    for i in (-2, 0):
        left_constraints.append([left_mult * dx, i * dy, -switch_mult * dz])
    for i in (-2, 0):
        right_constraints.append([right_mult * dx, i * dy, switch_mult * dz])

    for i in (-1, 1):
        for j in (-1, 1):
            top_constraints.append([i * dx, -dy * 2, j * dz])
    for i in (-1, 1):
        for j in (-1, 1):
            bottom_constraints.append([i * dx, 0, j * dz])

    # now, 64 combinations
    for left in left_constraints:
        for top in top_constraints:
            for right in right_constraints:
                for bottom in bottom_constraints:
                    constraints.append([left, top, right, bottom])

    # filter out the ones with repeats
    constraints = filter(lambda x: len(x) == len(set(tuple(i) for i in x)),
                         constraints)

    # create pre M (the term with I and the R*X)
    pre_M = np.zeros([4, 4])
    # 1's down diagonal
    for i in range(0, 4):
        pre_M[i][i] = 1

    best_loc = None
    best_error = [1e09]
    best_X = None

    # loop through each possible constraint, hold on to the best guess
    # constraint will be 64 sets of 4 corners
    count = 0
    for constraint in constraints:
        # each corner
        Xa = constraint[0]
        Xb = constraint[1]
        Xc = constraint[2]
        Xd = constraint[3]

        X_array = [Xa, Xb, Xc, Xd]  # 4约束,对应上下左右 ,shape=4,3
        # M: all 1's down diagonal, and upper 3x1 is Rotation_matrix * [x, y, z]
        Ma = np.copy(pre_M)
        Mb = np.copy(pre_M)
        Mc = np.copy(pre_M)
        Md = np.copy(pre_M)

        M_array = [Ma, Mb, Mc, Md]  # 4个对角为1的4*4方阵

        # create A, b
        A = np.zeros([4, 3], dtype=np.float)
        b = np.zeros([4, 1])

        # 对于其中某个约束/上/下/左/右
        indicies = [0, 1, 0, 1]
        for row, index in enumerate(indicies):
            X = X_array[row]

            M = M_array[row]  # 一个对角是1的4*4方阵 .shape = 4*4

            # create M for corner Xx
            RX = np.dot(R, X)  # 某边对应的某点在相机坐标系下的坐标, 维度3 .shape = 3,1
            # 对角线是1,最后一列前三行分别是RX对应的相机坐标系下的长宽高 .shape = 4,4
            M[:3, 3] = RX.reshape(3)

            # 投影到二维平面的坐标(前三维).shape = 3,4,前三列是project矩阵,最后一列是二维平面的x,y,1
            M = np.dot(proj_matrix, M)

            A[row, :] = M[index, :3] - box_corners[row] * M[2, :3]
            b[row] = box_corners[row] * M[2, 3] - M[index, 3]

        # solve here with least squares, since over fit will get some error
        loc, error, rank, s = np.linalg.lstsq(A, b, rcond=None)

        # found a better estimation
        if error < best_error:
            count += 1  # for debugging
            best_loc = loc
            best_error = error
            best_X = X_array

    best_loc = [best_loc[0][0], best_loc[1][0], best_loc[2][0]]
    return best_loc
def get_location_6(box_2d, dimension, rotation_x, rotation_y, rotation_z,
                   proj_matrix):
    """
    2D框包含3D框作为约束条件。
    固定住坐标系,约束为64-30=34
    再考虑长宽置换的情况,最终约束为34*2=68
    不考虑000这种特殊情况
    2D框中心也是3D框的中心
    """
    R = get_R(rotation_x, rotation_y, rotation_z)
    # format 2d corners
    xmin = box_2d[0]
    ymin = box_2d[1]
    xmax = box_2d[2]
    ymax = box_2d[3]

    # left top right bottom
    box_corners = [xmin, ymin, xmax, ymax]
    # print('box_corners:',box_corners)
    # get the point constraints
    constraints = []

    left_constraints = []
    right_constraints = []
    top_constraints = []
    bottom_constraints = []

    left_constraints_2 = []
    right_constraints_2 = []
    top_constraints_2 = []
    bottom_constraints_2 = []

    # using a different coord system ; 原数据集中第一个是height(车高度),第二个是width(车两侧的距离),第三个是length(车头到车尾)
    dx = dimension[2] / 2  # length
    dy = dimension[0] / 2  # height
    dz = dimension[1] / 2  # width

    left_mult = -1
    right_mult = 1

    for j in (-1, 1):
        left_constraints.append([left_mult * dx, -2 * dy, j * dz])
    for j in (-2, 0):
        right_constraints.append([right_mult * dx, j * dy, -dz])
    left_constraints.append([left_mult * dx, 0, dz])
    # 考虑长宽的置换
    for j in (-1, 1):
        left_constraints_2.append([left_mult * dz, -2 * dy, j * dx])
    for j in (-2, 0):
        right_constraints.append([right_mult * dz, j * dy, -dx])
    left_constraints_2.append([left_mult * dz, 0, dx])

    # top and bottom are easy, just the top and bottom of car
    for i in (-1, 1):
        top_constraints.append([i * dx, -dy * 2, dz])
    for i in (-1, 1):
        bottom_constraints.append([i * dx, 0, -dz])
    # 考虑长宽的置换
    for i in (-1, 1):
        top_constraints_2.append([i * dz, -dy * 2, dx])
    for i in (-1, 1):
        bottom_constraints_2.append([i * dz, 0, -dx])

    # now, 64 combinations
    for left in left_constraints:
        for top in top_constraints:
            for right in right_constraints:
                for bottom in bottom_constraints:
                    constraints.append([left, top, right, bottom])

    for left in left_constraints_2:
        for top in top_constraints_2:
            for right in right_constraints_2:
                for bottom in bottom_constraints_2:
                    constraints.append([left, top, right, bottom])

    # filter out the ones with repeats
    constraints = filter(lambda x: len(x) == len(set(tuple(i) for i in x)),
                         constraints)
    # print(len(list(constraints)))

    # create pre M (the term with I and the R*X)
    pre_M = np.zeros([4, 4])
    # 1's down diagonal
    for i in range(0, 4):
        pre_M[i][i] = 1

    best_loc = None
    best_error = [1e09]
    best_X = None

    # 约束2 中心点
    constraints_center = [0, dy, 0]
    corners = [(xmin + xmax) / 2, (ymin + ymax) / 2]

    # loop through each possible constraint, hold on to the best guess
    # constraint will be 64 sets of 4 corners
    # 约束1
    count = 0
    for constraint in constraints:
        # print('constraint:',constraint)
        # each corner
        Xa = constraint[0]
        Xb = constraint[1]
        Xc = constraint[2]
        Xd = constraint[3]

        X_array = [Xa, Xb, Xc, Xd]  # 4约束,对应上下左右 ,shape=4,3
        # print('X_array:',X_array)
        # M: all 1's down diagonal, and upper 3x1 is Rotation_matrix * [x, y, z]
        Ma = np.copy(pre_M)
        Mb = np.copy(pre_M)
        Mc = np.copy(pre_M)
        Md = np.copy(pre_M)

        M_array = [Ma, Mb, Mc, Md]  # 4个对角为1的4*4方阵

        # create A, b
        A = np.zeros([6, 3], dtype=np.float)
        b = np.zeros([6, 1])

        # 对于其中某个约束/上/下/左/右
        indicies = [0, 1, 0, 1]
        for row, index in enumerate(indicies):
            X = X_array[row]
            # x_array is four constrains for up bottom left and right;
            # x is one point in world World coordinate system, .shape = 3
            M = M_array[row]  # 一个对角是1的4*4方阵 .shape = 4*4

            # create M for corner Xx
            RX = np.dot(R, X)  # 某边对应的某点在相机坐标系下的坐标, 维度3 .shape = 3,1
            # 对角线是1,最后一列前三行分别是RX对应的相机坐标系下的长宽高 .shape = 4,4
            M[:3, 3] = RX.reshape(3)

            # 投影到二维平面的坐标(前三维).shape = 3,4,前三列是project矩阵,最后一列是二维平面的x,y,1
            M = np.dot(proj_matrix, M)

            A[row, :] = M[index, :3] - box_corners[row] * M[2, :3]
            b[row] = box_corners[row] * M[2, 3] - M[index, 3]

        # 2D中心是3D的投影中心
        M_cer = np.zeros([4, 4])
        # 1's down diagonal
        for i in range(0, 4):
            M_cer[i][i] = 1

        RX_cer = np.dot(R, constraints_center)
        M_cer[:3, 3] = RX_cer.reshape(3)

        M_cer = np.dot(proj_matrix, M_cer)
        A[4, :] = M_cer[0, :3] - corners[0] * \
            M_cer[2, :3]  # [540 0 960] - 1116[0 0 1]
        b[4] = corners[0] * M_cer[2, 3] - M_cer[0, 3]

        A[5, :] = M_cer[1, :3] - corners[1] * \
            M_cer[2, :3]  # [540 0 960] - 1116[0 0 1]
        b[5] = corners[1] * M_cer[2, 3] - M_cer[1, 3]

        # solve here with least squares, since over fit will get some error
        loc, error, rank, s = np.linalg.lstsq(A, b, rcond=None)

        # found a better estimation
        if error < best_error:
            count += 1  # for debugging
            best_loc = loc
            best_error = error
            best_X = X_array

    best_loc = [best_loc[0][0], best_loc[1][0], best_loc[2][0]]
    return best_loc