diff --git a/monoloco/activity.py b/monoloco/activity.py index 5ba7676..f910225 100644 --- a/monoloco/activity.py +++ b/monoloco/activity.py @@ -66,22 +66,51 @@ def social_interactions(idx, centers, angles, dds, stds=None, social_distance=Fa return False -def is_raising_hand(keypoint): +def is_raising_hand(kp): """ Returns flag of alert if someone raises their hand """ + x=0 + y=1 + + nose = 0 + l_ear = 3 l_shoulder = 5 + l_elbow = 7 l_hand = 9 + r_ear = 4 r_shoulder = 6 + r_elbow = 8 r_hand = 10 - if keypoint[1][l_hand] < keypoint[1][l_shoulder] and keypoint[1][r_hand] < keypoint[1][r_shoulder]: + head_width = kp[x][l_ear]- kp[x][r_ear] + head_top = (4/5) * (kp[y][nose] - head_width) + + l_forearm = [kp[x][l_hand] - kp[x][l_elbow], kp[y][l_hand] - kp[y][l_elbow]] + l_arm = [kp[x][l_shoulder] - kp[x][l_elbow], kp[y][l_shoulder] - kp[y][l_elbow]] + + r_forearm = [kp[x][r_hand] - kp[x][r_elbow], kp[y][r_hand] - kp[y][r_elbow]] + r_arm = [kp[x][r_shoulder] - kp[x][r_elbow], kp[y][r_shoulder] - kp[y][r_elbow]] + + l_angle = (90/np.pi) * np.arccos(np.dot(l_forearm/np.linalg.norm(l_forearm), l_arm/np.linalg.norm(l_arm))) + r_angle = (90/np.pi) * np.arccos(np.dot(r_forearm/np.linalg.norm(r_forearm), r_arm/np.linalg.norm(r_arm))) + + is_l_up = kp[y][l_hand] < kp[y][l_shoulder] + is_r_up = kp[y][r_hand] < kp[y][r_shoulder] + + l_too_close = kp[x][l_hand] <= kp[x][l_shoulder] and kp[y][l_hand]>=head_top + r_too_close = kp[x][r_hand] >= kp[x][r_shoulder] and kp[y][r_hand]>=head_top + + is_left_risen = is_l_up and l_angle >= 30 and not l_too_close + is_right_risen = is_r_up and r_angle >= 30 and not r_too_close + + if is_left_risen and is_right_risen: return 'both' - if keypoint[1][l_hand] < keypoint[1][l_shoulder]: + if is_left_risen: return 'left' - if keypoint[1][r_hand] < keypoint[1][r_shoulder]: + if is_right_risen: return 'right' return 'none' diff --git a/monoloco/run.py b/monoloco/run.py index 713721f..8d7d319 100644 --- a/monoloco/run.py +++ b/monoloco/run.py @@ -19,7 +19,7 @@ def cli(): predict_parser.add_argument('images', nargs='*', help='input images') predict_parser.add_argument('--glob', help='glob expression for input images (for many images)') predict_parser.add_argument('-o', '--output-directory', help='Output directory') - predict_parser.add_argument('--output_types', nargs='+', default=['json'], + predict_parser.add_argument('--output_types', nargs='+', help='what to output: json keypoints skeleton for Pifpaf' 'json bird front or multi for MonStereo') predict_parser.add_argument('--no_save', help='to show images', action='store_true') @@ -131,6 +131,8 @@ def main(): from .visuals.webcam import webcam webcam(args) else: + if args.output_types is None: + args.output_types = ['json'] from .predict import predict predict(args) diff --git a/monoloco/visuals/pifpaf_show.py b/monoloco/visuals/pifpaf_show.py index 5c10ae5..d0e18d6 100644 --- a/monoloco/visuals/pifpaf_show.py +++ b/monoloco/visuals/pifpaf_show.py @@ -103,7 +103,7 @@ class KeypointPainter(object): linewidth = np.sqrt((x[9]-x[7])**2 + (y[9]-y[7])**2) if ((connection[0] == 6 and connection[1] == 8) or (connection[0] == 8 and connection[1] == 10)) and raise_hand in ['right', 'both']: c = 'yellow' - linewidth = np.sqrt((x[9]-x[7])**2 + (y[9]-y[7])**2) + linewidth = np.sqrt((x[10]-x[8])**2 + (y[10]-y[8])**2) if self.color_connections: c = matplotlib.cm.get_cmap('tab20')(ci / len(self.skeleton)) if np.all(v[connection] > self.dashed_threshold): @@ -153,7 +153,7 @@ class KeypointPainter(object): ax.text(x1, y1, '{:.4f}'.format(score), fontsize=8, color=color) @staticmethod - def _draw_text(ax, x, y, v, text, color): + def _draw_text(ax, x, y, v, text, color, fontsize=8): if not np.any(v > 0): return @@ -167,7 +167,7 @@ class KeypointPainter(object): y1 -= 2.0 y2 += 2.0 - ax.text(x1 + 2, y1 - 2, text, fontsize=8, + ax.text(x1 + 2, y1 - 2, text, fontsize=fontsize, color='white', bbox={'facecolor': color, 'alpha': 0.5, 'linewidth': 0}) @staticmethod @@ -208,7 +208,7 @@ class KeypointPainter(object): if score is not None: z_str = str(score).split(sep='.') text = z_str[0] + '.' + z_str[1][0] - self._draw_text(ax, x-2, y, v, text, color) + self._draw_text(ax, x[1:3], y[1:3]-5, v[1:3], text, color, fontsize=16) if self.show_box: score = scores[i] if scores is not None else None self._draw_box(ax, x, y, v, color, score) diff --git a/monoloco/visuals/printer.py b/monoloco/visuals/printer.py index 0d82850..94ae192 100644 --- a/monoloco/visuals/printer.py +++ b/monoloco/visuals/printer.py @@ -417,6 +417,7 @@ class Printer: uv_max = [0., float(self.height)] xyz_max = pixel_to_camera(uv_max, self.kk, self.z_max) x_max = abs(xyz_max[0]) # shortcut to avoid oval circles in case of different kk + x_max=6 corr = round(float(x_max / 3)) ax.plot([0, x_max], [0, self.z_max], 'k--') ax.plot([0, -x_max], [0, self.z_max], 'k--') diff --git a/monoloco/visuals/webcam.py b/monoloco/visuals/webcam.py index e7c46a8..d8778ff 100644 --- a/monoloco/visuals/webcam.py +++ b/monoloco/visuals/webcam.py @@ -13,7 +13,10 @@ import logging import torch import matplotlib.pyplot as plt from PIL import Image -import cv2 +try: + import cv2 +except ImportError: + cv2 = None from openpifpaf import decoder, network, visualizer, show, logger import openpifpaf.datasets as datasets @@ -33,6 +36,15 @@ def factory_from_args(args): args.checkpoint = dic_models['keypoints'] logger.configure(args, LOG) # logger first + + if args.output_types is None: + args.output_types = ['multi'] + + assert 'bird' not in args.output_types + if 'json' not in args.output_types: + assert len(args.output_types) is 1 + else: + assert len(args.output_types) < 3 # Devices args.device = torch.device('cpu') @@ -67,6 +79,7 @@ def factory_from_args(args): def webcam(args): assert args.mode in ('mono') + args, dic_models = factory_from_args(args) # Load Models @@ -175,7 +188,7 @@ class Visualizer: axes[1].lines = [axes[1].lines[0], axes[1].lines[1]] axes[1].texts = [] - if dic_out: + if dic_out and dic_out['dds_pred']: printer._process_results(dic_out) printer.draw(figures, axes, image, dic_out, pifpaf_outs['left']) mypause(0.01)