133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Copyright 2014 The Chromium Authors. All rights reserved. 233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Use of this source code is governed by a BSD-style license that can be 333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# found in the LICENSE file. 433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport copy 633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport math 733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport os 833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport unittest 933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 1033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry.core import util 1133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry.internal.util import external_modules 1233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 1333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Recktry: 1433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck np = external_modules.ImportRequiredModule('numpy') 1533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck cv2 = external_modules.ImportRequiredModule('cv2') 1633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckexcept (ImportError, NotImplementedError) as err: 1733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 1833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckelse: 1933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # pylint: disable=protected-access 2033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck class ScreenFinderTest(unittest.TestCase): 2133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __init__(self, *args, **kwargs): 2233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck super(ScreenFinderTest, self).__init__(*args, **kwargs) 2333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # Import modules with dependencies that may not be preset in test setup so 2433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # that importing this unit test doesn't cause the test runner to raise an 2533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # exception. 2633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck from telemetry.internal.image_processing import fake_frame_generator 2733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck from telemetry.internal.image_processing import screen_finder 2833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck from telemetry.internal.image_processing import video_file_frame_generator 2933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.FakeFrameGenerator = fake_frame_generator.FakeFrameGenerator 3033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.VideoFileFrameGenerator = \ 3133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck video_file_frame_generator.VideoFileFrameGenerator 3233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.ScreenFinder = screen_finder.ScreenFinder 3333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 3433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def _GetScreenFinder(self, video_filename): 3533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not video_filename: 3633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck fg = self.FakeFrameGenerator() 3733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 3833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck vid = os.path.join(util.GetUnittestDataDir(), video_filename) 3933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck fg = self.VideoFileFrameGenerator(vid) 4033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.ScreenFinder(fg) 4133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testBasicFunctionality(self): 4333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def CheckCorners(corners, expected): 4433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for i in xrange(len(corners)): 4533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for j in xrange(len(corners[i])): 4633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertAlmostEqual(corners[i][j], expected[i][j], delta=1.1) 4733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected = [[314, 60], [168, 58], [162, 274], [311, 276]] 4833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf = self._GetScreenFinder('screen_3_frames.mov') 4933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertTrue(sf.HasNext()) 5033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck screen, corners = sf.GetNext() 5133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck CheckCorners(corners, expected) 5233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIsNotNone(screen) 5333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck height, width = screen.shape[:2] 5433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertAlmostEqual(height, 226, delta=2) 5533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertAlmostEqual(width, 156, delta=2) 5633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertTrue(sf.HasNext()) 5733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck screen, corners = sf.GetNext() 5833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck CheckCorners(corners, expected) 5933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIsNotNone(screen) 6033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck height1, width1 = screen.shape[:2] 6133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(width, width1) 6233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(height, height1) 6333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertTrue(sf.HasNext()) 6433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck screen, corners = sf.GetNext() 6533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck CheckCorners(corners, expected) 6633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIsNotNone(screen) 6733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck height2, width2 = screen.shape[:2] 6833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(width, width2) 6933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(height, height2) 7033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertFalse(sf.HasNext()) 7133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck error = '' 7233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck try: 7333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf.GetNext() 7433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck except RuntimeError as e: 7533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck error = str(e) 7633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(error, 'No more frames available.') 7733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 7833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testHasMovedFast(self): 7933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf = self._GetScreenFinder(None) 8033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck prev_corners = np.asfarray(([1000, 1000], [0, 1000], [0, 0], [1000, 0])) 8133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertFalse(sf._HasMovedFast(prev_corners, prev_corners)) 8233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck not_moved = copy.deepcopy(prev_corners) 8333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck not_moved[0][1] += 1 8433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck not_moved[1][1] += 1 8533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck not_moved[3][0] += 0.9 8633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertFalse(sf._HasMovedFast(not_moved, prev_corners)) 8733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck moved = copy.deepcopy(prev_corners) 8833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck moved[0][1] += math.sqrt(0.5) 8933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck moved[0][0] += math.sqrt(0.5) 9033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck moved[1][1] += 2.1 9133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertTrue(sf._HasMovedFast(moved, prev_corners)) 9233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 9333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testPointConnectsToCorners(self): 9433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf = self._GetScreenFinder(None) 9533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck line1 = np.asfarray(((0, 0, 1, 0))) 9633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck line2 = np.asfarray(((0, 0, 0, 1))) 9733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck point = np.asfarray((0, 0)) 9833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck point_info = (point, line1, line2) 9933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = np.asfarray(((1, 0), (0, 1))) 10033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertFalse(sf._PointConnectsToCorners(corners, point_info, 1)) 10133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = np.append(corners, (100, 1)) 10233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = np.append(corners, (1, 100)) 10333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = corners.reshape(-1, 2) 10433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertTrue(sf._PointConnectsToCorners(corners, point_info, 2)) 10533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertFalse(sf._PointConnectsToCorners(corners, point_info, 0.5)) 10633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = np.append(corners, (100, 0)) 10733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = np.append(corners, (0, 100)) 10833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = corners.reshape(-1, 2) 10933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertTrue(sf._PointConnectsToCorners(corners, point_info, 0)) 11033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 11133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testFindIntersections(self): 11233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def _BuildResult(point, line1, line2): 11333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return [point, np.asfarray(line1).tolist(), np.asfarray(line2).tolist()] 11433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 11533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def _IntersectionResultsToList(results): 11633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck result_list = [] 11733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for result in results: 11833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck point, line1, line2 = result 11933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck p = np.round(point).tolist() 12033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l1 = np.round(line1).tolist() 12133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l2 = np.round(line2).tolist() 12233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck result_list.append([p, l1, l2]) 12333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return result_list 12433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 12533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf = self._GetScreenFinder(None) 12633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected = [] 12733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines = [] 12833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # Box with corners at (0, 0), (1000, 0), (0, 1000), (1000, 1000) 12933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray(((0, 1001, 0, -1)))) 13033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray(((-1, 0, 1001, 0)))) 13133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray(((1000, 1001, 1000, -1)))) 13233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray(((-1, 1000, 1001, 1000)))) 13333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected.append(_BuildResult([0, 0], lines[0], lines[1])) 13433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected.append(_BuildResult([0, 1000], lines[0], lines[3])) 13533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected.append(_BuildResult([1000, 0], lines[1], lines[2])) 13633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected.append(_BuildResult([1000, 1000], lines[2], lines[3])) 13733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 13833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # crosses 2 lines at 45 degrees. 13933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray(((0, 500, 500, 0)))) 14033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected.append(_BuildResult([0, 500], lines[0], lines[4])) 14133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected.append(_BuildResult([500, 0], lines[1], lines[4])) 14233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 14333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # crosses 1 line at > 45 degrees, 1 line at < 45 degrees. 14433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray(((0, 400, 600, 0)))) 14533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected.append(_BuildResult([0, 400], lines[0], lines[5])) 14633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 14733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # Test without previous corner data, all intersections should be found. 14833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck results = sf._FindIntersections(lines) 14933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck result_list = _IntersectionResultsToList(results) 15033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 15133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for e in expected: 15233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIn(e, result_list) 15333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(len(expected), len(result_list)) 15433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 15533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # Now introduce previous corners, but also reset conditions. No 15633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # intersections should be lost. 15733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = ((1000, 1000), (0, 1000), (0, 0), (1000, 0)) 15833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf._prev_corners = np.asfarray(corners, np.float32) 15933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf._lost_corner_frames = sf.RESET_AFTER_N_BAD_FRAMES + 1 16033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck results = sf._FindIntersections(lines) 16133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck result_list = _IntersectionResultsToList(results) 16233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 16333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for e in expected: 16433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIn(e, result_list) 16533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(len(expected), len(result_list)) 16633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 16733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # Remove reset conditions, so intersections not near corners will be lost. 16833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf._lost_corner_frames = sf.RESET_AFTER_N_BAD_FRAMES 16933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # First 4 intersections are the ones at the old corner locations. 17033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected = expected[0:4] 17133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck results = sf._FindIntersections(lines) 17233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck result_list = _IntersectionResultsToList(results) 17333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 17433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for e in expected: 17533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIn(e, result_list) 17633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(len(expected), len(result_list)) 17733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 17833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testPointIsCloseToPreviousCorners(self): 17933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf = self._GetScreenFinder(None) 18033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = ((1000, 1000), (0, 1000), (0, 0), (1000, 0)) 18133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf._prev_corners = np.asfarray(corners, np.float32) 18233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck dist = math.sqrt(sf.MAX_INTERFRAME_MOTION) 18333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sidedist1 = math.sqrt(sf.MAX_INTERFRAME_MOTION) / math.sqrt(2) - (1e-13) 18433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sidedist2 = math.sqrt(sf.MAX_INTERFRAME_MOTION) / math.sqrt(2) + (1e-13) 18533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck point1 = (corners[3][0] + dist, corners[3][1]) 18633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertTrue(sf._PointIsCloseToPreviousCorners(point1)) 18733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck point2 = (corners[3][0] + sidedist1, corners[3][1] + sidedist1) 18833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertTrue(sf._PointIsCloseToPreviousCorners(point2)) 18933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck point3 = (corners[1][0] + sidedist2, corners[1][1] + sidedist2) 19033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertFalse(sf._PointIsCloseToPreviousCorners(point3)) 19133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 19233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testLooksLikeCorner(self): 19333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # TODO: Probably easier to just do end to end tests. 19433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 19533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 19633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testCornerData(self): 19733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck cd = self.ScreenFinder.CornerData('a', 'b', 'c', 'd', 'e') 19833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(cd.corner_index, 'a') 19933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(cd.corner_location, 'b') 20033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(cd.brightness_score, 'c') 20133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(cd.line1, 'd') 20233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(cd.line2, 'e') 20333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck cd_list = [] 20433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck cd_list.append(self.ScreenFinder.CornerData(0, None, None, None, None)) 20533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck cd_list.append(self.ScreenFinder.CornerData(3, None, None, None, None)) 20633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck cd_list.append(self.ScreenFinder.CornerData(1, None, None, None, None)) 20733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck cd_list.append(self.ScreenFinder.CornerData(2, None, None, None, None)) 20833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck cd_list.sort() 20933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for i in range(len(cd_list)): 21033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(i, cd_list[i].corner_index) 21133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 21233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testFindCorners(self): 21333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # TODO: Probably easier to just do end to end tests. 21433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 21533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 21633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testDeDupCorners(self): 21733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf = self._GetScreenFinder(None) 21833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck data = [] 21933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines = [] 22033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray((0, 1001, 0, -1))) 22133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray((-1, 0, 1001, 0))) 22233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray((1000, 1001, 1000, -1))) 22333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray((-1, 1000, 1001, 1000))) 22433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray((0, 10, 10, 0))) 22533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray((-1, 1001, 1001, 1001))) 22633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = np.asfarray(((1000, 1000), (0, 1000), (0, 0), 22733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck (1000, 0), (0, 10), (10, 0), (1000, 1001))) 22833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck data.append(self.ScreenFinder.CornerData(2, corners[2], 100, 22933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines[0], lines[1])) 23033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck data.append(self.ScreenFinder.CornerData(1, corners[1], 100, 23133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines[0], lines[3])) 23233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck data.append(self.ScreenFinder.CornerData(3, corners[3], 100, 23333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines[1], lines[2])) 23433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck data.append(self.ScreenFinder.CornerData(0, corners[0], 100, 23533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines[2], lines[3])) 23633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck data.append(self.ScreenFinder.CornerData(2, corners[4], 120, 23733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines[0], lines[4])) 23833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck data.append(self.ScreenFinder.CornerData(2, corners[5], 110, 23933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines[1], lines[4])) 24033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck data.append(self.ScreenFinder.CornerData(0, corners[6], 110, 24133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines[2], lines[5])) 24233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck dedup = copy.copy(data) 24333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # Tests 2 non-duplicate corners, 1 corner with connected and unconnected 24433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # corners, and 1 corner with two connected corners. 24533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf._DeDupCorners(dedup, corners) 24633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(len(dedup), 4) 24733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIn(data[0], dedup) 24833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIn(data[1], dedup) 24933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIn(data[2], dedup) 25033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIn(data[6], dedup) 25133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 25233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # Same test, but this time the corner with connected and unconnected 25333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # corners now only contains unconnected corners. 25433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck del data[0] 25533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = np.delete(corners, 2, axis=0) 25633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck dedup2 = copy.copy(data) 25733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf._DeDupCorners(dedup2, corners) 25833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(len(dedup2), 4) 25933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIn(data[3], dedup2) 26033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIn(data[0], dedup2) 26133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIn(data[1], dedup2) 26233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertIn(data[5], dedup2) 26333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 26433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testFindExactCorners(self): 26533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf = self._GetScreenFinder(None) 26633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck img = np.zeros((3, 3), np.uint8) 26733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck img[1][0] = 255 26833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck img[0][1] = 255 26933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck img[1][2] = 255 27033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck img[2][1] = 255 27133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf._frame_edges = img 27233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = np.asfarray([(1, 1), (1, 1), (1, 1), (1, 1)]) 27333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected = np.asfarray([(2, 0), (0, 0), (0, 2), (2, 2)]) 27433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ret = sf._FindExactCorners(corners) 27533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck np.testing.assert_equal(ret, expected) 27633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck img2 = np.zeros((3, 3), np.uint8) 27733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck img2[1][0] = 255 27833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck img2[1][1] = 255 27933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck img2[2][2] = 255 28033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck img2[2][1] = 255 28133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf._frame_edges = img2 28233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected2 = [(2, 1), (0, 1), (0, 2), (2, 2)] 28333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ret2 = sf._FindExactCorners(corners) 28433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck np.testing.assert_equal(ret2, expected2) 28533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 28633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testSmoothCorners(self): 28733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf = self._GetScreenFinder(None) 28833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = [[10, 10], [10, 10], [10, 10], [10, 10]] 28933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ret = sf._SmoothCorners(corners).tolist() 29033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertListEqual(ret, corners) 29133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = [[0, 0], [0, 0], [0, 0], [0, 0]] 29233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected = [[5, 5], [5, 5], [5, 5], [5, 5]] 29333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ret = sf._SmoothCorners(corners).tolist() 29433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertListEqual(ret, expected) 29533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected = [[2.5, 2.5], [2.5, 2.5], [2.5, 2.5], [2.5, 2.5]] 29633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ret = sf._SmoothCorners(corners).tolist() 29733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertListEqual(ret, expected) 29833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 29933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testGetTransform(self): 30033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf = self._GetScreenFinder(None) 30133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = np.array([[100, 1000], [0, 1000], [0, 0], [100, 0]], np.float32) 30233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck transform, w, h = sf._GetTransform(corners, 1) 30333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck transform = np.round(transform, 2) 30433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected = [[1., 0., 1.], [-0., -1., 1001.], [0., -0., 1.]] 30533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertListEqual(transform.tolist(), expected) 30633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(w, 102) 30733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(h, 1002) 30833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 30933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners = np.array([(200, 2000), (0, 2000), (0, 0), (200, 0)], np.float32) 31033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck transform, w, h = sf._GetTransform(corners, 5) 31133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck transform = np.round(transform, 2) 31233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected = [[0.5, 0.0, 5.0], [-0.0, -0.5, 1005.0], [-0.0, 0.0, 1.0]] 31333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertListEqual(transform.tolist(), expected) 31433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(w, 110) 31533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(h, 1010) 31633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 31733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testNewScreenLocation(self): 31833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf = self._GetScreenFinder(None) 31933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners_2 = np.asfarray([[np.nan, np.nan], [0, 1000], [np.nan, np.nan], 32033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck [1000, 0]]) 32133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners_3 = np.asfarray([[1000, 1000], [0, 1000], [np.nan, np.nan], 32233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck [1000, 0]]) 32333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck corners_4 = np.asfarray([[1000, 1000], [0, 1000], [0, 0], [1000, 0]]) 32433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines = [] 32533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # Box with corners at (0, 0), (1000, 0), (0, 1000), (1000, 1000) 32633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray(((0, 1001, 0, -1)))) 32733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray(((-1, 0, 1001, 0)))) 32833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray(((1000, 1001, 1000, -1)))) 32933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray(((-1, 1000, 1001, 1000)))) 33033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # Additional intersections near a corner. 33133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray(((0, 3, 7, 0)))) 33233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines.append(np.asfarray(((0, 4, 6, 0)))) 33333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck intersections = sf._FindIntersections(lines) 33433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck failed = False 33533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck try: 33633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf._NewScreenLocation(corners_3, 1, intersections) 33733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck except self.ScreenFinder.ScreenNotFoundError: 33833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck failed = True 33933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertTrue(failed) 34033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 34133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf._lost_corner_frames = 10 34233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf._lost_corners = [True, True, True, True] 34333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ret = sf._NewScreenLocation(corners_4, 0, intersections) 34433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck np.testing.assert_equal(ret, corners_4) 34533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertListEqual(sf._lost_corners, [False, False, False, False]) 34633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(sf._lost_corner_frames, 0) 34733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 34833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf._prev_corners = corners_4 34933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ret = sf._NewScreenLocation(corners_3, 1, intersections) 35033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ret = np.round(ret) 35133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck np.testing.assert_equal(ret, corners_4) 35233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertListEqual(sf._lost_corners, [False, False, True, False]) 35333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(sf._lost_corner_frames, 1) 35433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 35533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sf._prev_corners = np.asfarray([(1000, 1000), (0, 1000), 35633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck (0, 3), (1000, 0)]) 35733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ret = sf._NewScreenLocation(corners_3, 1, intersections) 35833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ret = np.round(ret) 35933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck np.testing.assert_equal(ret, corners_4) 36033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertListEqual(sf._lost_corners, [False, False, True, False]) 36133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(sf._lost_corner_frames, 2) 36233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 36333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ret = sf._NewScreenLocation(corners_2, 2, intersections) 36433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ret = np.round(ret) 36533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected = [[1000, 1000], [0, 1000], [0, 3], [1000, 0]] 36633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck np.testing.assert_equal(ret, expected) 36733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertListEqual(sf._lost_corners, [True, False, True, False]) 36833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(sf._lost_corner_frames, 3) 369