2021-06-25 15:54:54 +08:00
|
|
|
|
'''
|
|
|
|
|
@ Date: 2021-06-04 21:58:37
|
|
|
|
|
@ Author: Qing Shuai
|
|
|
|
|
@ LastEditors: Qing Shuai
|
|
|
|
|
@ LastEditTime: 2021-06-25 11:50:10
|
|
|
|
|
@ FilePath: /EasyMocapRelease/easymocap/assignment/associate.py
|
|
|
|
|
'''
|
|
|
|
|
import numpy as np
|
|
|
|
|
from ..mytools.reconstruction import batch_triangulate, projectN3
|
|
|
|
|
from ..config import load_object
|
|
|
|
|
|
|
|
|
|
def views_from_dimGroups(dimGroups):
|
|
|
|
|
views = np.zeros(dimGroups[-1], dtype=np.int)
|
|
|
|
|
for nv in range(len(dimGroups) - 1):
|
|
|
|
|
views[dimGroups[nv]:dimGroups[nv+1]] = nv
|
|
|
|
|
return views
|
|
|
|
|
|
|
|
|
|
def set_keypoints2d(indices, annots, Pall, dimGroups):
|
|
|
|
|
Vused = np.where(indices!=-1)[0]
|
|
|
|
|
if len(Vused) < 1:
|
2021-11-10 11:16:28 +08:00
|
|
|
|
return [], [], [], []
|
2021-06-25 15:54:54 +08:00
|
|
|
|
keypoints2d = np.stack([annots[nv][indices[nv]-dimGroups[nv]]['keypoints'].copy() for nv in Vused])
|
|
|
|
|
bboxes = np.stack([annots[nv][indices[nv]-dimGroups[nv]]['bbox'].copy() for nv in Vused])
|
|
|
|
|
Pused = Pall[Vused]
|
|
|
|
|
return keypoints2d, bboxes, Pused, Vused
|
|
|
|
|
|
|
|
|
|
def load_criterions(cfg):
|
|
|
|
|
criterions = []
|
|
|
|
|
for key, val in cfg.items():
|
|
|
|
|
crit = load_object(key, val)
|
|
|
|
|
criterions.append(crit)
|
|
|
|
|
return criterions
|
|
|
|
|
|
|
|
|
|
def simple_associate(annots, affinity, dimGroups, Pall, group, cfg):
|
|
|
|
|
nViews = len(annots)
|
|
|
|
|
criterions = load_criterions(cfg.criterions)
|
|
|
|
|
n2D = dimGroups[-1]
|
|
|
|
|
views = views_from_dimGroups(dimGroups)
|
|
|
|
|
|
|
|
|
|
views_cnt = np.zeros((affinity.shape[0], nViews))
|
|
|
|
|
for nv in range(nViews):
|
|
|
|
|
views_cnt[:, nv] = affinity[:, dimGroups[nv]:dimGroups[nv+1]].sum(axis=1)
|
|
|
|
|
views_cnt = (views_cnt>0.5).sum(axis=1)
|
|
|
|
|
sortidx = np.argsort(-views_cnt)
|
|
|
|
|
p2dAssigned = np.zeros(n2D, dtype=np.int) - 1
|
|
|
|
|
indices_zero = np.zeros((nViews), dtype=np.int) - 1
|
|
|
|
|
for idx in sortidx:
|
|
|
|
|
if p2dAssigned[idx] != -1:
|
|
|
|
|
continue
|
|
|
|
|
proposals = [indices_zero.copy()]
|
|
|
|
|
for nv in range(nViews):
|
|
|
|
|
match = np.where(
|
|
|
|
|
(affinity[idx, dimGroups[nv]:dimGroups[nv+1]] > 0.)
|
|
|
|
|
& (p2dAssigned[dimGroups[nv]:dimGroups[nv+1]] == -1) )[0]
|
|
|
|
|
if len(match) > 0:
|
|
|
|
|
match = match + dimGroups[nv]
|
|
|
|
|
for proposal in proposals:
|
|
|
|
|
proposal[nv] = match[0]
|
|
|
|
|
if len(match) > 1:
|
|
|
|
|
proposals_new = []
|
|
|
|
|
for proposal in proposals:
|
|
|
|
|
for col in match[1:]:
|
|
|
|
|
p = proposal.copy()
|
|
|
|
|
p[nv] = col
|
|
|
|
|
proposals_new.append(p)
|
2021-11-10 11:16:28 +08:00
|
|
|
|
proposals += proposals_new
|
2021-06-25 15:54:54 +08:00
|
|
|
|
results = []
|
|
|
|
|
while len(proposals) > 0:
|
|
|
|
|
proposal = proposals.pop()
|
|
|
|
|
# less than two views
|
|
|
|
|
if (proposal != -1).sum() < cfg.min_views:
|
|
|
|
|
continue
|
|
|
|
|
# print('[associate] pop proposal: {}'.format(proposal))
|
|
|
|
|
keypoints2d, bboxes, Pused, Vused = set_keypoints2d(proposal, annots, Pall, dimGroups)
|
|
|
|
|
keypoints3d = batch_triangulate(keypoints2d, Pused)
|
|
|
|
|
kptsRepro = projectN3(keypoints3d, Pused)
|
|
|
|
|
err = ((kptsRepro[:, :, 2]*keypoints2d[:, :, 2]) > 0.) * np.linalg.norm(kptsRepro[:, :, :2] - keypoints2d[:, :, :2], axis=2)
|
|
|
|
|
size = (bboxes[:, [2, 3]] - bboxes[:, [0, 1]]).max(axis=1, keepdims=True)
|
|
|
|
|
err = err / size
|
2022-09-23 00:36:53 +08:00
|
|
|
|
err_view = err.sum(axis=1)/((err>0. + 1e-9).sum(axis=1))
|
2021-06-25 15:54:54 +08:00
|
|
|
|
flag = (err_view < cfg.max_repro_error).all()
|
2022-09-23 00:36:53 +08:00
|
|
|
|
err = err.sum()/(err>0 + 1e-9).sum()
|
2021-06-25 15:54:54 +08:00
|
|
|
|
# err_view = err.sum(axis=1)/((err>0.).sum(axis=1))
|
|
|
|
|
# err = err.sum()/(err>0.).sum()
|
|
|
|
|
# flag = err_view.max() < err_view.mean() * 2
|
|
|
|
|
flag = True
|
|
|
|
|
for crit in criterions:
|
|
|
|
|
if not crit(keypoints3d):
|
|
|
|
|
flag = False
|
|
|
|
|
break
|
|
|
|
|
if flag:
|
|
|
|
|
# print('[associate]: view {}'.format(Vused))
|
|
|
|
|
results.append({
|
|
|
|
|
'indices': proposal,
|
|
|
|
|
'keypoints2d': keypoints2d,
|
|
|
|
|
'keypoints3d': keypoints3d,
|
|
|
|
|
'Vused': Vused,
|
|
|
|
|
'error': err
|
|
|
|
|
})
|
|
|
|
|
else:
|
|
|
|
|
# make new proposals
|
|
|
|
|
outlier_view = Vused[err_view.argmax()]
|
|
|
|
|
proposal[outlier_view] = -1
|
|
|
|
|
proposals.append(proposal)
|
|
|
|
|
if len(results) == 0:
|
|
|
|
|
continue
|
|
|
|
|
if len(results) > 1:
|
|
|
|
|
# print('[associate] More than one avalible results')
|
|
|
|
|
results.sort(key=lambda x:x['error'])
|
|
|
|
|
result = results[0]
|
|
|
|
|
proposal = result['indices']
|
|
|
|
|
Vused = result['Vused']
|
|
|
|
|
# proposal中有-1的,所以需要使用Vused进行赋值
|
|
|
|
|
p2dAssigned[proposal[Vused]] = 1
|
|
|
|
|
group.add(result)
|
|
|
|
|
group.dimGroups = dimGroups
|
|
|
|
|
return group
|