def test_draw_line_1_1(): """One keypoing but no full body line. No image should be saved.""" config = _fall_detect_config() fall_detector = FallDetector(**config) image = _get_image(file_name="fall_img_1.png") pose_dix = {fall_detector.LEFT_SHOULDER: [0, 0]} lines_drawn = fall_detector.draw_lines(image, pose_dix, 0.5) assert lines_drawn == 0
def test_bad_sample_good_sample(): """One bad sample should not prevent good samples from being processed.""" config = _fall_detect_config() result = 'nothing passed to me' def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result object_detector = ObjectDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) object_detector.connect_to_next_element(output) # bad sample object_detector.receive_next_sample(image=None) assert result == 'nothing passed to me' # good sample fall_detector = FallDetector(**config) fall_detector.connect_to_next_element(output) img_1 = _get_image(file_name='fall_img_1.png') img_2 = _get_image(file_name='fall_img_2.png') fall_detector.receive_next_sample(image=img_1) fall_detector.min_time_between_frames = 0.01 time.sleep(fall_detector.min_time_between_frames) fall_detector.receive_next_sample(image=img_2) assert result assert len(result) == 1 category, confidence, box, angle = result[0] assert box # Add this line to avoid 'Unused local variable' assert category == 'FALL' assert confidence > 0.7 assert angle > 60
def test_fall_detection_case_5(): """Expected to not detect a fall even the angle criteria is met because image 2 is standing up rather than fall""" config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) # The frame represents a person falls. img_1 = _get_image(file_name="fall_img_2.png") # The frame represents a person who is in a standing position. img_2 = _get_image(file_name="fall_img_1.png") fall_detector.receive_next_sample(image=img_1) fall_detector.min_time_between_frames = 0.01 time.sleep(fall_detector.min_time_between_frames) fall_detector.receive_next_sample(image=img_2) assert not result
def test_fall_detection_case_3(): """Expect to detect a fall as key-points are detected by rotating the image.""" config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) img_1 = _get_image(file_name='fall_img_11.png') img_2 = _get_image(file_name='fall_img_12.png') fall_detector.receive_next_sample(image=img_1) # set min time to a small number to speed up testing fall_detector.min_time_between_frames = 0.01 time.sleep(fall_detector.min_time_between_frames) fall_detector.receive_next_sample(image=img_2) assert result assert len(result) == 1 category, confidence, box, angle = result[0] assert box # Add this line to avoid 'Unused local variable' assert category == 'FALL' assert confidence > 0.3 assert angle > 60
def test_fall_detection_case_2_2(): """Expected to detect a fall because key-points are detected, the angle criteria is met and the time distance between frames is not too short.""" config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) img_1 = _get_image(file_name='fall_img_1.png') img_2 = _get_image(file_name='fall_img_2.png') fall_detector.receive_next_sample(image=img_1) fall_detector.min_time_between_frames = 0.01 time.sleep(fall_detector.min_time_between_frames) fall_detector.receive_next_sample(image=img_2) assert result assert len(result) == 1 category, confidence, box, angle = result[0] assert box # Add this line to avoid 'Unused local variable' assert category == 'FALL' assert confidence > 0.7 assert angle > 60
def test_fall_detection_case_8(): """Expect to not detect a fall""" config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) # No person in a frame img_1 = _get_image(file_name="fall_img_6.png") # The frame represents a person who is in a standing position. img_2 = _get_image(file_name="fall_img_7.png") fall_detector.receive_next_sample(image=img_1) # set min time to a small number to speed up testing fall_detector.min_time_between_frames = 0.01 time.sleep(fall_detector.min_time_between_frames) fall_detector.receive_next_sample(image=img_2) assert not result
def test_fall_detection_case_2_1(): """Expected to not detect a fall even though key-points are detected and the angle criteria is met. However the time distance between frames is too short.""" config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) # The frame represents a person who is in a standing position. img_1 = _get_image(file_name="fall_img_1.png") # The frame represents a person falls. img_2 = _get_image(file_name="fall_img_2.png") start_time = time.monotonic() fall_detector.receive_next_sample(image=img_1) end_time = time.monotonic() safe_min = end_time - start_time + 1 # set min time to a sufficiently big number to ensure test passes # on slow environments # the goal is to simulate two frames that are too close in time # to be considered for a fall detection sequence fall_detector.min_time_between_frames = safe_min fall_detector.receive_next_sample(image=img_2) assert not result
def test_fall_detection_case_1(): """Expected to not detect a fall as key-points are not detected.""" config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) # The frame represents a person who is in a standing position. img_1 = _get_image(file_name="fall_img_1.png") # The frame represents a person completely falls. img_2 = _get_image(file_name="fall_img_3.png") fall_detector.receive_next_sample(image=img_1) fall_detector.min_time_between_frames = 0.01 time.sleep(fall_detector.min_time_between_frames) fall_detector.receive_next_sample(image=img_2) assert not result
def test_draw_line_1(): """One body line passed to draw. Image with one line should be saved.""" config = _fall_detect_config() fall_detector = FallDetector(**config) image = _get_image(file_name="fall_img_1.png") pose_dix = { fall_detector.LEFT_SHOULDER: [0, 0], fall_detector.LEFT_HIP: [0, 1] } lines_drawn = fall_detector.draw_lines(image, pose_dix, 0.5) assert lines_drawn == 1
def test_draw_line_0(): """No body lines passed to draw. No image should be saved.""" config = _fall_detect_config() fall_detector = FallDetector(**config) image = _get_image(file_name="fall_img_1.png") pose_dix = None lines_drawn = fall_detector.draw_lines(image, pose_dix, 0.5) assert lines_drawn == 0 pose_dix = {} lines_drawn = fall_detector.draw_lines(image, pose_dix, 0.5) assert lines_drawn == 0
def test_draw_line_2(): """Two body lines passed to draw. Image with two lines should be saved.""" config = _fall_detect_config() fall_detector = FallDetector(**config) # The frame represents a person who is in a standing position. image = _get_image(file_name="fall_img_1.png") pose_dix = { fall_detector.LEFT_SHOULDER: [0, 0], fall_detector.LEFT_HIP: [0, 1], fall_detector.RIGHT_SHOULDER: [1, 0], fall_detector.RIGHT_HIP: [1, 1], } lines_drawn = fall_detector.draw_lines(image, pose_dix, 0.5) assert lines_drawn == 2
def test_config_confidence_threshold(): """Verify against known confidence threshold. Make sure it propagates at all levels.""" config = _fall_detect_config() fall_detector = FallDetector(**config) tfe = fall_detector._tfengine pe = fall_detector._pose_engine assert fall_detector.confidence_threshold == config["confidence_threshold"] assert pe.confidence_threshold == config["confidence_threshold"] assert tfe.confidence_threshold == config["confidence_threshold"] config["confidence_threshold"] = 0.457 fall_detector = FallDetector(**config) tfe = fall_detector._tfengine pe = fall_detector._pose_engine assert fall_detector.confidence_threshold == config["confidence_threshold"] assert pe.confidence_threshold == config["confidence_threshold"] assert tfe.confidence_threshold == config["confidence_threshold"]
def test_one_person(): """Expect to detect a fall.""" config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) img_1 = _get_image(file_name='basic_fall_1.jpg') img_2 = _get_image(file_name='basic_fall_2.jpg') fall_detector.receive_next_sample(image=img_1) fall_detector.receive_next_sample(image=img_2) assert result assert len(result) == 1 category, confidence, (x0, y0, x1, y1) = result[0] assert category == 'FALL' assert confidence > 0.7 assert x0 > 0 and x0 < x1 assert y0 > 0 and y0 < y1
def test_model_inputs(): """Verify against known model inputs.""" config = _fall_detect_config() fall_detector = FallDetector(**config) tfe = fall_detector._tfengine samples = tfe.input_details[0]['shape'][0] assert samples == 1 height = tfe.input_details[0]['shape'][1] assert height == 300 width = tfe.input_details[0]['shape'][2] assert width == 300 colors = tfe.input_details[0]['shape'][3] assert colors == 3
def test_bad_sample_good_sample(): """One bad sample should not prevent good samples from being processed.""" config = _fall_detect_config() result = "nothing passed to me" def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result object_detector = ObjectDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) object_detector.connect_to_next_element(output) # bad sample object_detector.receive_next_sample(image=None) assert result == "nothing passed to me" # good sample fall_detector = FallDetector(**config) fall_detector.connect_to_next_element(output) # The frame represents a person who is in a standing position. img_1 = _get_image(file_name="fall_img_1.png") # The frame represents a person falls. img_2 = _get_image(file_name="fall_img_2.png") fall_detector.receive_next_sample(image=img_1) fall_detector.min_time_between_frames = 0.01 time.sleep(fall_detector.min_time_between_frames) fall_detector.receive_next_sample(image=img_2) assert result assert len(result) == 1 category = result[0]["label"] confidence = result[0]["confidence"] angle = result[0]["leaning_angle"] keypoint_corr = result[0]["keypoint_corr"] assert keypoint_corr assert category == "FALL" assert confidence > 0.7 assert angle > 60
def test_fall_detection_case_3_2(): """Expect to detect a fall as key-points are detected by rotating the image counter clockwise.""" config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) # The frame represents a person who is in a standing position. img_1 = _get_image(file_name="fall_img_11_flip.png") # The frame represents a person completely falls. img_2 = _get_image(file_name="fall_img_12_flip.png") fall_detector.receive_next_sample(image=img_1) # set min time to a small number to speed up testing fall_detector.min_time_between_frames = 0.01 time.sleep(fall_detector.min_time_between_frames) fall_detector.receive_next_sample(image=img_2) assert result assert len(result) == 1 category = result[0]["label"] confidence = result[0]["confidence"] angle = result[0]["leaning_angle"] keypoint_corr = result[0]["keypoint_corr"] assert keypoint_corr assert category == "FALL" assert confidence > 0.3 assert angle > 60
def test_model_outputs(): """Verify against known model outputs.""" config = _fall_detect_config() object_detector = FallDetector(**config) tfe = fall_detector._tfengine assert tfe.output_details[0]['shape'][0] == 1 scores = tfe.output_details[0]['shape'][1] assert scores == 20 assert tfe.output_details[1]['shape'][0] == 1 boxes = tfe.output_details[1]['shape'][1] assert boxes == 20 assert tfe.output_details[2]['shape'][0] == 1 labels = tfe.output_details[2]['shape'][1] assert labels == 20 num = tfe.output_details[3]['shape'][0] assert num == 1
def test_background_image(): """Expect to not detect anything interesting in a background image.""" config = _fall_detect_config() result = None def sample_callback(image=None, thumbnail=None, inference_result=None, **kwargs): nonlocal result result = image is not None and thumbnail is not None and not inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) img = _get_image(file_name="background.jpg") fall_detector.receive_next_sample(image=img) fall_detector.min_time_between_frames = 0.01 time.sleep(fall_detector.min_time_between_frames) img = _get_image(file_name="background.jpg") fall_detector.receive_next_sample(image=img) assert result is True
def test_fall_detection_case_2_2(): """Expected to detect a fall because key-points are detected, the angle criteria is met and the time distance between frames is not too short.""" config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) # The frame represents a person who is in a standing position. img_1 = _get_image(file_name="fall_img_1.png") # The frame represents a person falls. img_2 = _get_image(file_name="fall_img_2.png") fall_detector.receive_next_sample(image=img_1) fall_detector.min_time_between_frames = 0.01 time.sleep(fall_detector.min_time_between_frames) fall_detector.receive_next_sample(image=img_2) assert result assert len(result) == 1 category = result[0]["label"] confidence = result[0]["confidence"] angle = result[0]["leaning_angle"] keypoint_corr = result[0]["keypoint_corr"] assert keypoint_corr assert category == "FALL" assert confidence > 0.7 assert angle > 60
def test_fall_detection_case_4(): """No Fall""" config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) img_1 = _get_image(file_name='fall_img_1.png') img_2 = _get_image(file_name='fall_img_4.png') fall_detector.receive_next_sample(image=img_1) fall_detector.min_time_between_frames = 0.01 time.sleep(fall_detector.min_time_between_frames) fall_detector.receive_next_sample(image=img_2) assert not result
def test_no_sample(): """Expect element to pass empty sample to next element.""" config = _fall_detect_config() result = False def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = image is None and inference_result is None fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) fall_detector.receive_next_sample() assert result is True
def test_background_image(): """Expect to not detect anything interesting in a background image.""" config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) img = _get_image(file_name='background.jpg') fall_detector.receive_next_sample(image=img) assert not result
def test_fall_detection_thumbnail_present(): """Expected to receive thumnail in result if image is provided \ and poses are detected.""" config = _fall_detect_config() result = None def sample_callback(image=None, thumbnail=None, inference_result=None, **kwargs): nonlocal result result = (image is not None and thumbnail is not None and inference_result is not None) fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) img_1 = _get_image(file_name="fall_img_1.png") fall_detector.receive_next_sample(image=img_1) assert result is True
def _helper_test_debug_image_save(context: PipelineContext = None): log_config = {"level": "DEBUG"} logger.configure(config=log_config) # Expect to receive thumnail in result if image is provided and # poses are detected. config = _fall_detect_config() result = None def sample_callback(image=None, thumbnail=None, inference_result=None, **kwargs): nonlocal result result = (image is not None and thumbnail is not None and inference_result is not None) fall_detector = FallDetector(context=context, **config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) img_1 = _get_image(file_name="fall_img_1.png") fall_detector.receive_next_sample(image=img_1) assert result is True # now that we know there was a positive detection # lets check if the the interim debug images were saved as expected pose_img_files = list(_data_dir.glob("tmp-pose-detect-image*.jpg")) assert len(pose_img_files) > 0 fall_img_files = list(_data_dir.glob("tmp-fall-detect-thumbnail*.jpg")) assert len(fall_img_files) > 0 # cleanup after test all_tmp_files = pose_img_files + fall_img_files for f in all_tmp_files: f.unlink() # return logger level to INFO to prevent side effects in other tests log_config = {"level": "INFO"} logger.configure(config=log_config)
def test_fall_detection_2_frame_back_case_3(): """ Expected to not detect a fall using frame[t],frame[t-1] and frame[t-2]. frame[t-2] : A person is in walking postion. frame[t-1] : A person is in walking postion. frame[t] : A person is slight in lean postion but no fall. """ config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) # A frame at t-2 timestamp when person is in walking postion. img_1 = _get_image(file_name="fall_img_15.png") # A frame at t-1 timestamp when person is in walking postion. img_2 = _get_image(file_name="fall_img_16.png") # A frame at t timestamp when person is slight in lean postion but no fall. img_3 = _get_image(file_name="fall_img_17.png") fall_detector.min_time_between_frames = 0.01 fall_detector.receive_next_sample(image=img_1) time.sleep(fall_detector.min_time_between_frames) fall_detector.receive_next_sample(image=img_2) time.sleep(fall_detector.min_time_between_frames) assert not result fall_detector.receive_next_sample(image=img_3) assert not result
def test_fall_detection_2_frame_back_case_2(): """ Expected to detect a fall using frame[t] and frame[t-2]. frame[t-2] : A person is in standing position. frame[t-1] : A person is mid-way of fall. frame[t] : A person is fall down. """ config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) # A frame at t-2 timestamp when person is in standing position. img_1 = _get_image(file_name="fall_img_1.png") # A frame at t-1 timestamp when person is mid-way of fall. img_2 = _get_image(file_name="fall_img_2_2.png") # A frame at t timestamp when person falls down. img_3 = _get_image(file_name="fall_img_2.png") fall_detector.min_time_between_frames = 0.01 fall_detector.max_time_between_frames = 15 fall_detector.receive_next_sample(image=img_1) time.sleep(fall_detector.min_time_between_frames) fall_detector.receive_next_sample(image=img_2) time.sleep(fall_detector.min_time_between_frames) assert not result fall_detector.receive_next_sample(image=img_3) assert result assert len(result) == 1 category = result[0]["label"] confidence = result[0]["confidence"] angle = result[0]["leaning_angle"] keypoint_corr = result[0]["keypoint_corr"] assert keypoint_corr assert category == "FALL" assert confidence > 0.7 assert angle > 60
def test_fall_detection_2_frame_back_case_1(): """ Expected to detect a fall using frame[t] and frame[t-1]. frame[t-2] : A person is in standing position. frame[t-1] : A person is almost in standing position as he is walking. frame[t] : A person is fall down. """ config = _fall_detect_config() result = None def sample_callback(image=None, inference_result=None, **kwargs): nonlocal result result = inference_result fall_detector = FallDetector(**config) output = _OutPipeElement(sample_callback=sample_callback) fall_detector.connect_to_next_element(output) # A frame at t-2 timestamp when person is in standing position. img_1 = _get_image(file_name='fall_img_1.png') # A frame at t-1 timestamp when person is almost in standing position \ # as he is walking. img_2 = _get_image(file_name='fall_img_1_1.png') # A frame at t timestamp when person falls down. img_3 = _get_image(file_name='fall_img_2.png') fall_detector.min_time_between_frames = 0.01 fall_detector.receive_next_sample(image=img_1) time.sleep(fall_detector.min_time_between_frames) fall_detector.receive_next_sample(image=img_2) time.sleep(fall_detector.min_time_between_frames) assert not result fall_detector.receive_next_sample(image=img_3) assert result assert len(result) == 1 category = result[0]['label'] confidence = result[0]['confidence'] angle = result[0]['leaning_angle'] keypoint_corr = result[0]['keypoint_corr'] assert keypoint_corr assert category == 'FALL' assert confidence > 0.7 assert angle > 60