def optimize_walls(walls_3d_line, manual_merge_pairs=None):
    '''
    XYXYSin2WZ0Z1
    '''
    wall_bottom = walls_3d_line[:,-2].min()
    walls_3d_line[:,-2] = wall_bottom

    bottom_corners = OBJ_REPS_PARSE.encode_obj(walls_3d_line, 'XYXYSin2WZ0Z1', 'Bottom_Corners').reshape(-1,3)
    #_show_3d_points_objs_ls([bottom_corners], objs_ls = [walls_3d_line],  obj_rep='XYXYSin2WZ0Z1')

    walls_2d_line = walls_3d_line[:,:5]

    #_show_3d_points_objs_ls(objs_ls=[walls_2d_line], obj_rep='RoLine2D_UpRight_xyxy_sin2a')
    walls_2d_line_new, _, valid_ids = GraphUtils.optimize_wall_graph(walls_2d_line, obj_rep_in='XYXYSin2', opt_graph_cor_dis_thr=0.15, min_out_length=0.22)
    valid_ids = valid_ids.reshape(-1)

    if manual_merge_pairs is not None:
      walls_2d_line_new = GraphUtils.opti_wall_manually(walls_2d_line_new, 'XYXYSin2', manual_merge_pairs)
    #_show_3d_points_objs_ls(objs_ls=[walls_2d_line_new], obj_rep='RoLine2D_UpRight_xyxy_sin2a')

    try:
      walls_3d_line_new = np.concatenate( [walls_2d_line_new, walls_3d_line[valid_ids][:,5:8]], axis=1 )
    except:
      import pdb; pdb.set_trace()  # XXX BREAKPOINT
      pass
    bottom_corners_new = OBJ_REPS_PARSE.encode_obj(walls_3d_line_new, 'XYXYSin2WZ0Z1', 'Bottom_Corners').reshape(-1,3)
    #_show_3d_points_objs_ls([bottom_corners_new], objs_ls = [walls_3d_line_new],  obj_rep='XYXYSin2WZ0Z1')
    return walls_3d_line_new
    pass
def transfer_lines(lines, obj_rep, img_shape, angle, offset):
  '''
  lines: [n,5]
  angle: clock-wise is positive
  offset: (2)
  '''
  scale = 1
  h, w = img_shape
  #assert h%2 == 0
  #assert w%2 == 0
  center = ((w - 0) * 0.5, (h - 0) * 0.5 )
  matrix = cv2.getRotationMatrix2D(center, -angle, scale)
  n = lines.shape[0]
  assert lines.shape[1] == 4
  assert obj_rep == 'RoLine2D_2p'

  #lines_2endpts = decode_line_rep(lines, obj_rep).reshape(n,2,2)
  lines_2endpts = OBJ_REPS_PARSE.encode_obj(lines, obj_rep, 'RoLine2D_2p').reshape(n,2,2)

  ones = np.ones([n,2,1], dtype=lines.dtype)
  tmp = np.concatenate([lines_2endpts, ones], axis=2).reshape([n*2, 3])
  lines_2pts_r = np.matmul( tmp, matrix.T ).reshape([n,2,2])
  lines_2pts_r[:,:,0] += offset[0]
  lines_2pts_r[:,:,1] += offset[1]
  lines_rotated = OBJ_REPS_PARSE.encode_obj(lines_2pts_r.reshape(n,4), 'RoLine2D_2p', obj_rep)
  return lines_rotated
def rotate_bboxes_img(bboxes, img, angle,  obj_rep):
  #angle = 30
  if obj_rep != 'XYXYSin2':
    XYXYSin2W = OBJ_REPS_PARSE.encode_obj(bboxes, obj_rep, 'XYXYSin2W')
    lines = XYXYSin2W[:,:5]
  else:
    lines = bboxes

  rotate_lines, new_img, scale = rotate_lines_img(lines, img, angle, 'XYXYSin2')
  if obj_rep == 'XYXYSin2':
    return rotate_lines, new_img

  width = XYXYSin2W[:,5:6] * scale
  r_XYXYSin2W = np.concatenate([ rotate_lines, width ], axis=1)
  if obj_rep == 'XYXYSin2W':
    return r_XYXYSin2W, new_img
  elif obj_rep == 'XYXYSin2WZ0Z1':
    XYXYSin2WZ0Z1 = np.concatenate([ r_XYXYSin2W, bboxes[:,[-2,-1]] ], axis=1)
    return XYXYSin2WZ0Z1, new_img
  elif obj_rep == 'XYZLgWsHA':
    zc, H = bboxes[:,2:3], bboxes[:,5:6]
    z0 = zc - H/2
    z1 = zc + H/2
    XYXYSin2WZ0Z1 = np.concatenate([ r_XYXYSin2W, z0, z1], axis=1)
  elif obj_rep == 'Rect4CornersZ0Z1':
    XYXYSin2WZ0Z1 = np.concatenate([ r_XYXYSin2W, bboxes[:,[-2,-1]] ], axis=1)
  else:
    raise NotImplementedError
  rotated_bboxes = OBJ_REPS_PARSE.encode_obj(XYXYSin2WZ0Z1, 'XYXYSin2WZ0Z1', obj_rep)
  rotated_bboxes = rotated_bboxes.astype(np.float32)
  show = 0
  if show:
    _show_objs_ls_points_ls( new_img[:,:,0], [rotated_bboxes], obj_rep=obj_rep )
  pass
  return rotated_bboxes, new_img
def clean_outer_false_walls_of_1_room(room, walls, obj_rep):
  from mmdet.core.bbox.geometry import dsiou_rotated_3d_bbox_np
  assert obj_rep == 'XYZLgWsHA'
  nw = walls.shape[0]
  cen_room = room[None, :2]
  w_lines = OBJ_REPS_PARSE.encode_obj(walls[:,:7], obj_rep, 'RoLine2D_2p').reshape(-1,2,2)
  valid_ids = []
  for i in range(nw):
    cen_i = walls[i:i+1, :2]
    box = np.concatenate([cen_i, cen_room], 1)
    box = OBJ_REPS_PARSE.encode_obj(box, 'RoLine2D_2p', obj_rep)
    box[:, 3:5] *= 0.95

    line_i = OBJ_REPS_PARSE.encode_obj(box, obj_rep, 'RoLine2D_2p').reshape(1,2,2)
    intsects = lines_intersection_2d( line_i, w_lines, True, True )
    valid_i = np.isnan(intsects).all()

    if valid_i:
      valid_ids.append( i )
    if not valid_i and 0:
      print(valid_i)
      print(intsects)
      _show_objs_ls_points_ls( (512,512), [walls[:,:7], walls[i:i+1,:7], box], obj_rep, obj_colors=['white', 'lime', 'red'] )
  #_show_objs_ls_points_ls( (512,512), [walls[:,:7], walls[valid_ids,:7], box], obj_rep, obj_colors=['white', 'lime', 'red'] )
  return valid_ids
def intersect_2edges_by_modification(walls0, obj_rep, corners_bad=None):
  '''
  corners_bad: if this is not None, this is the corners that should be fixed.
  '''
  assert walls0.shape[0] == 2
  #_show_objs_ls_points_ls( (512,512), [walls0], obj_rep, points_ls=[corners_bad] )
  w0, w1 = walls0[0], walls0[1]
  cor_0 = OBJ_REPS_PARSE.encode_obj(w0[None,:], obj_rep, 'RoLine2D_2p').reshape(2,2)
  cor_1 = OBJ_REPS_PARSE.encode_obj(w1[None,:], obj_rep, 'RoLine2D_2p').reshape(2,2)
  intersect = line_intersection_2d(cor_0, cor_1, min_angle=np.pi/8).reshape(1,2)
  cor_0_new = replace_1cor_of_edge_to_midify(cor_0, intersect).reshape(1,4)
  cor_1_new = replace_1cor_of_edge_to_midify(cor_1, intersect).reshape(1,4)
  if corners_bad is not None:
    dis_to_bad = np.linalg.norm( corners_bad - intersect, axis=1 )
    dis0 = np.linalg.norm( cor_0 - intersect, axis=1 )
    dis1 = np.linalg.norm( cor_1 - intersect, axis=1 )
    check0 =  abs(dis_to_bad[0] - dis0.min()) < 1
    check1 =  abs(dis_to_bad[1] - dis1.min()) < 1
    check = check0 * check1
    if not check:
      # The corners_bad should be replaced. But it is still here. Invalid
      # connection
      return None
  w_0_new = OBJ_REPS_PARSE.encode_obj(cor_0_new, 'RoLine2D_2p', obj_rep)[0]
  w_1_new = OBJ_REPS_PARSE.encode_obj(cor_1_new, 'RoLine2D_2p', obj_rep)[0]
  walls_new = np.concatenate([w_0_new[None], w_1_new[None]], 0)
  return walls_new
def transfer_lines_points(lines, obj_rep, points=None, center=(0,0), angle=0, offset=(0,0)):
  '''
  lines: [n,5]
  points: [m,2]
  angle: clock-wise is positive, degree
  offset: (2)
  '''
  assert lines.ndim == 2
  n = lines.shape[0]
  scale = 1
  angle *= 180/np.pi
  matrix = cv2.getRotationMatrix2D(center, -angle, scale)

  lines_2endpts = OBJ_REPS_PARSE.encode_obj(lines, obj_rep, 'RoLine2D_2p').reshape(n,2,2)

  ones = np.ones([n,2,1], dtype=lines.dtype)
  tmp = np.concatenate([lines_2endpts, ones], axis=2).reshape([n*2, 3])
  lines_2pts_r = np.matmul( tmp, matrix.T ).reshape([n,2,2])
  lines_2pts_r[:,:,0] += offset[0]
  lines_2pts_r[:,:,1] += offset[1]
  lines_rotated = OBJ_REPS_PARSE.encode_obj(lines_2pts_r.reshape(n,4), 'RoLine2D_2p', obj_rep)
  if obj_rep == 'XYLgWsA':
    lines_rotated[:,3] = lines[:,3]
  if obj_rep == 'XYZLgWsHA':
    lines_rotated[:,[2,4,5]] = lines[:,[2,4,5]]

  if points is not None:
    assert points.ndim == 2
    m,pc = points.shape
    ones = np.ones([m,1], dtype=lines.dtype)
    tmp = np.concatenate([points, ones], axis=1).reshape([m, pc+1])
    points_r = np.matmul( tmp, matrix.T ).reshape([m,pc])
  else:
    points_r = None
  return lines_rotated, points_r
def manual_rm_objs(bboxes0, obj_rep, all_colors, max_size=7):
  print(bboxes0[:,3] )
  bboxes1 = OBJ_REPS_PARSE.encode_obj(bboxes0, obj_rep, 'XYZLgWsHA')
  #_show_3d_bboxes_ids(bboxes0, obj_rep)
  mask1 = bboxes1[:,3] < max_size
  angle_dif = np.abs(limit_period_np(bboxes1[:,6], 0.5, np.pi/2))
  mask2 = angle_dif < 0.3
  mask = mask1 * mask2
  bboxes2 = bboxes1[mask]
  bboxes_out = OBJ_REPS_PARSE.encode_obj(bboxes2, 'XYZLgWsHA', obj_rep)
  all_colors = [all_colors[i] for i in range(len(mask)) if mask[i]]
  return bboxes_out, all_colors
def move_axis_aligned_box_to_wall(box2d, walls, cat_name, voxel_size):
  assert box2d.shape == (1,5)
  assert walls.shape[1] == 8
  box2d0 = box2d.copy()

  max_thick = MAX_THICK_MAP[cat_name] / voxel_size
  thick_add_on_wall = int(THICK_GREATER_THAN_WALL[cat_name] / voxel_size)
  n = walls.shape[0]

  center = np.array(box2d[0,:2])
  wall_lines = OBJ_REPS_PARSE.encode_obj( walls, 'XYXYSin2WZ0Z1', 'RoLine2D_2p' ).reshape(-1,2,2)
  walls_ = OBJ_REPS_PARSE.encode_obj(walls, 'XYXYSin2WZ0Z1', 'XYLgWsA')
  diss = vertical_dis_1point_lines(center, wall_lines, no_extend=False)
  angles_dif = walls_[:,-1] - box2d[:,-1]
  angles_dif = limit_period_np(angles_dif, 0.5, np.pi)
  invalid_mask = np.abs(angles_dif) > np.pi/4
  diss[invalid_mask]  = 1000
  diss *= voxel_size
  if diss.min() > 0.3:
    return box2d
  the_wall_id = diss.argmin()
  the_wall = walls_[the_wall_id]

  thick_add_on_wall = int(THICK_GREATER_THAN_WALL[cat_name] / voxel_size)
  new_thick = min(the_wall[3] + thick_add_on_wall, max_thick)
  new_thick = max(new_thick, max_thick*0.7)
  box2d[0,3] = new_thick
  angle_dif = limit_period_np( the_wall[-1] - box2d[0,-1], 0.5, np.pi )

  if abs(box2d[0,-1]) < np.pi/4:
    # long axis is x, move y
    move_axis = 1
  else:
    move_axis = 0

  # if the center of box2d is not inside the wall, do not move
  j = 1- move_axis
  inside_wall = box2d0[0,j] < the_wall[j]+the_wall[2]/2 and box2d0[0,j] > the_wall[j]-the_wall[2]/2
  if inside_wall:
    move0 = the_wall[move_axis] - box2d0[0,move_axis]
    if abs(move0 * voxel_size) < 0.1:
      move = move0
    else:
      move = abs(new_thick - box2d0[0,3]) * np.sign(move0) / 2
    box2d[0,move_axis] += move
    print(f'move:{move}, move0:{move0}')
    #_show_3d_points_objs_ls( objs_ls=[ box2d0, box2d, the_wall[None]], obj_rep='XYLgWsA', obj_colors=['blue', 'red', 'black'])
    #_show_3d_points_objs_ls( objs_ls=[ box2d0, the_wall[None]], obj_rep='XYLgWsA', obj_colors=[ 'blue', 'black'])
    #_show_3d_points_objs_ls( objs_ls=[ box2d, the_wall[None]], obj_rep='XYLgWsA', obj_colors=[ 'red', 'black'])
    pass
  return box2d
def intersect_2edges_by_add_new_wall(walls0, obj_rep, corners_bad=None):
  '''
  corners_bad: if this is not None, this is the corners that should be fixed.
  '''
  assert walls0.shape[0] == 2
  #_show_objs_ls_points_ls( (512,512), [walls0], obj_rep, points_ls=[corners_bad] )
  w0, w1 = walls0[0], walls0[1]
  cor_0 = OBJ_REPS_PARSE.encode_obj(w0[None,:], obj_rep, 'RoLine2D_2p').reshape(2,2)
  cor_1 = OBJ_REPS_PARSE.encode_obj(w1[None,:], obj_rep, 'RoLine2D_2p').reshape(2,2)
  intersect = line_intersection_2d(cor_0, cor_1, min_angle=np.pi/8).reshape(1,2)
  intersect = np.repeat( intersect, 2, 0 )
  new_walls = np.concatenate( [intersect, corners_bad], 1 )
  new_walls = OBJ_REPS_PARSE.encode_obj(new_walls, 'RoLine2D_2p', obj_rep)
  return new_walls
Exemple #10
0
def draw_corners_to_box( point_thickness=25,
                         line_thickness=4,
                        box_thickness = 4):
  corners = np.array( [
    [100, 100],
    [800, 300],
    [900, 500],
    [600, 800],
  ] )
  corners = sort_four_corners_np(corners[None,:,:])[0].reshape(-1,2)
  center = corners.mean(0,keepdims=True)
  box_XYDAsinAsinSin2 = four_corners_to_box_np(corners[None,:,:])
  box = OBJ_REPS_PARSE.encode_obj(box_XYDAsinAsinSin2, 'XYDAsinAsinSin2', 'XYLgWsA')

  tmp = np.repeat( center, 4, 0)
  mid_points = ( corners + corners[[1,2,3,0],:] ) /2
  mid_lines = np.concatenate([mid_points[:,None,:], tmp[:,None,:]], 1)

  lines = np.concatenate([corners[:,None,:], tmp[:,None,:]], 1)


  h,w = 1024, 1024
  img = np.zeros([h,w,3], dtype=np.uint8) + 255
  img = _draw_points(img, corners, 'red', point_thickness)
  img = _draw_points(img, center, 'blue', point_thickness)
  img = _draw_points(img, mid_points, 'green', point_thickness)
  img = _draw_lines(img, lines, 'red', line_thickness)
  img = _draw_lines(img, mid_lines, 'blue', line_thickness)
  img = draw_XYLgWsA(img, box, 'black', box_thickness)


  img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  cv2.imshow('', img)
  cv2.waitKey(0)
  cv2.destroyAllWindows()
Exemple #11
0
def _make_bbox_line_mesh(bbox, box_oriented, color):
    assert box_oriented
    assert bbox.shape == (7, )
    radius = BOX_LINE_RADIUS
    #radius = bbox[3:6].max()/200

    lines = OBJ_REPS_PARSE.get_12_line_cors(bbox.reshape(1, 7),
                                            'XYZLgWsHA')[0]  # [12,2,3]
    centroids = lines.mean(1)
    directions = lines[:, 1, :] - lines[:, 0, :]
    heights = np.linalg.norm(directions, axis=1)
    heights = np.clip(heights, a_min=0.001, a_max=None)
    directions = directions / heights.reshape([-1, 1])
    mesh = []
    for i in range(12):
        cylinder_i = o3d.geometry.TriangleMesh.create_cylinder(
            radius=radius, height=heights[i])
        cylinder_i.paint_uniform_color(color)
        transformation = np.identity(4)
        transformation[:3, 3] = centroids[i]
        transformation[:3, 2] = directions[i]
        cylinder_i.transform(transformation)
        mesh.append(cylinder_i)

    cm = mesh[0]
    for i in range(1, 12):
        cm += mesh[i]
    return cm
Exemple #12
0
def draw_objs(img,
              objs,
              obj_rep,
              color,
              obj_thickness=1,
              scores=None,
              draw_rooms=False,
              cats=None,
              font_scale=FONT_SCALE,
              text_color='green',
              dash=False):
    if obj_rep != 'XYLgWsA':
        objs = OBJ_REPS_PARSE.encode_obj(objs, obj_rep, 'XYLgWsA')
    if draw_rooms:
        img = draw_rooms_from_walls(img.shape[:2], objs, 'XYLgWsA')
    draw_XYLgWsA(img,
                 objs,
                 color,
                 obj_thickness=obj_thickness,
                 scores=scores,
                 cats=cats,
                 font_scale=font_scale,
                 text_color=text_color,
                 dash=dash)
    return img
def m_transform_lines(lines, matrix, obj_rep):
  '''
  lines:  [n,5]
  matrix: [4,4]
  '''
  assert matrix.shape == (4,4)
  assert lines.shape[1] == 5
  assert obj_rep == 'XYXYSin2'
  n = lines.shape[0]
  lines_2endpts = OBJ_REPS_PARSE.encode_obj(lines, obj_rep, 'RoLine2D_2p').reshape(n,2,2)

  ones = np.ones([n,2,2], dtype=lines.dtype)
  tmp = np.concatenate([lines_2endpts, ones], axis=2).reshape([n*2, 4])
  lines_2pts_r = (tmp @ matrix.T)[:,:2].reshape([n,2,2])
  lines_rotated = OBJ_REPS_PARSE.encode_obj(lines_2pts_r.reshape(n,4), 'RoLine2D_2p', obj_rep)
  return lines_rotated.astype(np.float32)
    def show_gt_bboxes_1scene_bev(self, index):
        img_info = self.img_infos[index]
        print('\n\n', img_info['filename'])
        ann = img_info['ann']
        gt_bboxes_3d_raw = ann['bboxes_XYXYSin2WZ0Z1']
        gt_bboxes = ann['gt_bboxes']
        gt_labels = ann['labels']

        rm_cats = ['ceiling']
        #rm_cats = ['beam']
        kp_cats = ['wall', 'beam', 'column', 'door', 'window']

        # 2d
        gt_corners = OBJ_REPS_PARSE.encode_obj(gt_bboxes, self.obj_rep,
                                               'RoLine2D_2p')
        gt_corners, _ = filter_categories('keep', gt_corners, gt_labels,
                                          kp_cats, self._category_ids_map)
        gt_corners = gt_corners.reshape(-1, 2)
        w, h = gt_corners.max(0).astype(np.int) + 10
        gt_bboxes, gt_labels = filter_categories('keep', gt_bboxes, gt_labels,
                                                 kp_cats,
                                                 self._category_ids_map)
        obj_cats = np.array(kp_cats)[gt_labels]
        _show_objs_ls_points_ls((h, w), [gt_bboxes],
                                self.obj_rep,
                                points_ls=[gt_corners],
                                obj_scores_ls=[obj_cats])
def getOrientedLineRectSubPix(img, line, obj_rep, length_aug=-5, thickness_aug=40):
  '''
  img: [h,w] [h,w,1/3]
  line: [5]
  '''
  debug  = 0
  assert line.shape == (5,)
  assert img.shape[:2] == (512,512)
  if debug:
    img = _draw_lines_ls_points_ls(img, [line.reshape(-1,5)])
  h, w = img.shape[:2]

  #angle = line[-1]
  #line = decode_line_rep(line[None, :], obj_rep)[0]
  line = OBJ_REPS_PARSE.encode_obj(line[None,:], obj_rep, 'RoLine2D_2p').reshape(-1,2,2)[0]
  points = line[:4].reshape(2,2)
  x, y = points.mean(axis=0).astype(np.int)

  # move to center first
  xofs, yofs = w/2-x, h/2-y
  M_mc = np.array([[1,0, xofs], [0,1,yofs]])

  dir_v = points[1] - points[0]
  angle = angle_with_x_np( dir_v.reshape(1,2), 1 )[0]
  angle = -angle * 180 / np.pi

  M = cv2.getRotationMatrix2D( (w/2,h/2), angle, 1 )
  img_1 = cv2.warpAffine(img, M_mc, (w,h))
  img_rot = cv2.warpAffine(img_1, M, (w,h))
  tmp = np.concatenate([points, np.ones([2,1])], axis=1)
  points_1 = tmp @ M_mc.T
  tmp = np.concatenate([points_1, np.ones([2,1])], axis=1)
  points_rot = tmp @ M.T

  x,y = points_rot.mean(axis=0)
  center = (x,y)
  length = np.linalg.norm(points_rot[1] - points_rot[0]) + length_aug
  length = max(length, 5)
  thickness = thickness_aug
  size = (int(length), int(thickness))

  roi = cv2.getRectSubPix(img_rot, size, center)

  if debug:

    print(angle)
    _show_lines_ls_points_ls(img, points_ls=[points])
    _show_lines_ls_points_ls(img_rot, points_ls=[points_rot])
    _show_lines_ls_points_ls(roi)
    pass
  return roi
def fulfil_a_rectangle_room(corners_sorted, walls, room, obj_rep, show_fix_process_per_room=0):
  '''
  There are only two walls for one room. Add these two walls are connected.
  Add one extra corner and two extra walls to fulfil a rectangle.
  '''
  cors = corners_sorted
  cor3 = cors[0] - cors[1] + cors[2]
  tmp = np.repeat(cor3[None], 2, 0)
  wall_cors_new = np.concatenate([tmp, cors[[0,2]]], 1).reshape(2,4)
  walls_new = OBJ_REPS_PARSE.encode_obj(wall_cors_new, 'RoLine2D_2p', obj_rep)
  walls_new = np.concatenate([walls_new, walls[:,7:8]], 1)
  if show_fix_process_per_room:
    _show_objs_ls_points_ls( (512,512), [ walls[:,:7], room[None,:7], walls_new[:,:7] ], obj_rep, obj_colors=['red', 'white', 'lime'])
  return walls, walls_new
Exemple #17
0
def nms_rotated(dets,
                obj_rep,
                iou_thr,
                min_width_length_ratio=0.3,
                device_id=None):
    from detectron2 import _C
    if isinstance(dets, torch.Tensor):
        is_numpy = False
        dets_th = dets
    elif isinstance(dets, np.ndarray):
        is_numpy = True
        device = 'cpu' if device_id is None else 'cuda:{}'.format(device_id)
        dets_th = torch.from_numpy(dets).to(device)
    else:
        raise TypeError(
            'dets must be either a Tensor or numpy array, but got {}'.format(
                type(dets)))

    obj_dim = OBJ_REPS_PARSE._obj_dims[obj_rep]
    assert dets.shape[1] >= obj_dim + 1
    # execute cpu or cuda nms
    if dets_th.shape[0] == 0:
        inds = dets_th.new_zeros(0, dtype=torch.long)
    else:
        # patrse obj_rep to XYZHWA
        scores = dets_th[:, -1].clone()
        dets_th = OBJ_REPS_PARSE.encode_obj(dets_th[:, :obj_dim], obj_rep,
                                            'XYLgWsA')
        dets_th[:, 3] = torch.max(dets_th[:, 3],
                                  dets_th[:, 2] * min_width_length_ratio)
        #_show_objs_ls_points_ls_torch( (512,512), [dets_th[:,:obj_dim]], 'XYLgWsA' )
        dets_th[:, 4] *= -180 / np.pi

        inds = _C.nms_rotated(dets_th, scores, iou_thr)

    if is_numpy:
        inds = inds.cpu().numpy()

    if DEBUG_CFG.SHOW_NMS_PROCESS:
        n0 = scores.shape[0]
        n1 = inds.shape[0]
        print(f'\n\n{n0} -> {n1}')
        _show_objs_ls_points_ls_torch((512, 512), [dets[:, :obj_dim]], obj_rep)
        _show_objs_ls_points_ls_torch((512, 512), [dets[inds][:, :obj_dim]],
                                      obj_rep)
        import pdb
        pdb.set_trace()  # XXX BREAKPOINT

    return dets[inds, :], inds
def rm_one_wall_for_vis(gt_bboxes_3d_raw, gt_labels, scene_name):
  mask = gt_labels == 0
  walls = gt_bboxes_3d_raw[mask]
  walls = OBJ_REPS_PARSE.encode_obj(walls, 'XYXYSin2WZ0Z1', 'XYZLgWsHA')
  max_xy = walls[:,:2].max(0)
  min_xy = walls[:,:2].min(0)
  if scene_name == 'Area_3/office_4':
    del_axis=0
    #i = np.where( walls[:,del_axis] == max_xy[del_axis] )[0]
    i = np.where( walls[:,del_axis] == min_xy[del_axis] )[0]
  else:
    return gt_bboxes_3d_raw, gt_labels
  gt_bboxes_3d_raw = np.delete(gt_bboxes_3d_raw, i, 0)
  gt_labels = np.delete(gt_labels, i, 0)
  return gt_bboxes_3d_raw, gt_labels
Exemple #19
0
def test_rotation_order():
    u = np.pi / 180
    XYLgWsA = np.array([
        [200, 200, 200, 10, 0],
        [200, 200, 200, 30, 30 * u],
    ])
    obj_rep = 'XYLgWsA'
    img = np.zeros([512, 512, 3], dtype=np.uint8)
    #img = draw_XYLgWsA( img, XYLgWsA, 'red')
    #mmcv.imshow(img)

    corners = OBJ_REPS_PARSE.encode_obj(XYLgWsA, 'XYLgWsA',
                                        'RoLine2D_2p').reshape(-1, 2)
    XYZLgWsHA = OBJ_REPS_PARSE.encode_obj(XYLgWsA, 'XYLgWsA', 'XYZLgWsHA')
    XYZLgWsHA[:, 5] = 10
    corners_3d = OBJ_REPS_PARSE.encode_obj(XYZLgWsHA, 'XYZLgWsHA',
                                           'Bottom_Corners').reshape(-1, 3)

    #_show_objs_ls_points_ls( (512,512), [XYLgWsA], obj_rep, points_ls=[corners])
    _show_3d_points_objs_ls([corners_3d],
                            objs_ls=[XYZLgWsHA],
                            obj_rep='XYZLgWsHA')

    pass
Exemple #20
0
def _show_3d_points_objs_ls(points_ls=None,
                            point_feats=None,
                            objs_ls=None,
                            obj_rep=None,
                            obj_colors='random',
                            box_types=None,
                            polygons_ls=None,
                            polygon_colors='random'):
    if objs_ls is not None:
        if obj_rep == 'XYXYSin2':
            if points_ls is not None:
                for i in range(len(points_ls)):
                    if points_ls[i].shape[1] == 2:
                        n = points_ls[i].shape[0]
                        z = np.zeros([n, 1])
                        points_ls[i] = np.concatenate([points_ls[i], z],
                                                      axis=1)

            if objs_ls is not None:
                for i in range(len(objs_ls)):
                    n = objs_ls[i].shape[0]
                    tzz = np.ones([n, 3])
                    tzz[:, 0] = 0.01
                    tzz[:, 1] = 0
                    tzz[:, 2] = 0.01
                    objs_ls[i] = np.concatenate([objs_ls[i], tzz], axis=1)
            obj_rep = 'XYXYSin2WZ0Z1'
        bboxes_ls = [
            OBJ_REPS_PARSE.encode_obj(o, obj_rep, 'XYZLgWsHA') for o in objs_ls
        ]
    else:
        bboxes_ls = None
    mesh_ls = _show_3d_points_bboxes_ls(points_ls,
                                        point_feats,
                                        bboxes_ls,
                                        obj_colors,
                                        box_oriented=True,
                                        box_types=box_types)

    if polygons_ls is not None:
        pls = _make_polygon_surface_ls(polygons_ls, polygon_colors)
        mesh_ls += pls

    #o3d.visualization.draw_geometries( show_ls )
    custom_draw_geometry_with_key_callback(mesh_ls)
Exemple #21
0
def draw_1_obj_dash(img, obj, color, obj_thickness, obj_rep):
    assert obj_rep == 'XYLgWsA'
    len_unit = 6
    gap_unit = 8
    corners = OBJ_REPS_PARSE.encode_obj(obj[None], obj_rep,
                                        'RoLine2D_2p').reshape(2, 2)
    length = obj[2]
    n = length / (len_unit + gap_unit)
    n = int(np.floor(n))
    n = max(n, 2)
    objs_dash = np.repeat(obj[None], n, 0)
    objs_dash[:, 2] = len_unit
    for i in range(n):
        r = (i + 1) / n
        center = corners[0] * r + corners[1] * (1 - r)
        objs_dash[i, :2] = center
        draw_1_obj(img, objs_dash[i], color, obj_thickness, obj_rep)
    pass
def lines2d_to_bboxes3d(lines, line_obj_rep='lscope_istopleft', height=60, thickness=1):
  '''
  lines:  [n,5]
  bboxes: [n,9] [center, size, angle]
  '''
  import open3d as o3d
  from  beike_data_utils.geometric_utils import angle_with_x_np
  assert line_obj_rep == 'lscope_istopleft'
  assert lines.ndim == 2
  assert lines.shape[1] == 5

  n = lines.shape[0]
  #lines_std = decode_line_rep(lines, line_obj_rep).reshape(n,2,2)
  lines_std = OBJ_REPS_PARSE.encode_obj(lines, obj_rep, 'RoLine2D_2p').reshape(n,2,2)
  center2d = lines_std.mean(axis=1)
  vec_rotation = lines_std[:,0] - center2d
  z_angles = -angle_with_x_np(vec_rotation, scope_id=0)

  length = np.linalg.norm( lines_std[:,1] - lines_std[:,0] , axis=1)

  center = np.zeros([lines.shape[0], 3], dtype=lines.dtype)
  center[:,:2] = center2d
  center[:,2] = height/2
  extent = np.zeros([lines.shape[0], 3], dtype=lines.dtype)
  extent[:,0] = length
  extent[:,1] = thickness
  extent[:,2] = height
  angles = np.zeros([lines.shape[0], 3], dtype=lines.dtype)
  angles[:,2] = z_angles

  bboxes3d = np.concatenate([center, extent, angles], axis=1)
  #_show_3d_points_bboxes_ls(bboxes_ls = [bboxes3d], box_oriented=True)
  return bboxes3d

  matrixes = []
  for a in theta:
    axis_angle = np.array([0,0,a]).reshape([3,1])
    matrix = o3d.geometry.get_rotation_matrix_from_yxz(axis_angle)
    matrixes.append( matrix )
  matrixes = np.array(matrixes)
  import pdb; pdb.set_trace()  # XXX BREAKPOINT
  pass
Exemple #23
0
def draw_XYXYSin2(img,
                  objs,
                  color,
                  obj_thickness=1,
                  font_scale=0.5,
                  text_color='green'):
    '''
    img: [h,w,3]
    objs: [n,5/6]
    color: 'red'
    '''
    assert objs.ndim == 2
    assert objs.shape[1] == 5 or objs.shape[1] == 6
    if objs.shape[1] == 6:
        scores = objs[:, 5]
        objs = objs[:, :5]
    else:
        scores = None
    rotations = objs[:, 4]
    text_color = _get_color(text_color)

    objs = decode_line_rep(objs, 'lscope_istopleft').reshape(-1, 2, 2)
    objs = OBJ_REPS_PARSE.encode_obj(objs, 'XYXYSin2', 'RoLine2D_2p')
    for i in range(objs.shape[0]):
        s, e = np.round(objs[i]).astype(np.int32)
        c = _get_color(color)
        cv2.line(img, (s[0], s[1]), (e[0], e[1]), c, thickness=obj_thickness)

        #label_text = class_names[label] if class_names is not None else 'cls {}'.format(label)
        label_text = ''
        if DEBUG_CFG.OBJ_LEGEND == 'score':
            if scores is not None:
                label_text += '{:.01f}'.format(scores[i])  # score
        else:
            label_text += '{:.01f}'.format(rotations[i])  # rotation
        m = np.round(((s + e) / 2)).astype(np.int32)
        if label_text != '':
            cv2.putText(img, label_text, (m[0] - 4, m[1] - 4),
                        cv2.FONT_HERSHEY_COMPLEX, font_scale, text_color)
    return img
def connect_two_corner(corners, walls0, obj_rep):
  assert corners.shape == (2,2)
  assert walls0.shape[0] == 2
  show = 0

  c = walls0.shape[1]
  angle_dif = limit_period_np( walls0[0,6] - walls0[1,6], 0.5, np.pi)
  angle_dif = abs(angle_dif)
  if angle_dif > np.pi / 4:
      new_wall = intersect_2edges_by_add_new_wall( walls0[:,:7], obj_rep, corners )
      walls1 = walls0[:,:7]
  else:
      new_wall = OBJ_REPS_PARSE.encode_obj(corners.reshape(1,4), 'RoLine2D_2p', obj_rep)
      walls1 = walls0[:,:7]
  if c==8:
    score =  new_wall[:,0:1].copy()
    score[:]  =1
    new_wall = np.concatenate([new_wall, score ], 1)
  if show:
    _show_objs_ls_points_ls( (512, 512), [walls0[:,:7], walls1[:,:7], new_wall[:,:7]], obj_rep,
                            obj_colors=['white', 'green', 'red'], obj_thickness=[4,1,1] )
    import pdb; pdb.set_trace()  # XXX BREAKPOINT
    pass
  return walls1, new_wall
def cal_wall_in_room_scores(walls, rooms_aug, rooms, obj_rep):
  from mmdet.core.bbox.geometry import dsiou_rotated_3d_bbox_np
  assert obj_rep == 'XYZLgWsHA'
  ious_inner = dsiou_rotated_3d_bbox_np( walls, rooms_aug, iou_w=1.0, size_rate_thres=None, ref='bboxes1', only_2d=True )


  # see if a wall is the edge of a room
  num_walls = walls.shape[0]
  num_rooms = rooms.shape[0]
  border_4_lines_0 = OBJ_REPS_PARSE.get_border_4_lines( rooms, obj_rep )
  border_4_lines = border_4_lines_0.reshape(num_rooms*4, 7)
  #_show_objs_ls_points_ls( (512,512), [ border_4_lines_0.reshape(-1,7) ], obj_rep,)
  ious_border_0 = dsiou_rotated_3d_bbox_np( walls, border_4_lines, iou_w=1, size_rate_thres=0.2, ref='bboxes1', only_2d=True )
  ious_border_1 = ious_border_0.reshape(num_walls, num_rooms, 4)
  ious_border = ious_border_1.max(2)

  #angles_dif = walls[:, None, 6] - border_4_lines[None,:,6]
  #angles_dif = np.abs( angle_dif_by_period_np( angles_dif, 0, 0 ))
  #angles_dif = angles_dif.reshape(num_walls, num_rooms, 4).min(2)

  ious_max = np.maximum( ious_border, ious_inner )
  ious_min = np.minimum( ious_border, ious_inner )
  ious = ious_max * 0.8 + ious_min * 0.2

  if 0:
    for i in range(num_rooms):
      ious_b_i = ious_border[:,i]
      ious_i = ious[:,i]
      print(f'border iou')
      #_show_objs_ls_points_ls( (512,512), [walls, rooms[i:i+1]], obj_rep, obj_colors=['random', 'white' ], obj_thickness=[1,2], obj_scores_ls=[ ious_b_i, None ] )
      print(f'inner iou')
      print(f'fuse iou')
      _show_objs_ls_points_ls( (512,512), [walls, rooms_aug[i:i+1]], obj_rep, obj_colors=['random', 'white' ], obj_thickness=[1,2], obj_scores_ls=[ ious_i, None ] )
  #print(ious)
  #_show_objs_ls_points_ls( (512,512), [walls, rooms], obj_rep, obj_colors=['green', 'red' ], obj_thickness=[1,3] )
  return ious
Exemple #26
0
def bboxes_flip_scope_itl(bboxes_in, curr_ax, coord_max, obj_rep):
  from obj_geo_utils.obj_utils import OBJ_REPS_PARSE

  if obj_rep == 'XYXYSin2':
    lines0 = bboxes_in
    assert lines0.shape[1] == 5
    assert curr_ax==0 or curr_ax==1
    tmp = coord_max - lines0[:, curr_ax]
    lines0[:, curr_ax] = coord_max - lines0[:, curr_ax + 2]
    lines0[:, curr_ax + 2] = tmp
    lines0[:,4] = -lines0[:,4]
    return lines0
  elif obj_rep == 'Rect4CornersZ0Z1':
    assert bboxes_in.shape[1] == 10
    assert curr_ax==0 or curr_ax==1
    flipped = bboxes_in.copy()
    if curr_ax == 0:
      flipped[..., 0:8:2] = coord_max - bboxes_in[..., 0:8:2]
    if curr_ax == 1:
      flipped[..., 1:9:2] = coord_max - bboxes_in[..., 1:9:2]
    flipped = OBJ_REPS_PARSE.update_corners_order( flipped, obj_rep )
    return flipped
  else:
    raise NotImplementedError
def _show_2dlines_as_3d(lines_2d_ls, obj_rep, filename, height_method=['same','per_room'][1]):
  '''
  lines_2d_ls: [walls, windows, doors]
  '''
  from obj_geo_utils.geometry_utils import get_rooms_from_edges
  from beike_data_utils.beike_utils import load_ply

  wall_idx, door_idx, win_idx = 0, 1, 2

  assert obj_rep == 'XYZLgWsHA'
  scene_name = os.path.splitext(os.path.basename(filename))[0]
  print(f'{scene_name}')

  m2p_file = '../'+filename.replace('TopView_VerD', 'meter_to_pix_rates').replace('npy','txt')
  m2p_rate = np.loadtxt(m2p_file)

  rooms_line_ids, room_ids_per_edge, num_walls_inside_room, rooms = get_rooms_from_edges(lines_2d_ls[0], obj_rep, gen_bbox=True, show_rooms=0)
  num_room = len(rooms_line_ids)

  scope_file = '../'+filename.replace('TopView_VerD', 'pcl_scopes').replace('npy','txt')
  pcl_scope = np.loadtxt(scope_file)
  max_height = pcl_scope[1,-1] - pcl_scope[0,-1] - 0.3
  max_height = min(max_height, 4)
  #bottom = pcl_scope[0,-1]
  bottom = - max_height/2 + 0.1
  if height_method == 'same':
    heights = [max_height for _ in range(num_room)]
  elif height_method == 'per_room':
    pcl_file = '../'+filename.replace('TopView_VerD', 'ply').replace('npy','ply')
    pcl = load_ply(pcl_file)[:,:3]
    pcl_min = pcl.min(0).reshape(1,-1)
    pcl = pcl - pcl_min
    ids = np.random.choice(int(pcl.shape[0]), 100*1000)
    pcl = pcl[ids]

    heights = []
    point_nums = []
    for i in range(num_room):
      rc = rooms[i:i+1,:2] / m2p_rate
      rs = rooms[i,3:5].max() / m2p_rate
      mask = np.linalg.norm( pcl[:,:2] - rc, axis=1)  < rs * 0.7
      p_n = mask.sum()
      point_nums.append(p_n)
      if p_n < 100:
        heights.append(max_height)
        continue
      r_points = pcl[mask]
      height_i = r_points[:,2].max() - bottom
      gap = (max_height - height_i)/ max_height
      if gap < 0.1:
        height_i = max_height
      heights.append(height_i)
      pass


  wall_thickness = 0.2 # 0.24
  door_thickness = 0.23
  door_height = 2.1
  window_height = 1.5
  for i,ls in enumerate( lines_2d_ls):
    ls[:,:6] /= m2p_rate
    if i==wall_idx:
      ls[:,4] = wall_thickness
      #ls[:,5] = max_height
    else:
      ls[:,4] = door_thickness
      if i==door_idx:
        ls[:,5] = door_height
      if i==win_idx:
        ls[:,5] = 1.5

  for i in range(num_room):
    ids = rooms_line_ids[i]
    lines_2d_ls[0][ids, 5] = np.clip( lines_2d_ls[0][ids,5], a_min = heights[i], a_max=None)

  lines_2d_ls[wall_idx][:,2] = lines_2d_ls[wall_idx][:,2] + (lines_2d_ls[wall_idx][:,5] - max_height)/2
  lines_2d_ls[wall_idx][:,3] += wall_thickness * 0.8
  lines_2d_ls[door_idx][:,2] = lines_2d_ls[door_idx][:,2] + (lines_2d_ls[door_idx][:,5] - max_height)/2
  lines_2d_ls[win_idx][:,2] = lines_2d_ls[win_idx][:,5]/2 + 0.85 - max_height/2

  labels = []
  cat_num = len(lines_2d_ls)
  for i in range(cat_num):
    labels += [i] * lines_2d_ls[i].shape[0]
  obj_colors = ['gray', 'green', 'blue']
  colors = [obj_colors[l] for l in labels]

  # flip
  for ls in lines_2d_ls:
    ls[:,1] *= -1
    ls[:,-1] *= -1
  bboxes = np.concatenate(lines_2d_ls, 0)

  walls = lines_2d_ls[0]
  walls_2cor = OBJ_REPS_PARSE.encode_obj(walls, obj_rep, 'RoLine2D_2p')
  floors = gen_floor_mesh_from_walls(walls_2cor, rooms_line_ids, bottom-0.1)

  if 1:
    print('point_nums', point_nums)
    print('heights', heights)

  _show_3d_points_objs_ls(objs_ls = [bboxes, bboxes], obj_rep=obj_rep, obj_colors=[colors, 'black'], box_types=['surface_mesh','line_mesh'], polygons_ls=[floors], polygon_colors=['order'] )
  pass
def gen_corners_from_lines_np(lines, labels, obj_rep, min_cor_dis_thr, get_degree=False,  flag=''):
    '''
    lines: [n,5]
    labels: [n,1/2]: 1 for label only, 2 for label and score

    corners: [m,2]
    labels_cor: [m, 1/2]
    corIds_per_line: [n,2]
    num_cor_uq: m
    '''
    if lines.shape[0] == 0:
      if labels is None:
        labels_cor = None
      else:
        labels_cor = np.zeros([0,labels.shape[1]])
      return np.zeros([0,2]), labels_cor, np.zeros([0,2], dtype=np.int), 0

    #lines0 = decode_line_rep(lines, obj_rep)
    lines0 = OBJ_REPS_PARSE.encode_obj(lines, obj_rep, 'RoLine2D_2p').reshape(-1,2,2)
    if labels is not None:
      num_line = lines.shape[0]
      assert labels.shape[0] == num_line
      labels = labels.reshape(num_line, -1)
      lc = labels.shape[1]

      labels_1 = labels.reshape(-1,lc)
      lines1 = np.concatenate([lines0[:,0], labels_1, lines0[:,1], labels_1], axis=1)
      corners1 = lines1.reshape(-1,2+lc)
    else:
      corners1 = lines0.reshape(-1,2)
    corners1, _ = merge_close_corners(corners1, min_cor_dis_thr, labels)

    corners1 = round_positions(corners1, 1000)
    corners_uq, unique_indices, inds_inverse = np.unique(corners1, axis=0, return_index=True, return_inverse=True)
    #print( abs(corners_uq[9] - corners_uq[10]).max() )
    num_cor_uq = corners_uq.shape[0]
    corners = corners_uq[:,:2]
    if labels is not None:
      labels_cor = corners_uq[:,2:].astype(labels.dtype)
    else:
      labels_cor = None
    corIds_per_line = inds_inverse.reshape(-1,2)

    lineIds_per_cor = get_lineIdsPerCor_from_corIdsPerLine(corIds_per_line, corners.shape[0])

    if 0:
      n_org = corners1.shape[0]
      n_new = corners.shape[0]
      print(f'{n_org} -> {n_new}')
      _show_objs_ls_points_ls( (512,512), points_ls=[corners1], point_colors='red' )
      _show_objs_ls_points_ls( (512,512), points_ls=[corners], point_colors='red' )

    if find_duplicate_corners(corners, 1, 'B'):
      import pdb; pdb.set_trace()  # XXX BREAKPOINT
      pass

    cor_degrees = np.zeros([num_cor_uq], dtype=np.int32)-1
    for i in corIds_per_line.reshape(-1):
      cor_degrees[i] += 1

    res = (corners, labels_cor, corIds_per_line, num_cor_uq)
    if get_degree:
      res = res + (cor_degrees,)
    return res
def rotate_lines_img(lines, img, angle,  obj_rep, debug_rotation=0):
  '''
  The img sizes of input  and output are the same.
  angle in degree
  '''
  assert obj_rep == 'XYXYSin2'
  assert img.ndim == 3
  assert lines.ndim == 2
  assert lines.shape[1] == 5
  assert img.shape[2] == 4

  img_shape = img.shape[:2]

  if debug_rotation:
    add_cross = 1
    if add_cross:
      img[:,:,1:] = np.abs(img[:,:,1:])*255
      lines = add_cross_in_lines(lines, img_shape)
    #_show_lines_ls_points_ls(img[:,:,0], [lines])
    #_show_lines_ls_points_ls(img[:,:,1:], [lines])
    #_show_lines_ls_points_ls(img[:,:,:3], [lines])
    pass

  n = lines.shape[0]
  if n == 0:
    return lines, img
  lines_2endpts = OBJ_REPS_PARSE.encode_obj(lines, obj_rep, 'RoLine2D_2p').reshape(n,2,2)
  #lines_2endpts = decode_line_rep(lines, obj_rep).reshape(n,2,2)

  h, w = img_shape
  assert h%2 == 0
  assert w%2 == 0
  center = ((w - 1) * 0.5, (h - 1) * 0.5)
  scale = 1.0
  matrix = cv2.getRotationMatrix2D(center, -angle, scale)

  ones = np.ones([n,2,1], dtype=lines.dtype)
  tmp = np.concatenate([lines_2endpts, ones], axis=2)
  lines_2pts_r = np.matmul( tmp, matrix.T )

  # (1) rotate the lines
  lines_rotated = OBJ_REPS_PARSE.encode_obj(lines_2pts_r.reshape(-1,4), 'RoLine2D_2p', obj_rep)
  #lines_rotated = encode_line_rep(lines_2pts_r, obj_rep)
  #_show_lines_ls_points_ls(img[:,:,0], [lines_rotated])

  # (3) scale the lines to fit the image size
  # Move before scaling can increase the scale ratio
  x_min_ =  lines_rotated[:,[0,2]].min()
  x_max_ =  lines_rotated[:,[0,2]].max()
  y_min_ =  lines_rotated[:,[1,3]].min()
  y_max_ =  lines_rotated[:,[1,3]].max()

  border_pad = 4
  gap_x0 = 0 - x_min_
  gap_y0 = 0 - y_min_
  gap_x1 = x_max_ - (w-1)
  gap_y1 = y_max_ - (h-1)
  gap_x = np.ceil(np.array([gap_x0, gap_x1, 0]).max())
  gap_y = np.ceil(np.array([gap_y0, gap_y1, 0]).max())
  scale_x = (w-border_pad*2) / (w+gap_x*2.0)
  scale_y = (h-border_pad*2) / (h+gap_y*2.0)
  scale = min(scale_x, scale_y)
  scale = np.floor(scale * 100)/100.0

  lines_rotated[:,:4] = ((lines_rotated[:,:4].reshape(-1,2) - center) * scale + center).reshape(-1,4)

  # (4) rotate the image (do not scale at this stage)
  if debug_rotation:
    if add_cross:
      add_cross_in_img(img)
    #_show_lines_ls_points_ls(img[:,:,:3], [lines])


  img_big = np.pad(img, ( (h//2,h//2), (w//2,w//2), (0,0) ), 'constant', constant_values=0)
  img_r = mmcv.imrotate(img_big, angle, scale=scale)

  # (5) Move the image
  new_img = np.zeros([h,w], dtype=lines.dtype)
  h1,w1 = img_r.shape[:2]
  region = np.array([
    w1/2-w/2,
    h1/2-h/2,
    w1/2+w/2-1,
    h1/2+h/2-1,
  ])
  region_int = region.astype(np.int32)
  new_img = mmcv.imcrop(img_r, region_int)
  assert new_img.shape[:2] == img_shape

  # rotate the surface normal
  new_img[:,:,[1,2]] = np.matmul( new_img[:,:,[1,2]], matrix[:,:2].T )


  lines_rotated = lines_rotated.astype(np.float32)
  new_img = new_img.astype(np.float32)
  assert lines_rotated[:,:4].min() > 0
  if debug_rotation:
    print(f'\nscale: {scale}')
    #_show_lines_ls_points_ls(img[:,:,:3], [lines])
    _show_lines_ls_points_ls(new_img[:,:,0], [lines_rotated])

    #_show_img_with_norm(img)
    #_show_img_with_norm(new_img)
    if add_cross:
      lines_rotated = lines_rotated[:-4]
    pass

  return  lines_rotated, new_img, scale
Exemple #30
0
    def assign(self, points, gt_bboxes, gt_bboxes_ignore=None, gt_labels=None,
               img_meta=None):
        """Assign gt to points.

        This method assign a gt bbox to every points set, each points set
        will be assigned with  0, or a positive number.
        0 means negative sample, positive number is the index (1-based) of
        assigned gt.
        The assignment is done in following steps, the order matters.

        1. assign every points to 0
        2. A point is assigned to some gt bbox if
            (i) the point is within the k closest points to the gt bbox
            (ii) the distance between this point and the gt is smaller than
                other gt bboxes

        Args:
            points (Tensor): points to be assigned, shape(n, 3) while last
                dimension stands for (x, y, stride).
            gt_bboxes (Tensor): Groundtruth boxes, shape (k, 4).
            gt_bboxes_ignore (Tensor, optional): Ground truth bboxes that are
                labelled as `ignored`, e.g., crowd boxes in COCO.
                NOTE: currently unused.
            gt_labels (Tensor, optional): Label of gt_bboxes, shape (k, ).

        Returns:
            :obj:`AssignResult`: The assign result.
        """
        num_points = points.shape[0]
        num_gts = gt_bboxes.shape[0]

        if num_gts == 0 or num_points == 0:
            # If no truth assign everything to the background
            assigned_gt_inds = points.new_full((num_points, ),
                                               0,
                                               dtype=torch.long)
            if gt_labels is None:
                assigned_labels = None
            else:
                assigned_labels = points.new_zeros((num_points, ),
                                                   dtype=torch.long)
            return AssignResult(
                num_gts, assigned_gt_inds, None, labels=assigned_labels)

        points_xy = points[:, :2]
        points_stride = points[:, 2]
        points_lvl = torch.log2(
            points_stride).int()  # [3...,4...,5...,6...,7...]
        lvl_min, lvl_max = points_lvl.min(), points_lvl.max()

        # assign gt box
        if self.obj_rep == 'box_scope':
          assert gt_bboxes.shape[1] == 4
          if gt_bboxes_ignore is not None:
            assert gt_bboxes_ignore.shape[1] == 4
          gt_bboxes_wh = (gt_bboxes[:, 2:] - gt_bboxes[:, :2]).clamp(min=1e-6)
          gt_bboxes_xy = (gt_bboxes[:, :2] + gt_bboxes[:, 2:]) / 2

        elif self.obj_rep == 'XYXYSin2' or self.obj_rep == 'XYXYSin2WZ0Z1':
          obj_dim =  {'XYXYSin2':5, 'XYXYSin2WZ0Z1':8}[self.obj_rep]
          assert gt_bboxes.shape[1] == obj_dim
          if gt_bboxes_ignore is not None:
            assert gt_bboxes_ignore.shape[1] == obj_dim
            gt_bboxes_ignore = gt_bboxes_ignore[:,:8]
          gt_bboxes_raw = gt_bboxes.clone()
          gt_bboxes = gt_bboxes[:,:4]
          gt_bboxes_wh = (gt_bboxes[:, 2:] - gt_bboxes[:, :2]).norm(dim=1)\
                                                              .clamp(min=1e-6)
          gt_bboxes_wh = gt_bboxes_wh.unsqueeze(1).repeat(1,2)      # [56, 2]
          gt_bboxes_xy = (gt_bboxes[:, :2] + gt_bboxes[:, 2:]) / 2  # [56, 2]

        elif self.obj_rep == 'Rect4CornersZ0Z1':
          from obj_geo_utils.obj_utils import OBJ_REPS_PARSE
          assert gt_bboxes.shape[1] == 10
          if gt_bboxes_ignore is not None:
            assert gt_bboxes_ignore.shape[1] == 10
          gt_bboxes_raw = gt_bboxes.clone()
          XYZLgWsHA = OBJ_REPS_PARSE.encode_obj(gt_bboxes, 'Rect4CornersZ0Z1', 'XYZLgWsHA')
          gt_bboxes_xy = XYZLgWsHA[:,:2]
          gt_bboxes_wh = XYZLgWsHA[:,3:4].repeat(1,2) * level_fac

        elif self.obj_rep == 'XYDRSin2Cos2Z0Z1':
          assert gt_bboxes.shape[1] == 8
          if gt_bboxes_ignore is not None:
            assert gt_bboxes_ignore.shape[1] == 8
            gt_bboxes_ignore = gt_bboxes_ignore[:,:8]
          gt_bboxes_raw = gt_bboxes.clone()
          gt_bboxes_wh = gt_bboxes[:,2:3].repeat(1,2) * level_fac
          gt_bboxes_xy = gt_bboxes[:,:2]

        elif self.obj_rep == 'XYDAsinAsinSin2Z0Z1':
          assert gt_bboxes.shape[1] == 8
          if gt_bboxes_ignore is not None:
            assert gt_bboxes_ignore.shape[1] == 8
            gt_bboxes_ignore = gt_bboxes_ignore[:,:8]
          gt_bboxes_raw = gt_bboxes.clone()
          gt_bboxes_wh = gt_bboxes[:,2:3].repeat(1,2) * level_fac
          gt_bboxes_xy = gt_bboxes[:,:2]

        elif self.obj_rep in ['XYLgWsAsinSin2Z0Z1', 'XYLgWsAbsSin2Z0Z1', 'XYLgWsSin2Cos2Z0Z1']:
          assert gt_bboxes.shape[1] == 8
          if gt_bboxes_ignore is not None:
            assert gt_bboxes_ignore.shape[1] == 8
            gt_bboxes_ignore = gt_bboxes_ignore[:,:8]
          gt_bboxes_raw = gt_bboxes.clone()
          gt_bboxes_wh = gt_bboxes[:,2:3].repeat(1,2)
          gt_bboxes_xy = gt_bboxes[:,:2]

        elif self.obj_rep == 'corner':
          raise NotImplemented
          assert gt_bboxes.shape[1] == 2
          assert lvl_min == lvl_max, "only use one level for corner heat map"
          gt_bboxes_wh = gt_bboxes * 0 + 2**(lvl_min)*self.scale
          gt_bboxes = gt_bboxes.repeat(1,2)
          pass

        else:
          import pdb; pdb.set_trace()  # XXX BREAKPOINT
          raise NotImplemented

        if DEBUG_CFG.CHECK_POINT_ASSIGN:
          if not gt_bboxes_wh.min() > DEBUG_CFG.MIN_BOX_SIZE:
            import pdb; pdb.set_trace()  # XXX BREAKPOINT
            pass

        scale = self.scale
        gt_bboxes_lvl = ((torch.log2(gt_bboxes_wh[:, 0] / scale) +
                          torch.log2(gt_bboxes_wh[:, 1] / scale)) / 2).int()
        gt_bboxes_lvl = torch.clamp(gt_bboxes_lvl, min=lvl_min, max=lvl_max)

        # stores the assigned gt index of each point
        assigned_gt_inds = points.new_zeros((num_points, ), dtype=torch.long)
        # stores the assigned gt dist (to this point) of each point
        assigned_gt_dist = points.new_full((num_points, ), float('inf'))
        points_range = torch.arange(points.shape[0])

        for idx in range(num_gts):
            gt_lvl = gt_bboxes_lvl[idx]
            # get the index of points in this level
            lvl_idx = gt_lvl == points_lvl
            points_index = points_range[lvl_idx]
            # get the points in this level
            lvl_points = points_xy[lvl_idx, :]
            # get the center point of gt
            gt_point = gt_bboxes_xy[[idx], :]
            # get width and height of gt
            gt_wh = gt_bboxes_wh[[idx], :]
            # compute the distance between gt center and
            #   all points in this level
            points_gt_dist = ((lvl_points - gt_point) / gt_wh).norm(dim=1)
            # find the nearest k points to gt center in this level
            min_dist, min_dist_index = torch.topk(
                points_gt_dist, self.pos_num, largest=False)

            #print(f'min_dist: {min_dist}')
            if DEBUG_CFG.CHECK_POINT_ASSIGN:
              if min_dist.max() > 2:
                print(f'\n\tmin_dist is too large: {min_dist}\n')
                import pdb; pdb.set_trace()  # XXX BREAKPOINT
                #assert False
                pass
            # the index of nearest k points to gt center in this level
            min_dist_points_index = points_index[min_dist_index]
            # The less_than_recorded_index stores the index
            #   of min_dist that is less then the assigned_gt_dist. Where
            #   assigned_gt_dist stores the dist from previous assigned gt
            #   (if exist) to each point.
            less_than_recorded_index = min_dist < assigned_gt_dist[
                min_dist_points_index]
            # The min_dist_points_index stores the index of points satisfy:
            #   (1) it is k nearest to current gt center in this level.
            #   (2) it is closer to current gt center than other gt center.
            min_dist_points_index = min_dist_points_index[
                less_than_recorded_index]
            # assign the result
            assigned_gt_inds[min_dist_points_index] = idx + 1
            assigned_gt_dist[min_dist_points_index] = min_dist[
                less_than_recorded_index]

        if gt_labels is not None:
            assigned_labels = assigned_gt_inds.new_zeros((num_points, ))
            pos_inds = torch.nonzero(assigned_gt_inds > 0).squeeze()
            if pos_inds.numel() > 0:
                assigned_labels[pos_inds] = gt_labels[assigned_gt_inds[pos_inds] - 1]

            if DEBUG_CFG.PRINT_POINT_ASSIGNER:
              pos_dist = assigned_gt_dist[pos_inds]
            #  print(f'pos_dist: {pos_dist}')
        else:
            assigned_labels = None

        assign_res = AssignResult(
            num_gts, assigned_gt_inds, None, labels=assigned_labels,
            env='PointAssigner', img_meta=img_meta)

        if DEBUG_CFG.PRINT_POINT_ASSIGNER:
          assign_res.dg_add_pos_dist(pos_dist)
          print('\tPointAssigner\t' + str(assign_res))

        if DEBUG_CFG.VISUALIZE_POINT_ASSIGNER:
          #if (not assign_res.num_pos_inds == num_gts):
            from tools.visual_utils import _show_objs_ls_points_ls
            import numpy as np
            filename = img_meta['filename']
            points_scope = points.max(0)[0][:2].int()
            print(f'\n\n{filename}\n')
            print(f'lvl_min: {lvl_min}')
            print(f'lvl_max: {lvl_max}')
            print(f'gt_bboxes_lvl: {gt_bboxes_lvl}')

            pos_inds = torch.nonzero(assigned_gt_inds).squeeze()
            pos_gt_inds = assigned_gt_inds[pos_inds].cpu().data.numpy() - 1
            pos_gt_inds = np.array(pos_gt_inds).reshape([-1])
            neg_gt_inds = [i for i in range(num_gts) if i not in pos_gt_inds]
            miss_gt_num = len(neg_gt_inds)
            print(f'\n\nMiss {miss_gt_num} in point assigner\n')
            gt_bboxes_raw = gt_bboxes_raw.cpu().data.numpy()
            missed_gt_bboxes = gt_bboxes_raw[neg_gt_inds]
            missed_gt_bboxes_center = missed_gt_bboxes[:,:4].reshape(-1,2,2).mean(1)

            if miss_gt_num>0:
              point_scope = points.max(0)[0][:2].cpu().data.numpy()
              is_gt_out_scope = (missed_gt_bboxes_center >  point_scope).any(-1)
              if is_gt_out_scope.all():
                print('\n\tthe missed gts are out of scope\n')
              else:
                import pdb; pdb.set_trace()  # XXX BREAKPOINT
                pass
                #assert False, "miss gt"
            if 1:
              pos_points = points[:,:2][pos_inds].cpu().data.numpy().reshape(-1,2)
              h = points_scope[1] + 100
              w = points_scope[0] + 100
              pos_levels = gt_bboxes_lvl[ pos_gt_inds ]
              #_show_objs_ls_points_ls((h,w), [gt_bboxes_raw], obj_rep=self.obj_rep)
              _show_objs_ls_points_ls((h,w), [gt_bboxes_raw[pos_gt_inds], missed_gt_bboxes], obj_rep=self.obj_rep, points_ls=[pos_points], obj_colors=['red', 'green'], obj_scores_ls=[pos_levels, None])
              for i in range(len(pos_inds)):
                l = gt_bboxes_lvl[ pos_gt_inds[i] ]
                print(f'level: {l}')
                pos_gt_i = gt_bboxes_raw[pos_gt_inds[i]].reshape(-1, gt_bboxes_raw.shape[1])
                _show_objs_ls_points_ls((h,w), [gt_bboxes_raw, pos_gt_i], obj_rep=self.obj_rep, points_ls = [pos_points[i:i+1]], obj_colors=['red', 'green'], obj_scores_ls=[None, l])
              pass

        return assign_res