Everything works properly
BIN
Content/Calib_int.png
Normal file
After Width: | Height: | Size: 600 KiB |
@ -5,7 +5,7 @@
|
||||
# Configure your project parameters here
|
||||
|
||||
[project]
|
||||
project_dir = 'D:\softs\github_david\pose2sim\Pose2Sim\Demo' # BETWEEN SINGLE QUOTES! # If empty, project dir is current dir
|
||||
project_dir = '' # BETWEEN SINGLE QUOTES! # If empty, project dir is current dir
|
||||
frame_range = [] #For example [10,300], or [] for all frames
|
||||
frame_rate = 60 #Hz
|
||||
|
||||
@ -26,7 +26,7 @@ pose_model = 'BODY_25B' #CUSTOM, BODY_25B, BODY_25, BODY_135, BLAZEPOSE, HALPE_2
|
||||
|
||||
|
||||
[calibration]
|
||||
calibration_type = 'calculate' # 'convert' or 'calculate'
|
||||
calibration_type = 'convert' # 'convert' or 'calculate'
|
||||
|
||||
[calibration.convert]
|
||||
convert_from = 'qualisys' # 'qualisys', 'optitrack', or 'vicon'
|
||||
@ -41,10 +41,9 @@ calibration_type = 'calculate' # 'convert' or 'calculate'
|
||||
intrinsics_board_type = 'checkerboard' # 'checkerboard' ('charucoboard' not supported yet)
|
||||
overwrite_intrinsics = false # overwrite (or not) if they have already been calculated?
|
||||
show_detection_intrinsics = true # true or false (lowercase)
|
||||
|
||||
intrinsics_extension = 'jpg' # any video or image extension
|
||||
extract_every_N_sec = 1 # if video, extract frames every N seconds (can be <1 )
|
||||
|
||||
extract_every_N_sec = 1 # if video, extract frames every N seconds (can be <1 )
|
||||
intrinsics_corners_nb = [4,7]
|
||||
intrinsics_square_size = 60 # mm
|
||||
intrinsics_marker_size = 40 # mm # only checked if charucoboard
|
||||
@ -56,7 +55,6 @@ calibration_type = 'calculate' # 'convert' or 'calculate'
|
||||
# 'scene' involves manually clicking any point of know coordinates on scene. Usually more accurate if points are spread out
|
||||
calculate_extrinsics = true # true or false (lowercase)
|
||||
show_reprojection_error = true # true or false (lowercase)
|
||||
|
||||
extrinsics_extension = 'png' # any video or image extension
|
||||
|
||||
# if extrinsics_board_type = 'checkerboard' or 'charucoboard'
|
||||
@ -87,7 +85,8 @@ likelihood_threshold = 0.3
|
||||
min_cameras_for_triangulation = 2
|
||||
interpolation = 'cubic' #linear, slinear, quadratic, cubic, or none
|
||||
# 'none' if you don't want to interpolate missing points
|
||||
show_interp_indices = false # true or false (lowercase). For each keypoint, return the frames that need to be interpolated
|
||||
interp_if_gap_smaller_than = 10 # do not interpolate bigger gaps
|
||||
show_interp_indices = true # true or false (lowercase). For each keypoint, return the frames that need to be interpolated
|
||||
|
||||
|
||||
[filtering]
|
||||
|
@ -1,5 +1,5 @@
|
||||
###############################################################################
|
||||
## POSE2SIM PROJECT PARAMETERS ##
|
||||
## PROJECT PARAMETERS ##
|
||||
###############################################################################
|
||||
|
||||
# Configure your project parameters here
|
||||
@ -9,45 +9,78 @@ project_dir = '' # BETWEEN SINGLE QUOTES! # If empty, project dir is current dir
|
||||
frame_range = [0,10] #For example [10,300], or [] for all frames
|
||||
frame_rate = 60 #Hz
|
||||
|
||||
rawImg_folder_name = 'raw-2d'
|
||||
rawImg_folder_name = 'raw'
|
||||
calib_folder_name = 'calibration'
|
||||
pose_folder_name = 'pose'
|
||||
pose_json_folder_extension = 'json'
|
||||
pose_img_folder_extension = 'img'
|
||||
poseTracked_folder_name = 'pose-2d-tracked'
|
||||
pose3d_folder_name = 'triangulation'
|
||||
poseAssociated_folder_name = 'pose-associated'
|
||||
pose3d_folder_name = 'pose-3d'
|
||||
opensim_folder_name = 'opensim'
|
||||
|
||||
|
||||
[pose]
|
||||
pose_model = 'BODY_25B' #CUSTOM, BODY_25B, BODY_25, BODY_135, BLAZEPOSE,
|
||||
# HALPE_26, HALPE_68, HALPE_136, COCO_133, COCO, MPII are available,
|
||||
pose_model = 'BODY_25B' #CUSTOM, BODY_25B, BODY_25, BODY_135, BLAZEPOSE, HALPE_26, HALPE_68, HALPE_136, COCO_133, COCO, MPII are available,
|
||||
# from DeepLabCut, OpenPose, MediaPipe BlazePose, and AlphaPose
|
||||
# See Pose2Sim\skeleton.py for their skeleton hierarchy
|
||||
|
||||
|
||||
[calibration]
|
||||
type = 'qca' # 'qca', 'checkerboard', 'arucoboard', or 'charucoboard'
|
||||
[calibration.qca]
|
||||
binning_factor = 1 # Usually 1, except when filming in 540p where it usually is 2
|
||||
calibration_type = 'convert' # 'convert' or 'calculate'
|
||||
|
||||
[calibration.checkerboard]
|
||||
corners_nb = [7,12] # [H,W] rather than [w,h]
|
||||
square_size = 80 # mm # [h,w] if square is actually a rectangle
|
||||
frame_for_origin = -1 # starting from zero. -1 if board is at origin on last frame
|
||||
# /!\ Beware that corners must be detected on all view at frame_for_origin, or else
|
||||
# extrinsic parameters will be wrong. Set show_corner_detection to true to check it.
|
||||
show_corner_detection = false # true or false (lowercase)
|
||||
from_vid_or_img = 'img' # 'vid' or 'img'
|
||||
vid_snapshot_every_N_frames = 20
|
||||
vid_extension = 'mp4'
|
||||
img_extension = 'jpg' # 'png', 'jpg', etc
|
||||
[calibration.convert]
|
||||
convert_from = 'qualisys' # 'qualisys', 'optitrack', or 'vicon'
|
||||
[calibration.convert.qualisys]
|
||||
binning_factor = 1 # Usually 1, except when filming in 540p where it usually is 2
|
||||
|
||||
[2d-tracking]
|
||||
|
||||
[calibration.calculate]
|
||||
calculate_method = 'board' # 'board' or 'points'
|
||||
|
||||
[calibration.calculate.board.intrinsics] # camera properties, only needs to be done once
|
||||
intrinsics_board_type = 'checkerboard' # 'checkerboard' ('charucoboard' not supported yet)
|
||||
overwrite_intrinsics = false # overwrite (or not) if they have already been calculated?
|
||||
show_detection_intrinsics = true # true or false (lowercase)
|
||||
intrinsics_extension = 'jpg' # any video or image extension
|
||||
|
||||
extract_every_N_sec = 1 # if video, extract frames every N seconds (can be <1 )
|
||||
intrinsics_corners_nb = [4,7]
|
||||
intrinsics_square_size = 60 # mm
|
||||
intrinsics_marker_size = 40 # mm # only checked if charucoboard
|
||||
intrinsics_aruco_dict = 'DICT_6X6_250' # only checked if charucoboard # see https://docs.opencv.org/3.4/dc/df7/dictionary_8hpp.html
|
||||
|
||||
[calibration.calculate.board.extrinsics] # camera placement, needs to be done every time
|
||||
extrinsics_board_type = 'scene' # 'checkerboard', 'scene' ('charucoboard' not supported yet)
|
||||
# 'board' should be large enough to be detected when laid on the floor.
|
||||
# 'scene' involves manually clicking any point of know coordinates on scene. Usually more accurate if points are spread out
|
||||
calculate_extrinsics = true # true or false (lowercase)
|
||||
show_reprojection_error = true # true or false (lowercase)
|
||||
extrinsics_extension = 'png' # any video or image extension
|
||||
|
||||
# if extrinsics_board_type = 'checkerboard' or 'charucoboard'
|
||||
extrinsics_corners_nb = [4,7] # [H,W] rather than [w,h]
|
||||
extrinsics_square_size = 60 # mm # [h,w] if square is actually a rectangle
|
||||
extrinsics_marker_size = 40 # mm # only checked if 'charucoboard' (not supported yet)
|
||||
extrinsics_aruco_dict = 'DICT_6X6_250' # only checked if 'charucoboard' # see https://docs.opencv.org/3.4/dc/df7/dictionary_8hpp.html
|
||||
|
||||
# if extrinsics_board_type = 'scene'
|
||||
# list of 3D coordinates to be manually labelled on images. Can also be a 2 dimensional plane. # in m
|
||||
object_coords_3d = [[-2.0, 0.3, 0.0], [-2.0 , 0.0, 0.0], [-2.0, 0.0, 0.05], [-2.0, -0.3 , 0.0], [0.0, 0.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.05], [0.0, -0.3, 0.0]] # in meters -> Not in mm! <-
|
||||
|
||||
|
||||
[calibration.calculate.points]
|
||||
calibration_points = 'wand' # 'wand' or 'keypoints'
|
||||
# Not supported yet.
|
||||
|
||||
|
||||
[personAssociation]
|
||||
tracked_keypoint = 'Neck' # If the neck is not detected by the pose_model, check skeleton.py
|
||||
# and choose a stable point for tracking the person of interest (e.g., 'right_shoulder' with BLAZEPOSE)
|
||||
error_threshold_tracking = 20 # px
|
||||
reproj_error_threshold_association = 20 # px
|
||||
|
||||
[3d-triangulation]
|
||||
error_threshold_triangulation = 15 # px
|
||||
|
||||
[triangulation]
|
||||
reproj_error_threshold_triangulation = 15 # px
|
||||
likelihood_threshold = 0.3
|
||||
min_cameras_for_triangulation = 2
|
||||
interpolation = 'cubic' #linear, slinear, quadratic, cubic, or none
|
||||
@ -55,23 +88,26 @@ interpolation = 'cubic' #linear, slinear, quadratic, cubic, or none
|
||||
interp_if_gap_smaller_than = 10 # do not interpolate bigger gaps
|
||||
show_interp_indices = true # true or false (lowercase). For each keypoint, return the frames that need to be interpolated
|
||||
|
||||
[3d-filtering]
|
||||
type = 'butterworth' # butterworth, butterworth_on_speed, gaussian, LOESS, median
|
||||
display_figures = false # true or false (lowercase)
|
||||
|
||||
[3d-filtering.butterworth]
|
||||
type = 'low'
|
||||
[filtering]
|
||||
type = 'butterworth' # butterworth, kalman, gaussian, LOESS, median, butterworth_on_speed
|
||||
display_figures = true # true or false (lowercase)
|
||||
|
||||
[filtering.butterworth]
|
||||
order = 4
|
||||
cut_off_frequency = 6 # Hz
|
||||
[3d-filtering.butterworth_on_speed]
|
||||
type = 'low'
|
||||
[filtering.kalman]
|
||||
# How much more do you trust triangulation results (measurements), than previous data (process assuming constant acceleration)?
|
||||
trust_ratio = 100 # = measurement_trust/process_trust ~= process_noise/measurement_noise
|
||||
smooth = true # should be true, unless you need real-time filtering
|
||||
[filtering.butterworth_on_speed]
|
||||
order = 4
|
||||
cut_off_frequency = 10 # Hz
|
||||
[3d-filtering.gaussian]
|
||||
[filtering.gaussian]
|
||||
sigma_kernel = 2 #px
|
||||
[3d-filtering.LOESS]
|
||||
nb_values_used = 5 # = fraction of data used * nb frames
|
||||
[3d-filtering.median]
|
||||
[filtering.LOESS]
|
||||
nb_values_used = 30 # = fraction of data used * nb frames
|
||||
[filtering.median]
|
||||
kernel_size = 9
|
||||
|
||||
[opensim]
|
||||
|
@ -1,39 +0,0 @@
|
||||
[cam_01]
|
||||
name = "cam_01"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1681.244873046875, 0.0, 532.97369384375], [ 0.0, 1681.075439453125, 948.137390140625], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.000721609375, 0.002187234375, 9.5e-06, 1.078125e-05]
|
||||
rotation = [ [1.70179346], [1.04839803], [-0.40602443]]
|
||||
translation = [ [0.31962238], [0.93995713], [2.97508412]]
|
||||
fisheye = false
|
||||
|
||||
[cam_02]
|
||||
name = "cam_02"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1673.729614265625, 0.0, 534.494567875], [ 0.0, 1673.79724121875, 963.225891109375], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.000747609375, 0.00213728125, 1.51875e-05, 4.546875e-06]
|
||||
rotation = [ [1.35902244], [1.60141928], [-1.18177902]]
|
||||
translation = [ [-0.12599186], [0.74502948], [3.17221429]]
|
||||
fisheye = false
|
||||
|
||||
[cam_03]
|
||||
name = "cam_03"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1681.598388671875, 0.0, 513.20837403125], [ 0.0, 1681.509887703125, 955.005126953125], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.000729765625, 0.00215034375, -8.46875e-06, -8.078125e-06]
|
||||
rotation = [ [0.81816165], [-2.22184308], [1.4608978]]
|
||||
translation = [ [-0.76301979], [0.34503189], [4.43845847]]
|
||||
fisheye = false
|
||||
|
||||
[cam_04]
|
||||
name = "cam_04"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1675.234985359375, 0.0, 540.106201171875], [ 0.0, 1675.204223640625, 964.0302734375], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.000744265625, 0.002104171875, 4.328125e-06, 3.109375e-06]
|
||||
rotation = [ [1.4245729], [-1.39512301], [0.45721172]]
|
||||
translation = [ [0.48659282], [0.02675454], [4.33496911]]
|
||||
fisheye = false
|
||||
|
||||
[metadata]
|
||||
adjusted = false
|
||||
error = 0.0
|
@ -1,39 +0,0 @@
|
||||
[cam_1]
|
||||
name = "cam_01"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1687.6396622414502, 0.0, 543.5], [ 0.0, 1686.6625452424132, 959.5], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.05054882348909584, 0.1576374662929963, 0.002210439026715273, -0.002164250840100675]
|
||||
rotation = [ 0, 0, 0]
|
||||
translation = [ 0, 0, 0]
|
||||
fisheye = false
|
||||
|
||||
[cam_2]
|
||||
name = "cam_02"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1687.859605173682, 0.0, 543.5], [ 0.0, 1685.4371774565182, 959.5], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.03518095956993663, 0.037170387967130306, 0.0017983248726869015, -0.0018747264134721386]
|
||||
rotation = [ 0, 0, 0]
|
||||
translation = [ 0, 0, 0]
|
||||
fisheye = false
|
||||
|
||||
[cam_3]
|
||||
name = "cam_03"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1680.286039024573, 0.0, 543.5], [ 0.0, 1681.1761700950424, 959.5], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.030304789365317657, 0.04613237843981006, 0.004618104732402956, -0.001684974310757026]
|
||||
rotation = [ 0, 0, 0]
|
||||
translation = [ 0, 0, 0]
|
||||
fisheye = false
|
||||
|
||||
[cam_4]
|
||||
name = "cam_04"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1689.483288223434, 0.0, 543.5], [ 0.0, 1688.5630322142706, 959.5], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.04369424846208241, 0.12212413289800295, 0.0017367557051414114, -0.0018985222378279064]
|
||||
rotation = [ 0, 0, 0]
|
||||
translation = [ 0, 0, 0]
|
||||
fisheye = false
|
||||
|
||||
[metadata]
|
||||
adjusted = false
|
||||
error = 0.0
|
@ -1,39 +0,0 @@
|
||||
[cam_01]
|
||||
name = "cam_01"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1681.244873046875, 0.0, 532.97369384375], [ 0.0, 1681.075439453125, 948.137390140625], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.000721609375, 0.002187234375, 9.5e-06, 1.078125e-05]
|
||||
rotation = [ 1.6882754799999993, 1.0483220499999997, -0.41955852000000016]
|
||||
translation = [ 0.3211048899999996, 0.9563320600000009, 2.8907130499999996]
|
||||
fisheye = false
|
||||
|
||||
[cam_02]
|
||||
name = "cam_02"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1673.729614265625, 0.0, 534.494567875], [ 0.0, 1673.79724121875, 963.225891109375], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.000747609375, 0.00213728125, 1.51875e-05, 4.546875e-06]
|
||||
rotation = [ 1.34975875, 1.5963809099999993, -1.1983285799999999]
|
||||
translation = [ -0.11152829000000017, 0.7766184800000001, 3.0675519599999994]
|
||||
fisheye = false
|
||||
|
||||
[cam_03]
|
||||
name = "cam_03"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1681.598388671875, 0.0, 513.20837403125], [ 0.0, 1681.509887703125, 955.005126953125], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.000729765625, 0.00215034375, -8.46875e-06, -8.078125e-06]
|
||||
rotation = [ 0.8109654899999995, -2.1972129299999996, 1.3760277799999996]
|
||||
translation = [ -0.7934803899999996, 0.32283594000000126, 4.353514870000001]
|
||||
fisheye = false
|
||||
|
||||
[cam_04]
|
||||
name = "cam_04"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1675.234985359375, 0.0, 540.106201171875], [ 0.0, 1675.204223640625, 964.0302734375], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.000744265625, 0.002104171875, 4.328125e-06, 3.109375e-06]
|
||||
rotation = [ 1.4045571699999995, -1.3887412699999993, 0.42535743000000026]
|
||||
translation = [ 0.5030217200000007, 0.04894934000000083, 4.406564460000002]
|
||||
fisheye = false
|
||||
|
||||
[metadata]
|
||||
adjusted = false
|
||||
error = 0.0
|
@ -1,39 +0,0 @@
|
||||
[cam_1]
|
||||
name = "cam01"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1681.244873046875, 0.0, 532.97369384375], [ 0.0, 1681.075439453125, 948.137390140625], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.000721609375, 0.002187234375, 9.5e-06, 1.078125e-05]
|
||||
rotation = [ 1.6882754799999993, 1.0483220499999997, -0.41955852000000016]
|
||||
translation = [ 0.3211048899999996, 0.9563320600000009, 2.8907130499999996]
|
||||
fisheye = false
|
||||
|
||||
[cam_2]
|
||||
name = "cam02"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1673.729614265625, 0.0, 534.494567875], [ 0.0, 1673.79724121875, 963.225891109375], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.000747609375, 0.00213728125, 1.51875e-05, 4.546875e-06]
|
||||
rotation = [ 1.34975875, 1.5963809099999993, -1.1983285799999999]
|
||||
translation = [ -0.11152829000000017, 0.7766184800000001, 3.0675519599999994]
|
||||
fisheye = false
|
||||
|
||||
[cam_3]
|
||||
name = "cam03"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1681.598388671875, 0.0, 513.20837403125], [ 0.0, 1681.509887703125, 955.005126953125], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.000729765625, 0.00215034375, -8.46875e-06, -8.078125e-06]
|
||||
rotation = [ 0.8109654899999995, -2.1972129299999996, 1.3760277799999996]
|
||||
translation = [ -0.7934803899999996, 0.32283594000000126, 4.353514870000001]
|
||||
fisheye = false
|
||||
|
||||
[cam_4]
|
||||
name = "cam04"
|
||||
size = [ 1088.0, 1920.0]
|
||||
matrix = [ [ 1675.234985359375, 0.0, 540.106201171875], [ 0.0, 1675.204223640625, 964.0302734375], [ 0.0, 0.0, 1.0]]
|
||||
distortions = [ -0.000744265625, 0.002104171875, 4.328125e-06, 3.109375e-06]
|
||||
rotation = [ 1.4045571699999995, -1.3887412699999993, 0.42535743000000026]
|
||||
translation = [ 0.5030217200000007, 0.04894934000000083, 4.406564460000002]
|
||||
fisheye = false
|
||||
|
||||
[metadata]
|
||||
adjusted = false
|
||||
error = 0.0
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
BIN
Pose2Sim/Demo/calibration/extrinsics/ext_cam3_img/cam03_ext.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
BIN
Pose2Sim/Demo/calibration/extrinsics/ext_cam4_img/cam04_ext.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 205 KiB After Width: | Height: | Size: 205 KiB |
Before Width: | Height: | Size: 173 KiB After Width: | Height: | Size: 173 KiB |
Before Width: | Height: | Size: 255 KiB After Width: | Height: | Size: 255 KiB |
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 240 KiB |
Before Width: | Height: | Size: 225 KiB After Width: | Height: | Size: 225 KiB |
Before Width: | Height: | Size: 205 KiB After Width: | Height: | Size: 205 KiB |
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 216 KiB |
Before Width: | Height: | Size: 255 KiB |
Before Width: | Height: | Size: 204 KiB |
Before Width: | Height: | Size: 204 KiB |
Before Width: | Height: | Size: 210 KiB |
Before Width: | Height: | Size: 213 KiB |
Before Width: | Height: | Size: 194 KiB |
Before Width: | Height: | Size: 222 KiB |
Before Width: | Height: | Size: 283 KiB |
Before Width: | Height: | Size: 217 KiB |
Before Width: | Height: | Size: 236 KiB |
Before Width: | Height: | Size: 232 KiB After Width: | Height: | Size: 232 KiB |
Before Width: | Height: | Size: 204 KiB After Width: | Height: | Size: 204 KiB |
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 150 KiB |
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 256 KiB |
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 248 KiB |
Before Width: | Height: | Size: 236 KiB After Width: | Height: | Size: 236 KiB |
Before Width: | Height: | Size: 222 KiB After Width: | Height: | Size: 222 KiB |
Before Width: | Height: | Size: 234 KiB |
Before Width: | Height: | Size: 170 KiB |
Before Width: | Height: | Size: 220 KiB |
Before Width: | Height: | Size: 209 KiB |
Before Width: | Height: | Size: 214 KiB |
Before Width: | Height: | Size: 244 KiB |
Before Width: | Height: | Size: 208 KiB |
Before Width: | Height: | Size: 236 KiB |
Before Width: | Height: | Size: 174 KiB |
Before Width: | Height: | Size: 182 KiB After Width: | Height: | Size: 182 KiB |
Before Width: | Height: | Size: 232 KiB After Width: | Height: | Size: 232 KiB |
Before Width: | Height: | Size: 251 KiB After Width: | Height: | Size: 251 KiB |
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 199 KiB |
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 180 KiB |
Before Width: | Height: | Size: 262 KiB After Width: | Height: | Size: 262 KiB |
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 238 KiB |
Before Width: | Height: | Size: 192 KiB |
Before Width: | Height: | Size: 222 KiB |
Before Width: | Height: | Size: 208 KiB |
Before Width: | Height: | Size: 222 KiB |
Before Width: | Height: | Size: 212 KiB |
Before Width: | Height: | Size: 212 KiB |
Before Width: | Height: | Size: 225 KiB |
Before Width: | Height: | Size: 228 KiB |
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 240 KiB |
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 199 KiB |
Before Width: | Height: | Size: 255 KiB After Width: | Height: | Size: 255 KiB |
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 253 KiB |
Before Width: | Height: | Size: 226 KiB After Width: | Height: | Size: 226 KiB |
Before Width: | Height: | Size: 235 KiB After Width: | Height: | Size: 235 KiB |
Before Width: | Height: | Size: 265 KiB After Width: | Height: | Size: 265 KiB |
Before Width: | Height: | Size: 229 KiB |
Before Width: | Height: | Size: 239 KiB |
Before Width: | Height: | Size: 234 KiB |
Before Width: | Height: | Size: 184 KiB |
Before Width: | Height: | Size: 217 KiB |
Before Width: | Height: | Size: 203 KiB |
Before Width: | Height: | Size: 190 KiB |
@ -1,5 +1,5 @@
|
||||
###############################################################################
|
||||
## POSE2SIM PROJECT PARAMETERS ##
|
||||
## PROJECT PARAMETERS ##
|
||||
###############################################################################
|
||||
|
||||
# Configure your project parameters here
|
||||
@ -9,45 +9,78 @@ project_dir = '' # BETWEEN SINGLE QUOTES! # If empty, project dir is current dir
|
||||
frame_range = [] #For example [10,300], or [] for all frames
|
||||
frame_rate = 60 #Hz
|
||||
|
||||
rawImg_folder_name = 'raw-2d'
|
||||
rawImg_folder_name = 'raw'
|
||||
calib_folder_name = 'calibration'
|
||||
pose_folder_name = 'pose'
|
||||
pose_json_folder_extension = 'json'
|
||||
pose_img_folder_extension = 'img'
|
||||
poseTracked_folder_name = 'pose-2d-tracked'
|
||||
pose3d_folder_name = 'triangulation'
|
||||
poseAssociated_folder_name = 'pose-associated'
|
||||
pose3d_folder_name = 'pose-3d'
|
||||
opensim_folder_name = 'opensim'
|
||||
|
||||
|
||||
[pose]
|
||||
pose_model = 'BODY_25B' #CUSTOM, BODY_25B, BODY_25, BODY_135, BLAZEPOSE,
|
||||
# HALPE_26, HALPE_68, HALPE_136, COCO_133, COCO, MPII are available,
|
||||
pose_model = 'BODY_25B' #CUSTOM, BODY_25B, BODY_25, BODY_135, BLAZEPOSE, HALPE_26, HALPE_68, HALPE_136, COCO_133, COCO, MPII are available,
|
||||
# from DeepLabCut, OpenPose, MediaPipe BlazePose, and AlphaPose
|
||||
# See Pose2Sim\skeleton.py for their skeleton hierarchy
|
||||
|
||||
|
||||
[calibration]
|
||||
type = 'qca' # 'qca', 'checkerboard', 'arucoboard', or 'charucoboard'
|
||||
[calibration.qca]
|
||||
binning_factor = 1 # Usually 1, except when filming in 540p where it usually is 2
|
||||
calibration_type = 'convert' # 'convert' or 'calculate'
|
||||
|
||||
[calibration.checkerboard]
|
||||
corners_nb = [7,12] # [H,W] rather than [w,h]
|
||||
square_size = 80 # mm # [h,w] if square is actually a rectangle
|
||||
frame_for_origin = -1 # starting from zero. -1 if board is at origin on last frame
|
||||
# /!\ Beware that corners must be detected on all view at frame_for_origin, or else
|
||||
# extrinsic parameters will be wrong. Set show_corner_detection to true to check it.
|
||||
show_corner_detection = false # true or false (lowercase)
|
||||
from_vid_or_img = 'img' # 'vid' or 'img'
|
||||
vid_snapshot_every_N_frames = 20
|
||||
vid_extension = 'mp4'
|
||||
img_extension = 'jpg' # 'png', 'jpg', etc
|
||||
[calibration.convert]
|
||||
convert_from = 'qualisys' # 'qualisys', 'optitrack', or 'vicon'
|
||||
[calibration.convert.qualisys]
|
||||
binning_factor = 1 # Usually 1, except when filming in 540p where it usually is 2
|
||||
|
||||
[2d-tracking]
|
||||
|
||||
[calibration.calculate]
|
||||
calculate_method = 'board' # 'board' or 'points'
|
||||
|
||||
[calibration.calculate.board.intrinsics] # camera properties, only needs to be done once
|
||||
intrinsics_board_type = 'checkerboard' # 'checkerboard' ('charucoboard' not supported yet)
|
||||
overwrite_intrinsics = false # overwrite (or not) if they have already been calculated?
|
||||
show_detection_intrinsics = true # true or false (lowercase)
|
||||
intrinsics_extension = 'jpg' # any video or image extension
|
||||
|
||||
extract_every_N_sec = 1 # if video, extract frames every N seconds (can be <1 )
|
||||
intrinsics_corners_nb = [4,7]
|
||||
intrinsics_square_size = 60 # mm
|
||||
intrinsics_marker_size = 40 # mm # only checked if charucoboard
|
||||
intrinsics_aruco_dict = 'DICT_6X6_250' # only checked if charucoboard # see https://docs.opencv.org/3.4/dc/df7/dictionary_8hpp.html
|
||||
|
||||
[calibration.calculate.board.extrinsics] # camera placement, needs to be done every time
|
||||
extrinsics_board_type = 'scene' # 'checkerboard', 'scene' ('charucoboard' not supported yet)
|
||||
# 'board' should be large enough to be detected when laid on the floor.
|
||||
# 'scene' involves manually clicking any point of know coordinates on scene. Usually more accurate if points are spread out
|
||||
calculate_extrinsics = true # true or false (lowercase)
|
||||
show_reprojection_error = true # true or false (lowercase)
|
||||
extrinsics_extension = 'png' # any video or image extension
|
||||
|
||||
# if extrinsics_board_type = 'checkerboard' or 'charucoboard'
|
||||
extrinsics_corners_nb = [4,7] # [H,W] rather than [w,h]
|
||||
extrinsics_square_size = 60 # mm # [h,w] if square is actually a rectangle
|
||||
extrinsics_marker_size = 40 # mm # only checked if 'charucoboard' (not supported yet)
|
||||
extrinsics_aruco_dict = 'DICT_6X6_250' # only checked if 'charucoboard' # see https://docs.opencv.org/3.4/dc/df7/dictionary_8hpp.html
|
||||
|
||||
# if extrinsics_board_type = 'scene'
|
||||
# list of 3D coordinates to be manually labelled on images. Can also be a 2 dimensional plane. # in m
|
||||
object_coords_3d = [[-2.0, 0.3, 0.0], [-2.0 , 0.0, 0.0], [-2.0, 0.0, 0.05], [-2.0, -0.3 , 0.0], [0.0, 0.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.05], [0.0, -0.3, 0.0]] # in meters -> Not in mm! <-
|
||||
|
||||
|
||||
[calibration.calculate.points]
|
||||
calibration_points = 'wand' # 'wand' or 'keypoints'
|
||||
# Not supported yet.
|
||||
|
||||
|
||||
[personAssociation]
|
||||
tracked_keypoint = 'Neck' # If the neck is not detected by the pose_model, check skeleton.py
|
||||
# and choose a stable point for tracking the person of interest (e.g., 'right_shoulder' with BLAZEPOSE)
|
||||
error_threshold_tracking = 20 # px
|
||||
reproj_error_threshold_association = 20 # px
|
||||
|
||||
[3d-triangulation]
|
||||
error_threshold_triangulation = 15 # px
|
||||
|
||||
[triangulation]
|
||||
reproj_error_threshold_triangulation = 15 # px
|
||||
likelihood_threshold = 0.3
|
||||
min_cameras_for_triangulation = 2
|
||||
interpolation = 'cubic' #linear, slinear, quadratic, cubic, or none
|
||||
@ -55,23 +88,26 @@ interpolation = 'cubic' #linear, slinear, quadratic, cubic, or none
|
||||
interp_if_gap_smaller_than = 10 # do not interpolate bigger gaps
|
||||
show_interp_indices = true # true or false (lowercase). For each keypoint, return the frames that need to be interpolated
|
||||
|
||||
[3d-filtering]
|
||||
type = 'butterworth' # butterworth, butterworth_on_speed, gaussian, LOESS, median
|
||||
|
||||
[filtering]
|
||||
type = 'butterworth' # butterworth, kalman, gaussian, LOESS, median, butterworth_on_speed
|
||||
display_figures = true # true or false (lowercase)
|
||||
|
||||
[3d-filtering.butterworth]
|
||||
type = 'low'
|
||||
[filtering.butterworth]
|
||||
order = 4
|
||||
cut_off_frequency = 6 # Hz
|
||||
[3d-filtering.butterworth_on_speed]
|
||||
type = 'low'
|
||||
[filtering.kalman]
|
||||
# How much more do you trust triangulation results (measurements), than previous data (process assuming constant acceleration)?
|
||||
trust_ratio = 100 # = measurement_trust/process_trust ~= process_noise/measurement_noise
|
||||
smooth = true # should be true, unless you need real-time filtering
|
||||
[filtering.butterworth_on_speed]
|
||||
order = 4
|
||||
cut_off_frequency = 10 # Hz
|
||||
[3d-filtering.gaussian]
|
||||
[filtering.gaussian]
|
||||
sigma_kernel = 2 #px
|
||||
[3d-filtering.LOESS]
|
||||
nb_values_used = 5 # = fraction of data used * nb frames
|
||||
[3d-filtering.median]
|
||||
[filtering.LOESS]
|
||||
nb_values_used = 30 # = fraction of data used * nb frames
|
||||
[filtering.median]
|
||||
kernel_size = 9
|
||||
|
||||
[opensim]
|
||||
|
@ -136,7 +136,7 @@ def read_qca(qca_path, binning_factor):
|
||||
|
||||
# Camera name
|
||||
for i, tag in enumerate(root.findall('cameras/camera')):
|
||||
ret += [float(tag.attrib.get('avg-residual'))/1000]
|
||||
ret += [float(tag.attrib.get('avg-residual'))]
|
||||
C += [tag.attrib.get('serial')]
|
||||
if tag.attrib.get('model') in ('Miqus Video', 'Miqus Video UnderWater', 'none'):
|
||||
vid_id += [i]
|
||||
@ -423,15 +423,13 @@ def calibrate_intrinsics(calib_dir, intrinsics_config_dict):
|
||||
logging.exception(f'The folder {os.path.join(calib_dir, "intrinsics", cam)} does not exist or does not contain any files with extension .{intrinsics_extension}.')
|
||||
raise ValueError(f'The folder {os.path.join(calib_dir, "intrinsics", cam)} does not exist or does not contain any files with extension .{intrinsics_extension}.')
|
||||
img_vid_files = sorted(img_vid_files, key=lambda c: [int(n) for n in re.findall(r'\d+', c)]) #sorting paths with numbers
|
||||
|
||||
# extract frames from video if video
|
||||
try:
|
||||
# check if file is a video rather than an image
|
||||
cap = cv2.VideoCapture(img_vid_files[0])
|
||||
cap.read()
|
||||
if cap.read()[0] == False:
|
||||
logging.exception('No video in the folder or wrong extension.')
|
||||
raise ValueError('No video in the folder or wrong extension.')
|
||||
# extract frames from video
|
||||
raise
|
||||
extract_frames(img_vid_files[0], extract_every_N_sec, overwrite_extraction)
|
||||
img_vid_files = glob.glob(os.path.join(calib_dir, 'intrinsics', cam, f'*.png'))
|
||||
img_vid_files = sorted(img_vid_files, key=lambda c: [int(n) for n in re.findall(r'\d+', c)])
|
||||
@ -442,16 +440,18 @@ def calibrate_intrinsics(calib_dir, intrinsics_config_dict):
|
||||
for img_path in img_vid_files:
|
||||
if show_detection_intrinsics == True:
|
||||
imgp_confirmed, objp_confirmed = findCorners(img_path, intrinsics_corners_nb, objp=objp, show=show_detection_intrinsics)
|
||||
print(len(imgp_confirmed), len(objp_confirmed))
|
||||
if isinstance(imgp_confirmed, np.ndarray):
|
||||
imgpoints.append(imgp_confirmed)
|
||||
objpoints.append(objp_confirmed)
|
||||
|
||||
else:
|
||||
imgp_confirmed = findCorners(img_path, intrinsics_corners_nb, objp=objp, show=show_detection_intrinsics)
|
||||
if isinstance(imgp_confirmed, np.ndarray):
|
||||
imgpoints.append(imgp_confirmed)
|
||||
objpoints.append(objp)
|
||||
if len(imgpoints) < 10:
|
||||
logging.info(f'Corners were detected only on {len(imgpoints)} images for camera {cam}. Calibration of intrinsic parameters may not be accurate with less than 10 good images of the board.')
|
||||
logging.info(f'Corners were detected only on {len(imgpoints)} images for camera {cam}. Calibration of intrinsic parameters may not be accurate with fewer than 10 good images of the board.')
|
||||
|
||||
# calculate intrinsics
|
||||
img = cv2.imread(str(img_path))
|
||||
@ -524,11 +524,12 @@ def calibrate_extrinsics(calib_dir, extrinsics_config_dict, C, S, K, D):
|
||||
logging.exception('No points clicked (or fewer than 6). Press \'C\' when the image is displayed, and then click on the image points corresponding to the \'object_coords_3d\' you measured and wrote down in the Config.toml file.')
|
||||
raise ValueError('No points clicked (or fewer than 6). Press \'C\' when the image is displayed, and then click on the image points corresponding to the \'object_coords_3d\' you measured and wrote down in the Config.toml file.')
|
||||
if len(objp) < 10:
|
||||
logging.info(f'Only {len(objp)} reference points for camera {cam}. Calibration of extrinsic parameters may not be accurate with less than 10 reference points, as spread out as possible.')
|
||||
logging.info(f'Only {len(objp)} reference points for camera {cam}. Calibration of extrinsic parameters may not be accurate with fewer than 10 reference points, as spread out as possible.')
|
||||
|
||||
# Calculate extrinsics
|
||||
mtx, dist = np.array(K[i]), np.array(D[i])
|
||||
_, r, t = cv2.solvePnP(objp, imgp, mtx, dist)
|
||||
r, t = r.flatten(), t.flatten()
|
||||
|
||||
# Projection of object points to image plane
|
||||
Kh_cam = np.block([mtx, np.zeros(3).reshape(3,1)])
|
||||
@ -545,9 +546,16 @@ def calibrate_extrinsics(calib_dir, extrinsics_config_dict, C, S, K, D):
|
||||
cv2.circle(img, (int(o[0]), int(o[1])), 8, (0,0,255), -1)
|
||||
for i in imgp:
|
||||
cv2.drawMarker(img, (int(i[0][0]), int(i[0][1])), (0,255,0), cv2.MARKER_CROSS, 15, 2)
|
||||
cv2.putText(img, 'Verify calibration results, then close window.', (20, 20), cv2.FONT_HERSHEY_SIMPLEX, .5, (255,255,255), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, 'Verify calibration results, then close window.', (20, 20), cv2.FONT_HERSHEY_SIMPLEX, .5, (0,0,0), 1, lineType = cv2.LINE_AA)
|
||||
cv2.drawMarker(img, (20,40), (0,255,0), cv2.MARKER_CROSS, 15, 2)
|
||||
cv2.putText(img, ' Clicked points', (20, 40), cv2.FONT_HERSHEY_SIMPLEX, .5, (255,255,255), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, ' Clicked points', (20, 40), cv2.FONT_HERSHEY_SIMPLEX, .5, (0,0,0), 1, lineType = cv2.LINE_AA)
|
||||
cv2.circle(img, (20,60), 8, (0,0,255), -1)
|
||||
cv2.putText(img, ' Reprojected object points', (20, 60), cv2.FONT_HERSHEY_SIMPLEX, .5, (255,255,255), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, ' Reprojected object points', (20, 60), cv2.FONT_HERSHEY_SIMPLEX, .5, (0,0,0), 1, lineType = cv2.LINE_AA)
|
||||
im_pil = Image.fromarray(img)
|
||||
print(img_vid_files[0])
|
||||
im_pil.show(title = img_vid_files[0])
|
||||
im_pil.show(title = os.path.basename(img_vid_files[0]))
|
||||
|
||||
# Calculate reprojection error
|
||||
imgp_to_objreproj_dist = [euclidean_distance(proj_obj[n], imgp[n]) for n in range(len(proj_obj))]
|
||||
@ -574,7 +582,7 @@ def findCorners(img_path, corner_nb, objp=[], show=True):
|
||||
|
||||
INPUTS:
|
||||
- img_path: path to image (or video)
|
||||
- corner_nb: [H, W] internal corners in checkerboard: list of two integers [9,6]
|
||||
- corner_nb: [H, W] internal corners in checkerboard: list of two integers [4,7]
|
||||
- optionnal: show: choose whether to show corner detections
|
||||
- optionnal: objp: array [3d corner coordinates]
|
||||
|
||||
@ -678,7 +686,7 @@ def imgp_objp_visualizer_clicker(img, imgp=[], objp=[], img_path=''):
|
||||
objp_confirmed = objp
|
||||
else:
|
||||
imgp_confirmed = np.array([imgp.astype('float32') for imgp in imgp_confirmed])
|
||||
objp_confirmed = np.array(objp_confirmed)
|
||||
objp_confirmed = objp_confirmed
|
||||
# OpenCV needs at leas 4 correspondance points to calibrate
|
||||
if len(imgp_confirmed) < 6:
|
||||
objp_confirmed = []
|
||||
@ -696,6 +704,9 @@ def imgp_objp_visualizer_clicker(img, imgp=[], objp=[], img_path=''):
|
||||
objp_confirmed = []
|
||||
|
||||
if event.key == 'c':
|
||||
# TODO: RIGHT NOW, IF 'C' IS PRESSED ANOTHER TIME, OBJP_CONFIRMED AND IMGP_CONFIRMED ARE RESET TO []
|
||||
if 'objp_confirmed' in globals():
|
||||
del objp_confirmed
|
||||
# If 'c', allows retrieving imgp_confirmed by clicking them on the image
|
||||
scat = ax.scatter([],[],s=100,marker='+',color='g')
|
||||
plt.connect('button_press_event', on_click)
|
||||
@ -731,7 +742,7 @@ def imgp_objp_visualizer_clicker(img, imgp=[], objp=[], img_path=''):
|
||||
fig_3d.canvas.draw()
|
||||
elif count == len(objp)-1:
|
||||
# if all objp have been clicked or indicated as not visible, close all
|
||||
imgp_confirmed = np.array(imgp)
|
||||
imgp_confirmed = np.array(imgp, np.float32)
|
||||
plt.close('all')
|
||||
for var_to_delete in ['events', 'count', 'scat', 'fig_3d', 'ax_3d', 'objp_confirmed_notok']:
|
||||
if var_to_delete in globals():
|
||||
@ -780,8 +791,8 @@ def imgp_objp_visualizer_clicker(img, imgp=[], objp=[], img_path=''):
|
||||
fig_3d.canvas.draw()
|
||||
elif count == len(objp)-1:
|
||||
# retrieve objp_confirmed
|
||||
objp_confirmed = np.array([[objp[count].tolist()] if 'objp_confirmed' not in globals() else objp_confirmed+[objp[count]]][0])
|
||||
imgp_confirmed = np.array(imgp_confirmed)
|
||||
objp_confirmed = np.array([[objp[count]] if 'objp_confirmed' not in globals() else objp_confirmed+[objp[count]]][0])
|
||||
imgp_confirmed = np.array(imgp_confirmed, np.float32)
|
||||
# close all, delete all
|
||||
plt.close('all')
|
||||
for var_to_delete in ['events', 'count', 'scat', 'scat_3d', 'fig_3d', 'ax_3d', 'objp_confirmed_notok']:
|
||||
@ -792,6 +803,8 @@ def imgp_objp_visualizer_clicker(img, imgp=[], objp=[], img_path=''):
|
||||
objp_confirmed = [[objp[count]] if 'objp_confirmed' not in globals() else objp_confirmed+[objp[count]]][0]
|
||||
ax_3d.scatter(*objp[count], marker='o', color='g')
|
||||
fig_3d.canvas.draw()
|
||||
print(objp_confirmed)
|
||||
|
||||
|
||||
# Right click:
|
||||
# If last event was left click, remove last point and if objp given, from objp_confirmed
|
||||
@ -858,20 +871,20 @@ def imgp_objp_visualizer_clicker(img, imgp=[], objp=[], img_path=''):
|
||||
ax.set_zlim3d([z_middle - plot_radius, z_middle + plot_radius])
|
||||
|
||||
# Write instructions
|
||||
cv2.putText(img, 'Type "Y" to accept point detection.', (20, 20), cv2.FONT_HERSHEY_SIMPLEX, .5, (255,255,255), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, 'Type "Y" to accept point detection.', (20, 20), cv2.FONT_HERSHEY_SIMPLEX, .5, (0,0,0), 1, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, 'If points are wrongfully (or not) detected:', (20, 40), cv2.FONT_HERSHEY_SIMPLEX, .5, (255,255,255), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, 'If points are wrongfully (or not) detected:', (20, 40), cv2.FONT_HERSHEY_SIMPLEX, .5, (0,0,0), 1, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, '- type "N" to dismiss this image,', (20, 60), cv2.FONT_HERSHEY_SIMPLEX, .5, (255,255,255), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, '- type "N" to dismiss this image,', (20, 60), cv2.FONT_HERSHEY_SIMPLEX, .5, (0,0,0), 1, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, '- type "C" to click points by hand (beware of their order).', (20, 80), cv2.FONT_HERSHEY_SIMPLEX, .5, (255,255,255), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, '- type "C" to click points by hand (beware of their order).', (20, 80), cv2.FONT_HERSHEY_SIMPLEX, .5, (0,0,0), 1, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, ' left click to add a point, right click to remove it, "H" to indicate it is not visible. ', (20, 100), cv2.FONT_HERSHEY_SIMPLEX, .5, (255,255,255), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, ' left click to add a point, right click to remove it, "H" to indicate it is not visible. ', (20, 100), cv2.FONT_HERSHEY_SIMPLEX, .5, (0,0,0), 1, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, ' Confirm with "Y", cancel with "N".', (20, 120), cv2.FONT_HERSHEY_SIMPLEX, .5, (255,255,255), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, ' Confirm with "Y", cancel with "N".', (20, 120), cv2.FONT_HERSHEY_SIMPLEX, .5, (0,0,0), 1, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, 'Use mouse wheel to zoom in and out and to pan', (20, 140), cv2.FONT_HERSHEY_SIMPLEX, .5, (255,255,255), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, 'Use mouse wheel to zoom in and out and to pan', (20, 140), cv2.FONT_HERSHEY_SIMPLEX, .5, (0,0,0), 1, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, 'Type "Y" to accept point detection.', (20, 20), cv2.FONT_HERSHEY_SIMPLEX, .7, (255,255,255), 3, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, 'Type "Y" to accept point detection.', (20, 20), cv2.FONT_HERSHEY_SIMPLEX, .7, (0,0,0), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, 'If points are wrongfully (or not) detected:', (20, 43), cv2.FONT_HERSHEY_SIMPLEX, .7, (255,255,255), 3, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, 'If points are wrongfully (or not) detected:', (20, 43), cv2.FONT_HERSHEY_SIMPLEX, .7, (0,0,0), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, '- type "N" to dismiss this image,', (20, 66), cv2.FONT_HERSHEY_SIMPLEX, .7, (255,255,255), 3, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, '- type "N" to dismiss this image,', (20, 66), cv2.FONT_HERSHEY_SIMPLEX, .7, (0,0,0), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, '- type "C" to click points by hand (beware of their order).', (20, 89), cv2.FONT_HERSHEY_SIMPLEX, .7, (255,255,255), 3, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, '- type "C" to click points by hand (beware of their order).', (20, 89), cv2.FONT_HERSHEY_SIMPLEX, .7, (0,0,0), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, ' left click to add a point, right click to remove it, "H" to indicate it is not visible. ', (20, 112), cv2.FONT_HERSHEY_SIMPLEX, .7, (255,255,255), 3, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, ' left click to add a point, right click to remove it, "H" to indicate it is not visible. ', (20, 112), cv2.FONT_HERSHEY_SIMPLEX, .7, (0,0,0), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, ' Confirm with "Y", cancel with "N".', (20, 135), cv2.FONT_HERSHEY_SIMPLEX, .7, (255,255,255), 3, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, ' Confirm with "Y", cancel with "N".', (20, 135), cv2.FONT_HERSHEY_SIMPLEX, .7, (0,0,0), 2, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, 'Use mouse wheel to zoom in and out and to pan', (20, 158), cv2.FONT_HERSHEY_SIMPLEX, .7, (255,255,255), 3, lineType = cv2.LINE_AA)
|
||||
cv2.putText(img, 'Use mouse wheel to zoom in and out and to pan', (20, 158), cv2.FONT_HERSHEY_SIMPLEX, .7, (0,0,0), 2, lineType = cv2.LINE_AA)
|
||||
|
||||
# Put image in a matplotlib figure for more controls
|
||||
plt.rcParams['toolbar'] = 'None'
|
||||
@ -997,15 +1010,14 @@ def recap_calibrate(ret, calib_path, calib_full_type):
|
||||
if cam != 'metadata':
|
||||
f_px = calib[cam]['matrix'][0][0]
|
||||
Dm = euclidean_distance(calib[cam]['translation'], [0,0,0])
|
||||
print(ret[c])
|
||||
if calib_full_type=='convert_qualisys' or calib_full_type=='convert_vicon':
|
||||
ret_m.append( np.around(ret[c]*1000, decimals=3) )
|
||||
ret_px.append( np.around(ret[c] / Dm * f_px, decimals=3) )
|
||||
ret_m.append( np.around(ret[c], decimals=3) )
|
||||
ret_px.append( np.around(ret[c] / (Dm*1000) * f_px, decimals=3) )
|
||||
elif calib_full_type=='calculate_board':
|
||||
ret_px.append( np.around(ret[c], decimals=3) )
|
||||
ret_m.append( np.around(ret[c]*Dm / f_px, decimals=3) )
|
||||
ret_m.append( np.around(ret[c]*Dm*1000 / f_px, decimals=3) )
|
||||
|
||||
logging.info(f'\n--> Residual (RMS) calibration errors for each camera are respectively {ret_px} px, \nwhich corresponds to {ret_m} m.\n')
|
||||
logging.info(f'\n--> Residual (RMS) calibration errors for each camera are respectively {ret_px} px, \nwhich corresponds to {ret_m} mm.\n')
|
||||
logging.info(f'Calibration file is stored at {calib_path}.')
|
||||
|
||||
|
||||
|
@ -150,8 +150,8 @@ def kalman_filter_1d(config, col):
|
||||
- col_filtered: Filtered pandas dataframe column
|
||||
'''
|
||||
|
||||
trustratio = int(config.get('3d-filtering').get('kalman').get('trust_ratio'))
|
||||
smooth = int(config.get('3d-filtering').get('kalman').get('smooth'))
|
||||
trustratio = int(config.get('filtering').get('kalman').get('trust_ratio'))
|
||||
smooth = int(config.get('filtering').get('kalman').get('smooth'))
|
||||
framerate = config.get('project').get('frame_rate')
|
||||
measurement_noise = 20
|
||||
process_noise = measurement_noise * trustratio
|
||||
@ -187,9 +187,9 @@ def butterworth_filter_1d(config, col):
|
||||
- col_filtered: Filtered pandas dataframe column
|
||||
'''
|
||||
|
||||
type = 'low' #config.get('3d-filtering').get('butterworth').get('type')
|
||||
order = int(config.get('3d-filtering').get('butterworth').get('order'))
|
||||
cutoff = int(config.get('3d-filtering').get('butterworth').get('cut_off_frequency'))
|
||||
type = 'low' #config.get('filtering').get('butterworth').get('type')
|
||||
order = int(config.get('filtering').get('butterworth').get('order'))
|
||||
cutoff = int(config.get('filtering').get('butterworth').get('cut_off_frequency'))
|
||||
framerate = config.get('project').get('frame_rate')
|
||||
|
||||
b, a = signal.butter(order/2, cutoff/(framerate/2), type, analog = False)
|
||||
@ -223,9 +223,9 @@ def butterworth_on_speed_filter_1d(config, col):
|
||||
- col_filtered: Filtered pandas dataframe column
|
||||
'''
|
||||
|
||||
type = 'low' # config.get('3d-filtering').get('butterworth_on_speed').get('type')
|
||||
order = int(config.get('3d-filtering').get('butterworth_on_speed').get('order'))
|
||||
cutoff = int(config.get('3d-filtering').get('butterworth_on_speed').get('cut_off_frequency'))
|
||||
type = 'low' # config.get('filtering').get('butterworth_on_speed').get('type')
|
||||
order = int(config.get('filtering').get('butterworth_on_speed').get('order'))
|
||||
cutoff = int(config.get('filtering').get('butterworth_on_speed').get('cut_off_frequency'))
|
||||
framerate = config.get('project').get('frame_rate')
|
||||
|
||||
b, a = signal.butter(order/2, cutoff/(framerate/2), type, analog = False)
|
||||
@ -264,7 +264,7 @@ def gaussian_filter_1d(config, col):
|
||||
- col_filtered: Filtered pandas dataframe column
|
||||
'''
|
||||
|
||||
gaussian_filter_sigma_kernel = int(config.get('3d-filtering').get('gaussian').get('sigma_kernel'))
|
||||
gaussian_filter_sigma_kernel = int(config.get('filtering').get('gaussian').get('sigma_kernel'))
|
||||
|
||||
col_filtered = gaussian_filter1d(col, gaussian_filter_sigma_kernel)
|
||||
|
||||
@ -284,7 +284,7 @@ def loess_filter_1d(config, col):
|
||||
- col_filtered: Filtered pandas dataframe column
|
||||
'''
|
||||
|
||||
kernel = config.get('3d-filtering').get('LOESS').get('nb_values_used')
|
||||
kernel = config.get('filtering').get('LOESS').get('nb_values_used')
|
||||
|
||||
col_filtered = col.copy()
|
||||
mask = np.isnan(col_filtered)
|
||||
@ -313,7 +313,7 @@ def median_filter_1d(config, col):
|
||||
- col_filtered: Filtered pandas dataframe column
|
||||
'''
|
||||
|
||||
median_filter_kernel_size = config.get('3d-filtering').get('median').get('kernel_size')
|
||||
median_filter_kernel_size = config.get('filtering').get('median').get('kernel_size')
|
||||
|
||||
col_filtered = signal.medfilt(col, kernel_size=median_filter_kernel_size)
|
||||
|
||||
@ -402,19 +402,19 @@ def recap_filter3d(config, trc_path):
|
||||
'''
|
||||
|
||||
# Read Config
|
||||
filter_type = config.get('3d-filtering').get('type')
|
||||
kalman_filter_trustratio = int(config.get('3d-filtering').get('kalman').get('trust_ratio'))
|
||||
kalman_filter_smooth = int(config.get('3d-filtering').get('kalman').get('smooth'))
|
||||
filter_type = config.get('filtering').get('type')
|
||||
kalman_filter_trustratio = int(config.get('filtering').get('kalman').get('trust_ratio'))
|
||||
kalman_filter_smooth = int(config.get('filtering').get('kalman').get('smooth'))
|
||||
kalman_filter_smooth_str = 'smoother' if kalman_filter_smooth else 'filter'
|
||||
butterworth_filter_type = 'low' # config.get('3d-filtering').get('butterworth').get('type')
|
||||
butterworth_filter_order = int(config.get('3d-filtering').get('butterworth').get('order'))
|
||||
butterworth_filter_cutoff = int(config.get('3d-filtering').get('butterworth').get('cut_off_frequency'))
|
||||
butter_speed_filter_type = 'low' # config.get('3d-filtering').get('butterworth_on_speed').get('type')
|
||||
butter_speed_filter_order = int(config.get('3d-filtering').get('butterworth_on_speed').get('order'))
|
||||
butter_speed_filter_cutoff = int(config.get('3d-filtering').get('butterworth_on_speed').get('cut_off_frequency'))
|
||||
gaussian_filter_sigma_kernel = int(config.get('3d-filtering').get('gaussian').get('sigma_kernel'))
|
||||
loess_filter_nb_values = config.get('3d-filtering').get('LOESS').get('nb_values_used')
|
||||
median_filter_kernel_size = config.get('3d-filtering').get('median').get('kernel_size')
|
||||
butterworth_filter_type = 'low' # config.get('filtering').get('butterworth').get('type')
|
||||
butterworth_filter_order = int(config.get('filtering').get('butterworth').get('order'))
|
||||
butterworth_filter_cutoff = int(config.get('filtering').get('butterworth').get('cut_off_frequency'))
|
||||
butter_speed_filter_type = 'low' # config.get('filtering').get('butterworth_on_speed').get('type')
|
||||
butter_speed_filter_order = int(config.get('filtering').get('butterworth_on_speed').get('order'))
|
||||
butter_speed_filter_cutoff = int(config.get('filtering').get('butterworth_on_speed').get('cut_off_frequency'))
|
||||
gaussian_filter_sigma_kernel = int(config.get('filtering').get('gaussian').get('sigma_kernel'))
|
||||
loess_filter_nb_values = config.get('filtering').get('LOESS').get('nb_values_used')
|
||||
median_filter_kernel_size = config.get('filtering').get('median').get('kernel_size')
|
||||
|
||||
# Recap
|
||||
filter_mapping_recap = {
|
||||
|
@ -192,7 +192,7 @@ def recap_tracking(config, error, nb_cams_excluded):
|
||||
# Read config
|
||||
project_dir = config.get('project').get('project_dir')
|
||||
if project_dir == '': project_dir = os.getcwd()
|
||||
poseTracked_folder_name = config.get('project').get('poseTracked_folder_name')
|
||||
poseTracked_folder_name = config.get('project').get('poseAssociated_folder_name')
|
||||
calib_folder_name = config.get('project').get('calib_folder_name')
|
||||
tracked_keypoint = config.get('personAssociation').get('tracked_keypoint')
|
||||
error_threshold_tracking = config.get('personAssociation').get('error_threshold_tracking')
|
||||
|
@ -413,7 +413,7 @@ def triangulate_all(config):
|
||||
interp_gap_smaller_than = config.get('triangulation').get('interp_if_gap_smaller_than')
|
||||
show_interp_indices = config.get('triangulation').get('show_interp_indices')
|
||||
pose_dir = os.path.join(project_dir, pose_folder_name)
|
||||
poseTracked_folder_name = config.get('project').get('poseTracked_folder_name')
|
||||
poseTracked_folder_name = config.get('project').get('poseAssociated_folder_name')
|
||||
calib_dir = os.path.join(project_dir, calib_folder_name)
|
||||
calib_file = glob.glob(os.path.join(calib_dir, '*.toml'))[0]
|
||||
poseTracked_dir = os.path.join(project_dir, poseTracked_folder_name)
|
||||
@ -495,6 +495,7 @@ def triangulate_all(config):
|
||||
non_interp_frames = [[f'{seq[0]}:{seq[-1]+1}' for seq in seq_kpt if len(seq)>interp_gap_smaller_than] for seq_kpt in sequences]
|
||||
else:
|
||||
interp_frames = None
|
||||
non_interp_frames = []
|
||||
|
||||
# Interpolate missing values
|
||||
if interpolation_kind != 'none':
|
||||
|
@ -98,7 +98,7 @@ You should obtain a plot of all the 3D coordinates trajectories. You can check t
|
||||
Results are stored as .trc files in the `Demo/pose-3d` directory.
|
||||
|
||||
*N.B.:* Default parameters have been provided in `Demo\Users\Config.toml` but can be edited.\
|
||||
**Try calibration tool by changing `calibration_type` to `calculate` instead of `convert` (more info [there](#calculate-from-scratch)).**
|
||||
*N.B.:* *Try calibration tool by changing `calibration_type` to `calculate` instead of `convert` (more info [there](#calculate-from-scratch)).*
|
||||
<br/>
|
||||
|
||||
## Demonstration Part-2: Obtain 3D joint angles with OpenSim
|
||||
@ -256,6 +256,7 @@ If you already have a calibration file, set `calibration_type` type to `convert`
|
||||
|
||||
- **With a board:**
|
||||
> *N.B.:* Try the calibration tool on the Demo by changing `calibration_type` to `calculate` instead of `convert` in `Config.toml`.\
|
||||
For the sake of practicality, there are voluntarily few images for intrinsics, and few clicked points for extrinsics. *You should use more of them.* In spite of this, your reprojection error should be under 1-2 cm, which [does not hinder the quality of kinematic results in practice](https://www.mdpi.com/1424-8220/21/19/6530/htm).
|
||||
|
||||
- **Calculate intrinsic parameters:**
|
||||
|
||||
|