blob: 2bf88f2870b7f06cf975e2deefa5843c2d66efc9 [file] [log] [blame]
# Copyright 2015 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unit tests for LEDDetector."""
import numpy as np
from optofidelity.detection._led_detector import Flash, LEDDetector
from optofidelity.detection.events import LEDEvent
from optofidelity.detection.screen_calibration import ScreenCalibration
from . import test_data
from .test_detector import DetectorTest
class LEDDetectorTest(DetectorTest):
def executeLEDPreprocessingTest(self, on_image, off_image):
def assertLEDFlash(flashes, off_to_on):
self.assertGreater(len(flashes), 0)
for flash in flashes:
if off_to_on:
self.assertGreater(flash.color, 0)
else:
self.assertLess(flash.color, 0)
frame = self.uncalibratedFrame(on_image, off_image)
flashes = LEDDetector().Preprocess(frame, None)
assertLEDFlash(flashes, True)
frame = self.uncalibratedFrame(off_image, on_image)
flashes = LEDDetector().Preprocess(frame, None)
assertLEDFlash(flashes, False)
def executeFalsePositiveTest(self, on_image, off_image, black_image=None,
white_image=None):
if black_image is not None and white_image is not None:
calibration = ScreenCalibration(test_data.LoadImage(black_image),
test_data.LoadImage(white_image))
frame = self.calibratedFrame(on_image, off_image, calibration)
else:
frame = self.uncalibratedFrame(on_image, off_image)
flashes = LEDDetector().Preprocess(frame, None)
self.assertEqual(len(flashes), 0)
def testPreprocessing1(self):
self.executeLEDPreprocessingTest("led_1_on.png", "led_1_off.png")
def testPreprocessing2(self):
self.executeLEDPreprocessingTest("led_2_on.png", "led_2_off.png")
def testPreprocessing3(self):
self.executeLEDPreprocessingTest("led_4_on.png", "led_4_off.png")
def testPreprocessing4(self):
self.executeLEDPreprocessingTest("led_3_on.png", "led_3_off.png")
def testFalsePositive0(self):
self.executeFalsePositiveTest("led_fp_0.png", "led_fp_0_prev.png")
def testFalsePositive1(self):
self.executeFalsePositiveTest("led_fp_1.png", "led_fp_1_prev.png",
"led_fp_1_calib_black.png",
"led_fp_1_calib_white.png")
def testEventGeneration(self):
def flash(coords, color):
return Flash(np.asarray(coords), float(color))
flashes_sequence = [
[flash((32, 32), 0.5)], # Flash fading in over multiple frames
[flash((32, 32), 1.0)],
[], [], [], [], [], [], [], [], [], [], # Wait 10 frames
[flash((32, 32), -0.5)], # Flash fading out over multiple frames
[flash((32, 32), -1.0)],
[], [], [], [], [], [], [], [], [], [], # Wait 10 frames
[flash((32, 32), 1.0)], # Bouncing flash
[flash((32, 32), -1.0)],
[flash((32, 32), 1.0)],
]
expected_events = [
LEDEvent(0, LEDEvent.STATE_ON),
LEDEvent(12, LEDEvent.STATE_OFF),
LEDEvent(24, LEDEvent.STATE_ON)
]
self.assertExpectedEventsGenerated(LEDDetector(), flashes_sequence,
expected_events)
def testMultiFrameFadeIn(self):
# Tests an edge case where an led fades in over multiple frames. In the
# first frame, only the LED itself is detected as a valid flash, but in the
# following frame a reflection is bright enough to be detected as well.
# The reflection should be supressed and not generate another LED event.
def flash(coords):
return Flash(np.asarray(coords), 1.0)
flashes_sequence = [
[flash((199, 126))],
[flash((225, 152)), flash((197., 123.))]
]
expected_events = [
LEDEvent(0, LEDEvent.STATE_ON)
]
self.assertExpectedEventsGenerated(LEDDetector(), flashes_sequence,
expected_events)