[vis] add filter for realtime visualization
This commit is contained in:
parent
be44c5b540
commit
6c8d277c9e
@ -1,4 +1,4 @@
|
|||||||
host: 'auto'
|
host: '127.0.0.1'
|
||||||
port: 9999
|
port: 9999
|
||||||
|
|
||||||
width: 1920
|
width: 1920
|
||||||
@ -36,4 +36,10 @@ scene:
|
|||||||
yrange: 3
|
yrange: 3
|
||||||
white: [1., 1., 1.]
|
white: [1., 1., 1.]
|
||||||
black: [0.,0.,0.]
|
black: [0.,0.,0.]
|
||||||
two_sides: True
|
two_sides: True
|
||||||
|
|
||||||
|
range:
|
||||||
|
minr: [-100, -100, -100]
|
||||||
|
maxr: [ 100, 100, 100]
|
||||||
|
rate_inlier: 0.8
|
||||||
|
min_conf: 0.1
|
30
config/vis3d/o3d_scene_412.yml
Normal file
30
config/vis3d/o3d_scene_412.yml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
parent: "config/vis3d/o3d_scene.yml"
|
||||||
|
|
||||||
|
scene:
|
||||||
|
"easymocap.visualize.o3dwrapper.create_bbox":
|
||||||
|
min_bound: [-3, -3, 0]
|
||||||
|
max_bound: [3, 3, 2]
|
||||||
|
flip: False
|
||||||
|
"easymocap.visualize.o3dwrapper.create_ground":
|
||||||
|
center: [0, 0, 0]
|
||||||
|
xdir: [1, 0, 0]
|
||||||
|
ydir: [0, 1, 0]
|
||||||
|
step: 1
|
||||||
|
xrange: 3
|
||||||
|
yrange: 3
|
||||||
|
white: [1., 1., 1.]
|
||||||
|
black: [0.,0.,0.]
|
||||||
|
two_sides: True
|
||||||
|
|
||||||
|
camera:
|
||||||
|
cy: 0.6
|
||||||
|
cz: 4.
|
||||||
|
theta: -30
|
||||||
|
|
||||||
|
range:
|
||||||
|
minr: [-2, -1, 0]
|
||||||
|
maxr: [ 2, 2, 2.5]
|
||||||
|
rate_inlier: 0.8
|
||||||
|
min_conf: 0.1
|
||||||
|
|
||||||
|
new_frames: 10
|
@ -2,7 +2,7 @@
|
|||||||
* @Date: 2021-06-04 15:56:55
|
* @Date: 2021-06-04 15:56:55
|
||||||
* @Author: Qing Shuai
|
* @Author: Qing Shuai
|
||||||
* @LastEditors: Qing Shuai
|
* @LastEditors: Qing Shuai
|
||||||
* @LastEditTime: 2021-06-04 17:11:48
|
* @LastEditTime: 2021-06-12 15:29:23
|
||||||
* @FilePath: /EasyMocapRelease/doc/realtime_visualization.md
|
* @FilePath: /EasyMocapRelease/doc/realtime_visualization.md
|
||||||
-->
|
-->
|
||||||
# EasyMoCap -> Real-time Visualization
|
# EasyMoCap -> Real-time Visualization
|
||||||
@ -21,7 +21,10 @@ python3 -m pip install open3d==0.9.0
|
|||||||
Before any visualization, you should run a server:
|
Before any visualization, you should run a server:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 apps/vis/vis_server.py --cfg config/vis/o3d_scene.yml host <your_ip_address> port <set_a_port>
|
# quick start:
|
||||||
|
python3 apps/vis/vis_server.py --cfg config/vis3d/o3d_scene.yml
|
||||||
|
# If you want to specify the host and port:
|
||||||
|
python3 apps/vis/vis_server.py --cfg config/vis3d/o3d_scene.yml host <your_ip_address> port <set_a_port>
|
||||||
```
|
```
|
||||||
|
|
||||||
This step will open the visualization window:
|
This step will open the visualization window:
|
||||||
|
83
easymocap/assignment/criterion.py
Normal file
83
easymocap/assignment/criterion.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
'''
|
||||||
|
@ Date: 2021-05-28 16:36:45
|
||||||
|
@ Author: Qing Shuai
|
||||||
|
@ LastEditors: Qing Shuai
|
||||||
|
@ LastEditTime: 2021-05-30 12:21:15
|
||||||
|
@ FilePath: /EasyMocap/easymocap/assignment/criterion.py
|
||||||
|
'''
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
class BaseCrit:
|
||||||
|
def __init__(self, min_conf, min_joints=3) -> None:
|
||||||
|
self.min_conf = min_conf
|
||||||
|
self.min_joints = min_joints
|
||||||
|
self.name = self.__class__.__name__
|
||||||
|
|
||||||
|
def __call__(self, keypoints3d, **kwargs):
|
||||||
|
# keypoints3d: (N, 4)
|
||||||
|
conf = keypoints3d[..., -1]
|
||||||
|
conf[conf<self.min_conf] = 0
|
||||||
|
idx = keypoints3d[..., -1] > self.min_conf
|
||||||
|
return len(idx) > self.min_joints
|
||||||
|
|
||||||
|
class CritWithTorso(BaseCrit):
|
||||||
|
def __init__(self, torso_idx, min_conf, **kwargs) -> None:
|
||||||
|
super().__init__(min_conf)
|
||||||
|
self.idx = torso_idx
|
||||||
|
self.min_conf = min_conf
|
||||||
|
|
||||||
|
def __call__(self, keypoints3d, **kwargs) -> bool:
|
||||||
|
self.log = '{}'.format(keypoints3d[self.idx, -1])
|
||||||
|
return (keypoints3d[self.idx, -1] > self.min_conf).all()
|
||||||
|
|
||||||
|
class CritLenTorso(BaseCrit):
|
||||||
|
def __init__(self, src, dst, min_torso_length, max_torso_length, min_conf) -> None:
|
||||||
|
super().__init__(min_conf)
|
||||||
|
self.src = src
|
||||||
|
self.dst = dst
|
||||||
|
self.min_torso_length = min_torso_length
|
||||||
|
self.max_torso_length = max_torso_length
|
||||||
|
|
||||||
|
def __call__(self, keypoints3d, **kwargs):
|
||||||
|
"""length of torso"""
|
||||||
|
# eps = 0.1
|
||||||
|
# MIN_TORSO_LENGTH = 0.3
|
||||||
|
# MAX_TORSO_LENGTH = 0.8
|
||||||
|
if (keypoints3d[[self.src, self.dst], -1] < self.min_conf).all():
|
||||||
|
# low confidence, skip
|
||||||
|
return True
|
||||||
|
length = np.linalg.norm(keypoints3d[self.dst] - keypoints3d[self.src])
|
||||||
|
self.log = '{}: {:.3f}'.format(self.name, length)
|
||||||
|
if length < self.min_torso_length or length > self.max_torso_length:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
class CritRange(BaseCrit):
|
||||||
|
def __init__(self, minr, maxr, rate_inlier, min_conf) -> None:
|
||||||
|
super().__init__(min_conf)
|
||||||
|
self.min = minr
|
||||||
|
self.max = maxr
|
||||||
|
self.rate = rate_inlier
|
||||||
|
|
||||||
|
def __call__(self, keypoints3d, **kwargs):
|
||||||
|
idx = keypoints3d[..., -1] > self.min_conf
|
||||||
|
k3d = keypoints3d[idx, :3]
|
||||||
|
crit = (k3d[:, 0] > self.min[0]) & (k3d[:, 0] < self.max[0]) &\
|
||||||
|
(k3d[:, 1] > self.min[1]) & (k3d[:, 1] < self.max[1]) &\
|
||||||
|
(k3d[:, 2] > self.min[2]) & (k3d[:, 2] < self.max[2])
|
||||||
|
self.log = '{}: {}'.format(self.name, k3d)
|
||||||
|
return crit.sum()/crit.shape[0] > self.rate
|
||||||
|
|
||||||
|
class CritMinMax(BaseCrit):
|
||||||
|
def __init__(self, max_human_length, min_conf) -> None:
|
||||||
|
super().__init__(min_conf)
|
||||||
|
self.max_human_length = max_human_length
|
||||||
|
|
||||||
|
def __call__(self, keypoints3d, **kwargs):
|
||||||
|
idx = keypoints3d[..., -1] > self.min_conf
|
||||||
|
k3d = keypoints3d[idx, :3]
|
||||||
|
mink = np.min(k3d, axis=0)
|
||||||
|
maxk = np.max(k3d, axis=0)
|
||||||
|
length = max(np.abs(maxk - mink))
|
||||||
|
self.log = '{}: {:.3f}'.format(self.name, length)
|
||||||
|
return length < self.max_human_length
|
@ -47,7 +47,6 @@ class Config:
|
|||||||
import importlib
|
import importlib
|
||||||
def load_object(module_name, module_args):
|
def load_object(module_name, module_args):
|
||||||
module_path = '.'.join(module_name.split('.')[:-1])
|
module_path = '.'.join(module_name.split('.')[:-1])
|
||||||
# scene_module = importlib.import_module(cfg.scene_module)
|
|
||||||
module = importlib.import_module(module_path)
|
module = importlib.import_module(module_path)
|
||||||
name = module_name.split('.')[-1]
|
name = module_name.split('.')[-1]
|
||||||
obj = getattr(module, name)(**module_args)
|
obj = getattr(module, name)(**module_args)
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
@ Date: 2021-05-30 11:17:18
|
@ Date: 2021-05-30 11:17:18
|
||||||
@ Author: Qing Shuai
|
@ Author: Qing Shuai
|
||||||
@ LastEditors: Qing Shuai
|
@ LastEditors: Qing Shuai
|
||||||
@ LastEditTime: 2021-06-04 15:44:56
|
@ LastEditTime: 2021-06-12 14:56:00
|
||||||
@ FilePath: /EasyMocap/easymocap/config/vis_socket.py
|
@ FilePath: /EasyMocapRelease/easymocap/config/vis_socket.py
|
||||||
'''
|
'''
|
||||||
from .baseconfig import CN
|
from .baseconfig import CN
|
||||||
from .baseconfig import Config as BaseConfig
|
from .baseconfig import Config as BaseConfig
|
||||||
@ -19,7 +19,6 @@ class Config(BaseConfig):
|
|||||||
cfg.width = 1920
|
cfg.width = 1920
|
||||||
cfg.height = 1080
|
cfg.height = 1080
|
||||||
|
|
||||||
cfg.body = 'body25'
|
|
||||||
cfg.max_human = 5
|
cfg.max_human = 5
|
||||||
cfg.track = True
|
cfg.track = True
|
||||||
cfg.block = True # block visualization or not, True for visualize each frame, False in realtime applications
|
cfg.block = True # block visualization or not, True for visualize each frame, False in realtime applications
|
||||||
@ -30,6 +29,9 @@ class Config(BaseConfig):
|
|||||||
cfg.scene_module = "easymocap.visualize.o3dwrapper"
|
cfg.scene_module = "easymocap.visualize.o3dwrapper"
|
||||||
cfg.scene = CN()
|
cfg.scene = CN()
|
||||||
cfg.extra = CN()
|
cfg.extra = CN()
|
||||||
|
cfg.range = CN()
|
||||||
|
cfg.new_frames = 0
|
||||||
|
|
||||||
# skel
|
# skel
|
||||||
cfg.skel = CN()
|
cfg.skel = CN()
|
||||||
cfg.skel.joint_radius = 0.02
|
cfg.skel.joint_radius = 0.02
|
||||||
@ -42,6 +44,12 @@ class Config(BaseConfig):
|
|||||||
cfg.camera.cz = 6.
|
cfg.camera.cz = 6.
|
||||||
cfg.camera.set_camera = False
|
cfg.camera.set_camera = False
|
||||||
cfg.camera.camera_pose = []
|
cfg.camera.camera_pose = []
|
||||||
|
# range
|
||||||
|
cfg.range = CN()
|
||||||
|
cfg.range.minr = [-100, -100, -10]
|
||||||
|
cfg.range.maxr = [ 100, 100, 10]
|
||||||
|
cfg.range.rate_inlier = 0.8
|
||||||
|
cfg.range.min_conf = 0.1
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
@ Date: 2021-01-15 12:09:27
|
@ Date: 2021-01-15 12:09:27
|
||||||
@ Author: Qing Shuai
|
@ Author: Qing Shuai
|
||||||
@ LastEditors: Qing Shuai
|
@ LastEditors: Qing Shuai
|
||||||
@ LastEditTime: 2021-05-27 20:36:42
|
@ LastEditTime: 2021-06-09 19:52:41
|
||||||
@ FilePath: /EasyMocapRelease/easymocap/mytools/cmd_loader.py
|
@ FilePath: /EasyMocap/easymocap/mytools/cmd_loader.py
|
||||||
'''
|
'''
|
||||||
import os
|
import os
|
||||||
import argparse
|
import argparse
|
||||||
@ -12,6 +12,7 @@ def load_parser():
|
|||||||
parser = argparse.ArgumentParser('EasyMocap commond line tools')
|
parser = argparse.ArgumentParser('EasyMocap commond line tools')
|
||||||
parser.add_argument('path', type=str)
|
parser.add_argument('path', type=str)
|
||||||
parser.add_argument('--out', type=str, default=None)
|
parser.add_argument('--out', type=str, default=None)
|
||||||
|
parser.add_argument('--cfg', type=str, default=None)
|
||||||
parser.add_argument('--camera', type=str, default=None)
|
parser.add_argument('--camera', type=str, default=None)
|
||||||
parser.add_argument('--annot', type=str, default='annots', help="sub directory name to store the generated annotation files, default to be annots")
|
parser.add_argument('--annot', type=str, default='annots', help="sub directory name to store the generated annotation files, default to be annots")
|
||||||
parser.add_argument('--sub', type=str, nargs='+', default=[],
|
parser.add_argument('--sub', type=str, nargs='+', default=[],
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
@ Date: 2021-05-25 11:14:48
|
@ Date: 2021-05-25 11:14:48
|
||||||
@ Author: Qing Shuai
|
@ Author: Qing Shuai
|
||||||
@ LastEditors: Qing Shuai
|
@ LastEditors: Qing Shuai
|
||||||
@ LastEditTime: 2021-06-02 13:00:35
|
@ LastEditTime: 2021-06-05 19:32:56
|
||||||
@ FilePath: /EasyMocap/easymocap/socket/base.py
|
@ FilePath: /EasyMocap/easymocap/socket/base.py
|
||||||
'''
|
'''
|
||||||
import socket
|
import socket
|
||||||
@ -24,9 +24,9 @@ class BaseSocket:
|
|||||||
serversocket.bind((host, port))
|
serversocket.bind((host, port))
|
||||||
serversocket.listen(1)
|
serversocket.listen(1)
|
||||||
self.serversocket = serversocket
|
self.serversocket = serversocket
|
||||||
|
self.queue = Queue()
|
||||||
self.t = Thread(target=self.run)
|
self.t = Thread(target=self.run)
|
||||||
self.t.start()
|
self.t.start()
|
||||||
self.queue = Queue()
|
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
self.disconnect = False
|
self.disconnect = False
|
||||||
|
|
||||||
@ -55,10 +55,12 @@ class BaseSocket:
|
|||||||
while True:
|
while True:
|
||||||
clientsocket, addr = self.serversocket.accept()
|
clientsocket, addr = self.serversocket.accept()
|
||||||
print("[Info] Connect: %s" % str(addr))
|
print("[Info] Connect: %s" % str(addr))
|
||||||
|
self.disconnect = False
|
||||||
while True:
|
while True:
|
||||||
flag, l = self.recvLine(clientsocket)
|
flag, l = self.recvLine(clientsocket)
|
||||||
if not flag:
|
if not flag:
|
||||||
print("[Info] Disonnect: %s" % str(addr))
|
print("[Info] Disonnect: %s" % str(addr))
|
||||||
|
self.disconnect = True
|
||||||
break
|
break
|
||||||
data = self.recvAll(clientsocket, l)
|
data = self.recvAll(clientsocket, l)
|
||||||
if self.debug:log('[Info] Recv data')
|
if self.debug:log('[Info] Recv data')
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
@ Date: 2021-05-25 11:15:53
|
@ Date: 2021-05-25 11:15:53
|
||||||
@ Author: Qing Shuai
|
@ Author: Qing Shuai
|
||||||
@ LastEditors: Qing Shuai
|
@ LastEditors: Qing Shuai
|
||||||
@ LastEditTime: 2021-06-04 17:06:17
|
@ LastEditTime: 2021-06-12 14:54:43
|
||||||
@ FilePath: /EasyMocapRelease/easymocap/socket/o3d.py
|
@ FilePath: /EasyMocapRelease/easymocap/socket/o3d.py
|
||||||
'''
|
'''
|
||||||
import open3d as o3d
|
import open3d as o3d
|
||||||
@ -15,6 +15,7 @@ import json
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from os.path import join
|
from os.path import join
|
||||||
import os
|
import os
|
||||||
|
from ..assignment.criterion import CritRange
|
||||||
|
|
||||||
class VisOpen3DSocket(BaseSocket):
|
class VisOpen3DSocket(BaseSocket):
|
||||||
def __init__(self, host, port, cfg) -> None:
|
def __init__(self, host, port, cfg) -> None:
|
||||||
@ -53,6 +54,9 @@ class VisOpen3DSocket(BaseSocket):
|
|||||||
self.add_human(zero_params)
|
self.add_human(zero_params)
|
||||||
|
|
||||||
self.count = 0
|
self.count = 0
|
||||||
|
self.previous = {}
|
||||||
|
self.critrange = CritRange(**cfg.range)
|
||||||
|
self.new_frames = cfg.new_frames
|
||||||
|
|
||||||
def add_human(self, zero_params):
|
def add_human(self, zero_params):
|
||||||
vertices = self.body_model(zero_params)[0]
|
vertices = self.body_model(zero_params)[0]
|
||||||
@ -69,15 +73,31 @@ class VisOpen3DSocket(BaseSocket):
|
|||||||
init_param.extrinsic = np.array(camera_pose)
|
init_param.extrinsic = np.array(camera_pose)
|
||||||
ctr.convert_from_pinhole_camera_parameters(init_param)
|
ctr.convert_from_pinhole_camera_parameters(init_param)
|
||||||
|
|
||||||
|
def filter_human(self, datas):
|
||||||
|
datas_new = []
|
||||||
|
for data in datas:
|
||||||
|
kpts3d = np.array(data['keypoints3d'])
|
||||||
|
data['keypoints3d'] = kpts3d
|
||||||
|
pid = data['id']
|
||||||
|
if pid not in self.previous.keys():
|
||||||
|
if not self.critrange(kpts3d):
|
||||||
|
continue
|
||||||
|
self.previous[pid] = 0
|
||||||
|
self.previous[pid] += 1
|
||||||
|
if self.previous[pid] > self.new_frames:
|
||||||
|
datas_new.append(data)
|
||||||
|
return datas_new
|
||||||
|
|
||||||
def main(self, datas):
|
def main(self, datas):
|
||||||
if self.debug:log('[Info] Load data {}'.format(self.count))
|
if self.debug:log('[Info] Load data {}'.format(self.count))
|
||||||
datas = json.loads(datas)
|
datas = json.loads(datas)
|
||||||
|
datas = self.filter_human(datas)
|
||||||
with Timer('forward'):
|
with Timer('forward'):
|
||||||
for i, data in enumerate(datas):
|
for i, data in enumerate(datas):
|
||||||
if i >= len(self.meshes):
|
if i >= len(self.meshes):
|
||||||
print('[Error] the number of human exceeds!')
|
print('[Error] the number of human exceeds!')
|
||||||
self.add_human(np.array(data['keypoints3d']))
|
self.add_human(np.array(data['keypoints3d']))
|
||||||
vertices = self.body_model(np.array(data['keypoints3d']))
|
vertices = self.body_model(data['keypoints3d'])
|
||||||
self.vertices[i] = Vector3dVector(vertices[0])
|
self.vertices[i] = Vector3dVector(vertices[0])
|
||||||
for i in range(len(datas), len(self.meshes)):
|
for i in range(len(datas), len(self.meshes)):
|
||||||
self.vertices[i] = self.zero_vertices
|
self.vertices[i] = self.zero_vertices
|
||||||
@ -90,6 +110,8 @@ class VisOpen3DSocket(BaseSocket):
|
|||||||
self.meshes[i].paint_uniform_color(col)
|
self.meshes[i].paint_uniform_color(col)
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
|
if self.disconnect and not self.block:
|
||||||
|
self.previous.clear()
|
||||||
if not self.queue.empty():
|
if not self.queue.empty():
|
||||||
if self.debug:log('Update' + str(self.queue.qsize()))
|
if self.debug:log('Update' + str(self.queue.qsize()))
|
||||||
datas = self.queue.get()
|
datas = self.queue.get()
|
||||||
|
Loading…
Reference in New Issue
Block a user