def test_contour_nomatch(self): finder = ContourFinder() finder.params["find"]["similarity"].value = 0.25 i = 1 for contour in finder.algorithms["contour_extractors"]: for threshold in finder.algorithms["threshold_filters"]: finder.configure_backend(contour, "contour") finder.configure_backend(threshold, "threshold") finder.params["contour"]["minArea"].value = 100 # verify match accuracy matches = finder.find(Image('n_ibs'), Image('all_shapes')) self.assertEqual(len(matches), 0) # verify dumped files count and names dumps = self._verify_and_get_dumps(6, i) self._verify_dumped_images('n_ibs', 'all_shapes', dumps, "contour") hotmaps = sorted(self._get_matches_in('.*hotmap.*', dumps)) self.assertEqual(len(hotmaps), 3) self.assertIn('3hotmap', hotmaps[0]) # report achieved similarity in the end of the filename self.assertRegex(hotmaps[0], ".*-\d\.\d+.*") self.assertTrue( os.path.isfile(os.path.join(self.logpath, hotmaps[0]))) self.assertIn('3hotmap-1threshold', hotmaps[1]) self.assertTrue( os.path.isfile(os.path.join(self.logpath, hotmaps[1]))) self.assertIn('3hotmap-2contours', hotmaps[2]) self.assertTrue( os.path.isfile(os.path.join(self.logpath, hotmaps[1]))) shutil.rmtree(self.logpath) i += 1
def test_template_nomatch(self): finder = TemplateFinder() finder.params["find"]["similarity"].value = 0.25 i = 1 for template in finder.algorithms["template_matchers"]: # one of the backend is too tolerant for this case if template == "ccorr_normed": continue finder.configure_backend(template, "template") matches = finder.find(Image('n_ibs'), Image('all_shapes')) # verify match accuracy self.assertEqual(len(matches), 0) # verify dumped files count and names dumps = self._verify_and_get_dumps(5, i) self._verify_dumped_images('n_ibs', 'all_shapes', dumps, "template") hotmaps = sorted(self._get_matches_in('.*hotmap.*', dumps)) self.assertEqual(len(hotmaps), 2) for j, hotmap in enumerate(hotmaps): if j == 0: self.assertIn('3hotmap', hotmap) else: self.assertIn('3hotmap-1template', hotmap) # report achieved similarity in the end of the filename self.assertRegex(hotmap, ".*-\d\.\d+.*") self.assertTrue( os.path.isfile(os.path.join(self.logpath, hotmap))) shutil.rmtree(self.logpath) i += 1
def test_deep_same(self): finder = DeepFinder() # pattern matching is not perfect finder.params["find"]["similarity"].value = 0.95 matches = finder.find(Pattern('cat'), Image('coco_cat')) # verify match accuracy self.assertEqual(len(matches), 1) self.assertAlmostEqual(matches[0].x, 90, delta=5) self.assertAlmostEqual(matches[0].y, 345, delta=5) self.assertAlmostEqual(matches[0].width, 515, delta=5) self.assertAlmostEqual(matches[0].height, 805, delta=5) # verify dumped files count and names dumps = self._verify_and_get_dumps(6) self._verify_dumped_images('cat', 'coco_cat', dumps, "deep") hotmaps = sorted(self._get_matches_in('.*hotmap.*', dumps)) self.assertEqual(len(hotmaps), 3) for i, hotmap in enumerate(hotmaps): if i == 0: self.assertIn('3hotmap', hotmap) # report achieved similarity in the end of the filename self.assertRegex(hotmap, ".*-\d\.\d+.*") else: self.assertIn('%sf' % i, hotmap) self.assertTrue(os.path.isfile(os.path.join(self.logpath, hotmap))) finder.configure_backend("tensorflow", "deep") with self.assertRaises(ImportError): finder.synchronize_backend() with self.assertRaises(NotImplementedError): finder.find(Pattern('cat'), Image('coco_cat'))
def test_tempfeat_nomatch(self): finder = TemplateFeatureFinder() finder.params["find"]["similarity"].value = 0.25 i = 1 for tempfeat in finder.algorithms["tempfeat_matchers"]: finder.configure_backend(tempfeat, "tempfeat") matches = finder.find(Image('n_ibs'), Image('all_shapes')) # verify match accuracy self.assertEqual(len(matches), 0) # verify dumped files count and names dumps = self._verify_and_get_dumps(4, i) self._verify_dumped_images('n_ibs', 'all_shapes', dumps, "tempfeat") hotmaps = sorted(self._get_matches_in('.*hotmap.*', dumps)) self.assertEqual(len(hotmaps), 1) hotmap = hotmaps[0] self.assertIn('3hotmap', hotmap) self.assertNotIn('template', hotmap) self.assertNotIn('feature', hotmap) # report achieved similarity in the end of the filename self.assertRegex(hotmap, ".*-\d\.\d+.*") self.assertTrue(os.path.isfile(os.path.join(self.logpath, hotmap))) shutil.rmtree(self.logpath) i += 1
def test_feature_rotation(self): finder = FeatureFinder() finder.params["find"]["similarity"].value = 0.45 matches = finder.find(Image('n_ibs'), Image('h_ibs_rotated')) self.assertEqual(len(matches), 1) self.assertAlmostEqual(matches[0].x, 435, delta=5) self.assertAlmostEqual(matches[0].y, 447, delta=5) self.assertAlmostEqual(matches[0].width, 270, delta=10) self.assertAlmostEqual(matches[0].height, 180, delta=10)
def test_feature_viewport(self): finder = FeatureFinder() finder.params["find"]["similarity"].value = 0.4 matches = finder.find(Image('n_ibs'), Image('h_ibs_viewport')) self.assertEqual(len(matches), 1) self.assertAlmostEqual(matches[0].x, 68, delta=5) self.assertAlmostEqual(matches[0].y, 18, delta=5) self.assertAlmostEqual(matches[0].width, 160, delta=10) self.assertAlmostEqual(matches[0].height, 235, delta=10)
def test_feature_scaling(self): finder = FeatureFinder() finder.params["find"]["similarity"].value = 0.25 matches = finder.find(Image('n_ibs'), Image('h_ibs_scaled')) self.assertEqual(len(matches), 1) self.assertAlmostEqual(matches[0].x, 39, delta=5) self.assertAlmostEqual(matches[0].y, 220, delta=5) self.assertAlmostEqual(matches[0].width, 100, delta=10) self.assertAlmostEqual(matches[0].height, 150, delta=10)
def test_exists(self): self.show_image('all_shapes') match = self.region.find(Image('shape_blue_circle')) self.assertTrue(isinstance(match, Match)) self.close_windows() match = self.region.exists(Image('shape_blue_circle')) self.assertEqual(None, match)
def test_find_zero_matches(self): self.show_image('all_shapes') matches = self.region.find_all(Image('shape_blue_circle')) self.assertEqual(len(matches), 1) self.close_windows() matches = self.region.find_all(Image('shape_blue_circle'), allow_zero=True) self.assertEqual(len(matches), 0) self.close_windows()
def test_image_cache(self): image = Image(self.file_all_shapes) second_image = Image(self.file_all_shapes) self.assertIs(image.pil_image, second_image.pil_image) # Clear image cache the hard way Image()._cache.clear() third_image = Image(self.file_all_shapes) self.assertIsNot(image.pil_image, third_image.pil_image)
def test_copy_object(self): image = Image(self.file_all_shapes) my_copy = image.copy() self.assertNotEqual(image.match_settings, my_copy.match_settings) self.assertEqual(image.filename, my_copy.filename) self.assertEqual(image.similarity, my_copy.similarity) self.assertEqual(image.pil_image, my_copy.pil_image) self.assertEqual(image.width, my_copy.width) self.assertEqual(image.height, my_copy.height) self.assertEqual(image.center_offset, my_copy.center_offset)
def test_find_error(self): try: self.region.find(Image('shape_blue_circle.png'), 0) self.fail('exception was not thrown') except FindError as e: pass try: self.region.find_all(Image('shape_blue_circle.png'), 0) self.fail('exception was not thrown') except FindError as e: pass
def test_autopy_nomatch(self): finder = AutoPyFinder() finder.params["find"]["similarity"].value = 0.25 matches = finder.find(Image('n_ibs'), Image('all_shapes')) # verify match accuracy self.assertEqual(len(matches), 0) # verify dumped files count and names dumps = self._verify_and_get_dumps(4) self._verify_dumped_images('n_ibs', 'all_shapes', dumps, "autopy") self._verify_single_hotmap(dumps, "autopy")
def test_find_all(self): self.show_image('all_shapes') greenbox = Image('shape_green_box') matches = self.region.find_all(greenbox) self.assertEqual(len(matches), 1) self.assertAlmostEqual(matches[0].x, 30, delta=5) self.assertAlmostEqual(matches[0].y, 190, delta=5) self.assertAlmostEqual(70, matches[0].width, delta=5) self.assertAlmostEqual(50, matches[0].height, delta=5) redbox = Image('shape_red_box') matches = self.region.find_all(redbox) expected_matches = [(25, 25), (320, 25), (315, 115)] self.assertEqual(len(matches), len(expected_matches)) for match in matches: self.region.hover(match) time.sleep(0.5) self.assertAlmostIn((match.x, match.y), expected_matches) self.assertAlmostEqual(70, match.width, delta=5) self.assertAlmostEqual(60, match.height, delta=5) pinkbox = Image('shape_pink_box') # pink is similar to red, so the best fuzzy matches also # include the three red boxes when considering color self.region.cv_backend.matcher.params["find"]["similarity"].value = 0.5 self.region.cv_backend.matcher.params["template"]["nocolor"].value = False matches = self.region.find_all(pinkbox) # approximately the above coordinates since maching different needle expected_matches = [(25, 35), (320, 40), (320, 125), (30, 255)] self.assertEqual(len(matches), len(expected_matches)) for match in matches: self.region.hover(match) time.sleep(0.5) self.assertAlmostIn((match.x, match.y), expected_matches) self.assertAlmostEqual(70, match.width, delta=5) self.assertAlmostEqual(50, match.height, delta=5) # ignore colors here so the best matches for the pink box # should be based on shape (the green and yellow box) self.region.cv_backend.matcher.params["find"]["similarity"].value = 0.8 self.region.cv_backend.matcher.params["template"]["nocolor"].value = True matches = self.region.find_all(pinkbox) expected_matches = [(30, 120), (30, 195), (30, 255)] self.assertEqual(len(matches), len(expected_matches)) for match in matches: self.region.hover(match) time.sleep(0.5) self.assertAlmostIn((match.x, match.y), expected_matches) self.assertAlmostEqual(70, match.width, delta=5) self.assertAlmostEqual(50, match.height, delta=5)
def test_sample(self): self.show_image('all_shapes') # autopy matching does not support similarity shapes = Region(cv=AutoPyFinder()) similarity = shapes.sample(Image('shape_blue_circle')) self.assertEqual(similarity, 0.0) # initialize template matching region to support similarity shapes = Region(cv=TemplateFinder()) similarity = shapes.sample(Image('shape_blue_circle')) self.assertAlmostEqual(similarity, 0.999999, delta=0.001) self.close_windows()
def test_similarity(self): image = Image(self.file_all_shapes) new_image = image.with_similarity(0.45) self.assertEqual(0.45, new_image.similarity) # TODO: create a separate config for defaults to extract this from there self.assertEqual(0.8, image.similarity) self.assertEqual(image.filename, new_image.filename) self.assertNotEqual(image.similarity, new_image.similarity) self.assertEqual(image.pil_image, new_image.pil_image) self.assertEqual(image.width, new_image.width) self.assertEqual(image.height, new_image.height) self.assertEqual(image.center_offset, new_image.center_offset)
def test_find_center_offset(self): self.show_image('all_shapes.png') match = self.region.find(Image('shape_blue_circle.png')) # Positive target offset match_offset = self.region.find(Image('shape_blue_circle.png').with_center_offset(200, 100)) self.assertEqual(match.target.x + 200, match_offset.target.x) self.assertEqual(match.target.y + 100, match_offset.target.y) # Negative target offset match_offset = self.region.find(Image('shape_blue_circle.png').with_center_offset(-50, -30)) self.assertEqual(match.target.x - 50, match_offset.target.x) self.assertEqual(match.target.y - 30, match_offset.target.y)
def test_wait(self): self.show_image('all_shapes') match = self.region.wait(Image('shape_blue_circle'), timeout=5) self.assertTrue(isinstance(match, Match)) self.close_windows()
def test_feature_same(self): finder = FeatureFinder() finder.params["find"]["similarity"].value = 1.0 i = 1 for feature in finder.algorithms["feature_projectors"]: for fdetect in finder.algorithms["feature_detectors"]: for fextract in finder.algorithms["feature_extractors"]: for fmatch in finder.algorithms["feature_matchers"]: finder.configure_backend(feature, "feature") finder.configure(feature_detect=fdetect, feature_extract=fextract, feature_match=fmatch) # also with customized synchronization to the configuration finder.synchronize_backend(feature, "feature") finder.synchronize(feature_detect=fdetect, feature_extract=fextract, feature_match=fmatch) matches = finder.find(Image('n_ibs'), Image('n_ibs')) # verify match accuracy self.assertEqual(len(matches), 1) self.assertEqual(matches[0].x, 0) self.assertEqual(matches[0].y, 0) self.assertEqual(matches[0].width, 178) self.assertEqual(matches[0].height, 269) # verify dumped files count and names dumps = self._verify_and_get_dumps(7, i) self._verify_dumped_images('n_ibs', 'n_ibs', dumps, "feature") hotmaps = sorted( self._get_matches_in('.*hotmap.*', dumps)) self.assertEqual(len(hotmaps), 4) self.assertIn('3hotmap', hotmaps[0]) # report achieved similarity in the end of the filename self.assertRegex(hotmaps[0], ".*-\d\.\d+.*") self.assertTrue( os.path.isfile( os.path.join(self.logpath, hotmaps[0]))) self.assertIn('3hotmap-1detect', hotmaps[1]) self.assertIn('3hotmap-2match', hotmaps[2]) self.assertIn('3hotmap-3project', hotmaps[3]) shutil.rmtree(self.logpath) i += 1
def test_text_bold(self): finder = TextFinder() matches = finder.find(Text('Find the word'), Image('sentence_bold')) self.assertEqual(len(matches), 1) self.assertEqual(matches[0].x, 12) self.assertEqual(matches[0].y, 13) self.assertAlmostEqual(matches[0].width, 100, delta=5) self.assertAlmostEqual(matches[0].height, 10, delta=5)
def test_autopy_same(self): finder = AutoPyFinder() finder.params["find"]["similarity"].value = 1.0 matches = finder.find(Image('shape_blue_circle'), Image('all_shapes')) # verify match accuracy self.assertEqual(len(matches), 1) self.assertEqual(matches[0].x, 104) self.assertEqual(matches[0].y, 10) self.assertEqual(matches[0].width, 165) self.assertEqual(matches[0].height, 151) # verify dumped files count and names dumps = self._verify_and_get_dumps(4) self._verify_dumped_images('shape_blue_circle', 'all_shapes', dumps, "autopy") self._verify_single_hotmap(dumps, "autopy")
def test_template_nocolor(self): finder = TemplateFinder() # template matching without color is not perfect finder.params["find"]["similarity"].value = 0.99 for template in finder.algorithms["template_matchers"]: finder.configure_backend(template, "template") finder.params["template"]["nocolor"].value = True matches = finder.find(Image('shape_blue_circle'), Image('all_shapes')) # verify match accuracy self.assertEqual(len(matches), 1) self.assertEqual(matches[0].x, 104) self.assertEqual(matches[0].y, 10) self.assertEqual(matches[0].width, 165) self.assertEqual(matches[0].height, 151)
def test_basic(self): image = Image(self.file_all_shapes) self.assertEqual(400, image.width) self.assertEqual(300, image.height) self.assertTrue(image.filename.find('all_shapes.png') != -1) self.assertIsInstance(image.match_settings, Finder) self.assertFalse(image.use_own_settings)
def test_text_larger(self): finder = TextFinder() matches = finder.find(Text('Find the word'), Image('sentence_larger')) self.assertEqual(len(matches), 1) # TODO: location too far due to poor text detection #self.assertEqual(matches[0].x, 13) self.assertEqual(matches[0].y, 13) #self.assertAlmostEqual(matches[0].width, 100, delta=5) self.assertAlmostEqual(matches[0].height, 10, delta=5)
def test_contour_same(self): finder = ContourFinder() # shape matching is not perfect finder.params["find"]["similarity"].value = 0.99 i = 1 for contour in finder.algorithms["contour_extractors"]: for threshold in finder.algorithms["threshold_filters"]: # TODO: this is still not implemented if contour == "components": continue finder.configure_backend(contour, "contour") finder.configure_backend(threshold, "threshold") finder.params["contour"]["minArea"].value = 100 matches = finder.find(Image('shape_blue_circle'), Image('all_shapes')) # verify match accuracy self.assertEqual(len(matches), 1) self.assertEqual(matches[0].x, 104) self.assertEqual(matches[0].y, 10) self.assertEqual(matches[0].width, 165) self.assertEqual(matches[0].height, 151) # verify dumped files count and names dumps = self._verify_and_get_dumps(6, i) self._verify_dumped_images('shape_blue_circle', 'all_shapes', dumps, "contour") hotmaps = sorted(self._get_matches_in('.*hotmap.*', dumps)) self.assertEqual(len(hotmaps), 3) self.assertIn('3hotmap', hotmaps[0]) # report achieved similarity in the end of the filename self.assertRegex(hotmaps[0], ".*-\d\.\d+.*") self.assertTrue( os.path.isfile(os.path.join(self.logpath, hotmaps[0]))) self.assertIn('3hotmap-1threshold', hotmaps[1]) self.assertTrue( os.path.isfile(os.path.join(self.logpath, hotmaps[1]))) self.assertIn('3hotmap-2contours', hotmaps[2]) self.assertTrue( os.path.isfile(os.path.join(self.logpath, hotmaps[1]))) shutil.rmtree(self.logpath) i += 1
def test_text_basic(self): finder = TextFinder() matches = finder.find(Text('Find the word here'), Image('sentence_sans')) self.assertEqual(len(matches), 1) # TODO: location too far due to poor text detection #self.assertEqual(matches[0].x, 11) self.assertEqual(matches[0].y, 12) self.assertAlmostEqual(matches[0].width, 115, delta=5) self.assertAlmostEqual(matches[0].height, 10, delta=5)
def test_cascade_viewport(self): finder = CascadeFinder() matches = finder.find(Pattern('n_ibs.xml'), Image('h_ibs_viewport')) self.assertEqual(len(matches), 1) # the original needle image was 150x150 with larger white margins self.assertAlmostEqual(matches[0].x, 20, delta=5) self.assertAlmostEqual(matches[0].y, 20, delta=5) # near square shape is due to the positive images used for training self.assertAlmostEqual(matches[0].width, 250, delta=10) self.assertAlmostEqual(matches[0].height, 250, delta=10)
def test_template_multiple(self): finder = TemplateFinder() finder.find(Image('shape_red_box'), Image('all_shapes')) # verify dumped files count and names dumps = self._verify_and_get_dumps(7) self._verify_dumped_images('shape_red_box', 'all_shapes', dumps, "template") hotmaps = sorted(self._get_matches_in('.*hotmap.*', dumps)) self.assertEqual(len(hotmaps), 4) self.assertEqual(len(self._get_matches_in('.*3hotmap.*', hotmaps)), 4) for i, hotmap in enumerate(hotmaps): if i == 0: self.assertIn('3hotmap', hotmap) else: self.assertIn('3hotmap-%stemplate' % i, hotmap) # report achieved similarity in the end of the filename self.assertRegex(hotmap, ".*-\d\.\d+.*") self.assertTrue(os.path.isfile(os.path.join(self.logpath, hotmap)))
def test_hybrid_nomatch(self): finder = HybridFinder() finder.configure_backend("autopy") finder.synchronize_backend("autopy") finder.params["find"]["similarity"].value = 1.0 matches = finder.find(Chain('circle_fake'), Image('all_shapes')) # verify match accuracy self.assertEqual(len(matches), 0) # verify dumped files count and names (4+4+7) dumps = self._verify_and_get_dumps(15, multistep=True)
def test_text_nomatch(self): finder = TextFinder() finder.params["find"]["similarity"].value = 0.25 i = 1 for tdetect in finder.algorithms["text_detectors"]: # TODO: this is still not implemented if tdetect == "components": continue for ocr in finder.algorithms["text_recognizers"]: # TODO: this is still not implemented if ocr == "beamSearch": continue # TODO: handle newer OpenCV bugs with some backends import cv2 # TODO: deprecate OpenCV 3.X versions after time if cv2.__version__.startswith("3.") and tdetect == "east": continue finder.configure_backend(tdetect, "tdetect") finder.configure_backend(ocr, "ocr") # also with customized synchronization to the configuration finder.synchronize_backend(tdetect, "tdetect") finder.synchronize_backend(ocr, "ocr") matches = finder.find(Text('Nothing'), Image('all_shapes')) # verify match accuracy self.assertEqual(len(matches), 0) # verify dumped files count and names dumps = self._verify_and_get_dumps(7, i) self._verify_dumped_images('Nothing', 'all_shapes', dumps, "text") hotmaps = sorted(self._get_matches_in('.*hotmap.*', dumps)) self.assertEqual(len(hotmaps), 4) for j, hotmap in enumerate(hotmaps): if j == 0: self.assertIn('3hotmap', hotmap) elif j == 1: self.assertIn('3hotmap-1char', hotmap) elif j == 2: self.assertIn('3hotmap-2text', hotmap) else: self.assertIn('3hotmap-3ocr-%stext' % (j - 2), hotmap) if j == 3 or j == 4: # report achieved similarity in the end of the filename self.assertRegex(hotmap, ".*-\d\.\d+.*") self.assertTrue( os.path.isfile(os.path.join(self.logpath, hotmap))) shutil.rmtree(self.logpath) i += 1