Beispiel #1
0
    def test_draw_about_box(self):
        tool = AnnotationTool()
        tool.load_app(True)

        appMenu = AppMenu(tool)
        complete = appMenu.draw_about_box()
        self.assertTrue(complete)
Beispiel #2
0
    def test_import_files_in_directory(self):
        tool = AnnotationTool()
        tool.load_app(True)
        tool.annotations = [Annotation(), Annotation(), Annotation()]
        tool.file_list = ['file1.jpg', 'file2.jpg', 'file3.png']
        tool.current_file = 0
        tool.class_list = []
        tool.img = MockImg(640, 480)

        appMenu = AppMenu(tool)

        self.assertTrue(tool.saved)
        complete = appMenu._import_files_in_directory('path/', MockMeta(6))
        self.assertTrue(complete)
        self.assertEqual(len(tool.annotations), 3)
        self.assertFalse(tool.saved)

        tool.saved = True
        self.assertTrue(tool.saved)
        complete = appMenu._import_files_in_directory('path/', MockMeta(6))
        self.assertTrue(complete)
        self.assertEqual(len(tool.annotations), 3)
        self.assertFalse(tool.saved)

        tool.saved = True
        self.assertTrue(tool.saved)
        complete = appMenu._import_files_in_directory('', MockMeta(6))
        self.assertFalse(complete)
        self.assertEqual(len(tool.annotations), 3)
        self.assertTrue(tool.saved)
Beispiel #3
0
    def test_new_project_wizard(self):
        tool = AnnotationTool()
        tool.load_app(True)

        appMenu = AppMenu(tool)
        complete = appMenu._new_project_wizard()
        self.assertTrue(complete)
Beispiel #4
0
    def test_csv_exporter(self):
        tool = AnnotationTool()
        tool.load_app(True)

        # Annotation added
        tool.annotations = []
        tool.file_list = []
        tool.class_list = ['winston', 'prince', 'duckie']
        tool.colorspace = ['#0000FF', '#FF0000', '#00FF00']
        tool.current_file = 0
        tool.img = MockImg()

        for i in range(5):
            a = Annotation()
            a.rotation = 3
            tool.file_list.append('file%d.jpg' % i)
            for p in range(3):
                roi = ROI()
                roi.push(0, 0)
                roi.push(100.0, 100.0)
                a.push(roi, i % len(tool.class_list))
            tool.annotations.append(a)

        appMenu = AppMenu(tool)
        complete = appMenu._csv_exporter('test')
        self.assertTrue(complete)

        appMenu = AppMenu(tool)
        complete = appMenu._csv_exporter('test.csv')
        self.assertTrue(complete)

        appMenu = AppMenu(tool)
        complete = appMenu._csv_exporter('')
        self.assertFalse(complete)
Beispiel #5
0
    def test_save_close_command(self):
        tool = AnnotationTool()
        tool.load_app(True)

        tool.saved = False
        appMenu = AppMenu(tool)
        complete = appMenu._save_close_command('file.oaf')
        self.assertTrue(complete)

        complete = appMenu._save_close_command('')
        self.assertFalse(complete)
Beispiel #6
0
    def test_close_command(self):
        tool = AnnotationTool()
        tool.load_app(True)

        appMenu = AppMenu(tool)
        complete = appMenu._close_command()
        self.assertTrue(complete)

        frame = tool.background.winfo_children()

        arr = [
            "New Blank Project", "New Project Wizard", "Load Project", "Quit"
        ]
        for i, child in enumerate(frame):
            self.assertEqual(frame[i].cget('text'), arr[i])
Beispiel #7
0
    def test_remove_class(self):
        tool = AnnotationTool()
        tool.load_app(True)
        tool.annotations = []

        tool.class_list = ['winston', 'prince', 'duckie']
        tool.colorspace = ['#0000FF', '#FF0000', '#00FF00']
        tool.class_count = [5, 15, 501]

        tool.top_colors_free = ['#00FFFF', '#FF00FF', '#FFFF00']
        tool.top_colors_used = ['#0000FF', '#FF0000', '#00FF00']

        appMenu = AppMenu(tool)
        wizard = ProjectWizard(appMenu)

        self.assertEqual(tool.class_list[-1], 'duckie')

        wizard._draw_right_pane()
        wizard._remove_class(2)

        self.assertEqual(tool.class_list[-1], 'prince')
        self.assertEqual(tool.class_count[-1], 15)
        self.assertEqual(tool.colorspace[-1], '#FF0000')
        self.assertEqual(len(tool.top_colors_used), 2)
        self.assertEqual(len(tool.top_colors_free), 4)
Beispiel #8
0
    def test_check_before_remove(self):
        tool = AnnotationTool()
        tool.load_app(True)
        tool.annotations = []

        tool.class_list = ['winston', 'prince', 'duckie']
        tool.colorspace = ['#0000FF', '#FF0000', '#00FF00']
        tool.class_count = [5, 15, 501]

        tool.top_colors_free = ['#00FFFF', '#FF00FF', '#FFFF00']
        tool.top_colors_used = ['#0000FF', '#FF0000', '#00FF00']

        appMenu = AppMenu(tool)
        wizard = ProjectWizard(appMenu)

        self.assertFalse(hasattr(wizard, 'popup_window'))
        wizard._check_before_remove(0)
        self.assertTrue(hasattr(wizard, 'popup_window'))

        frame_children = wizard.popup_window.winfo_children()[0]. \
            winfo_children()
        self.assertEqual(len(frame_children), 3)

        self.assertEqual(frame_children[0].cget("text"),
                         "Delete Class?  You cannot undo this action.")
        self.assertEqual(frame_children[1].cget("text"), "Remove")
        self.assertEqual(frame_children[2].cget("text"), "Cancel")
Beispiel #9
0
    def test_select_image(self):
        tool = AnnotationTool()
        tool.load_app(True)

        appMenu = AppMenu(tool)
        complete = appMenu.select_image()
        self.assertTrue(complete)
        self.assertTrue(hasattr(appMenu, 'prompt'))
        self.assertTrue(hasattr(appMenu, 'prompt_entry'))

        prompt_frame = appMenu.prompt.winfo_children()[0]
        frame_child = prompt_frame.winfo_children()

        arr = ["Move to Image #", '', "Ok", "Cancel"]
        for i, child in enumerate(frame_child):
            self.assertEqual(frame_child[i].cget('text'), arr[i])
Beispiel #10
0
    def test_rename_class_action(self):
        tool = AnnotationTool()
        tool.load_app(True)
        tool.annotations = []

        tool.class_list = ['winston', 'prince', 'duckie']
        tool.colorspace = ['#0000FF', '#FF0000', '#00FF00']
        tool.class_count = [5, 15, 501]

        tool.top_colors_free = ['#00FFFF', '#FF00FF', '#FFFF00']
        tool.top_colors_used = ['#0000FF', '#FF0000', '#00FF00']

        appMenu = AppMenu(tool)
        wizard = ProjectWizard(appMenu)

        self.assertEqual(tool.class_list[0], 'winston')

        wizard._rename_class_window(0)
        wizard.rename_class_var.set('')
        wizard._rename_class_action(0)

        self.assertEqual(tool.class_list[0], 'winston')

        wizard._rename_class_window(0)
        wizard.rename_class_var.set('TestRename')
        wizard._rename_class_action(0)

        self.assertEqual(tool.class_list[0], 'TestRename')
Beispiel #11
0
    def test_choose_color(self):
        tool = AnnotationTool()
        tool.load_app(True)
        menu = AppMenu(tool)
        tool.annotations = []
        tool.class_list = ['winston', 'prince', 'duckie']
        tool.colorspace = ['#0000FF', '#FF0000', '#00FF00']
        tool.class_count = [5, 5, 5]

        tool.top_colors_free = ['#00FFFF', '#FF00FF', '#FFFF00']
        tool.top_colors_used = ['#0000FF', '#FF0000', '#00FF00']

        wizard = ProjectWizard(menu)

        self.assertEqual(len(tool.top_colors_used), 3)
        self.assertEqual(len(tool.top_colors_free), 3)

        wizard._choose_color(0)

        self.assertEqual(tool.colorspace[0], '#EEEEEE')
        self.assertEqual(tool.colorspace[1], '#FF0000')
        self.assertEqual(len(tool.top_colors_used), 2)
        self.assertEqual(len(tool.top_colors_free), 4)
        self.assertEqual(tool.top_colors_free[0], '#0000FF')

        wizard._choose_color(1)
        self.assertEqual(tool.colorspace[0], '#EEEEEE')
        self.assertEqual(tool.colorspace[1], '#EEEEEE')
        self.assertEqual(len(tool.top_colors_used), 1)
        self.assertEqual(len(tool.top_colors_free), 5)
        self.assertEqual(tool.top_colors_free[0], '#FF0000')
Beispiel #12
0
    def test_import_file(self):
        tool = AnnotationTool()
        tool.load_app(True)
        tool.annotations = []
        tool.file_list = []
        tool.current_file = 0
        tool.class_list = []
        tool.img = MockImg(640, 480)

        appMenu = AppMenu(tool)
        wizard = ProjectWizard(appMenu)

        complete = wizard._import_file(('test.jpg', ), MockMeta(6))
        self.assertTrue(complete)
        self.assertEqual(len(tool.annotations), 1)

        complete = wizard._import_file(('test2.jpg', ), MockMeta(6))
        self.assertTrue(complete)
        self.assertEqual(len(tool.annotations), 2)

        complete = wizard._import_file(('test.jpg', ), MockMeta(6))
        self.assertTrue(complete)
        self.assertEqual(len(tool.annotations), 2)

        complete = wizard._import_file(('test.png', ), MockMeta(6))
        self.assertTrue(complete)
        self.assertEqual(len(tool.annotations), 3)

        complete = wizard._import_file('', MockMeta(6))
        self.assertFalse(complete)
        self.assertEqual(len(tool.annotations), 3)
Beispiel #13
0
    def test_draw_right_pane(self):

        tool = AnnotationTool()
        tool.load_app(True)
        menu = AppMenu(tool)
        tool.annotations = []
        tool.class_list = ['winston', 'prince', 'duckie']
        tool.colorspace = ['#0000FF', '#FF0000', '#00FF00']
        tool.class_count = [5, 5, 5]

        tool.top_colors_free = ['#00FFFF', '#FF00FF', '#FFFF00']
        tool.top_colors_used = ['#0000FF', '#FF0000', '#00FF00']

        wizard = ProjectWizard(menu)
        self.assertTrue(hasattr(wizard, 'right_pane'))

        children = wizard.right_pane.winfo_children()

        self.assertEqual(len(children), 5)
        self.assertEqual(children[0].cget('text'), 'Object Class Manager')

        for i in range(3):
            child = children[i + 1].winfo_children()
            self.assertEqual(child[0].cget('text'),
                             '%d. %s' % (i + 1, tool.class_list[i]))
            self.assertEqual(child[1].cget('bg'), tool.colorspace[i])
            self.assertEqual(child[2].cget('text'), 'Rename')
            self.assertEqual(child[3].cget('text'), 'Delete')

        child = children[-1].winfo_children()
        self.assertEqual(child[1].cget('text'), 'Add Class')
Beispiel #14
0
    def test_close(self):
        tool = AnnotationTool()
        tool.load_app(True)
        tool.saved = False
        tool.project_open = True

        appMenu = AppMenu(tool)
        complete = appMenu._close()

        pop = appMenu.popup_window
        self.assertTrue(complete)
        self.assertFalse(tool.project_open)
        self.assertTrue(pop.winfo_exists())

        arr = ["Close without saving?", "Save", "Close", "Cancel"]
        for i in range(4):
            widget = pop.winfo_children()[0].winfo_children()[i]
            self.assertEqual(arr[i], widget.cget('text'))
Beispiel #15
0
    def test_open(self):
        tool = AnnotationTool()
        tool.load_app(True)

        # Annotation added
        tool.annotations = []
        tool.file_list = []
        tool.class_list = ['winston', 'prince', 'duckie']
        tool.colorspace = ['#0000FF', '#FF0000', '#00FF00']
        tool.current_file = 0
        tool.img = MockImg()

        for i in range(5):
            a = Annotation()
            a.rotation = 3
            tool.file_list.append('file%d.jpg' % i)
            for p in range(3):
                roi = ROI()
                roi.push(0, 0)
                roi.push(100.0, 100.0)
                a.push(roi, i % len(tool.class_list))
            tool.annotations.append(a)

        appMenu = AppMenu(tool)
        complete = appMenu._open('file.oaf')
        self.assertTrue(complete)
        self.assertEqual(tool.class_count, [6, 6, 3])
        self.assertTrue(tool.project_open)
        self.assertTrue(tool.saved)
        self.assertEqual(tool.top_colors_used, tool.colorspace)
        self.assertEqual(tool.top_colors_free, tool.top_colors[3:])

        appMenu = AppMenu(tool)
        complete = appMenu._open('')
        self.assertFalse(complete)
Beispiel #16
0
    def test_new(self):

        tool = AnnotationTool()
        tool.load_app(True)

        # Annotation added
        tool.annotations = []
        tool.file_list = []
        tool.class_list = ['winston', 'prince', 'duckie']
        tool.colorspace = ['#0000FF', '#FF0000', '#00FF00']
        tool.current_file = 0
        tool.class_count = [0, 15, 0]
        tool.img = MockImg()

        for i in range(5):
            a = Annotation()
            a.rotation = 3
            tool.file_list.append('file%d.jpg' % i)
            for p in range(3):
                roi = ROI()
                roi.push(0, 0)
                roi.push(100.0, 100.0)
                a.push(roi, 1)
            tool.annotations.append(a)

        tool._draw_workspace()

        appMenu = AppMenu(tool)
        complete = appMenu._new()

        self.assertTrue(complete)
        self.assertEqual(tool.file_list, [])
        self.assertTrue(tool.project_open)
        self.assertEqual(tool.annotations, [])
        self.assertEqual(tool.top_colors_free, tool.top_colors)
        self.assertEqual(tool.top_colors_used, [])
        self.assertEqual(tool.class_count, [])
        self.assertEqual(tool.current_file, 0)
        self.assertEqual(tool.class_list, [])
        self.assertEqual(tool.colorspace, [])
Beispiel #17
0
    def test_cancel_project(self):
        tool = AnnotationTool()
        tool.load_app(True)
        tool.annotations = []
        tool.class_list = ['winston', 'prince', 'duckie']
        tool.colorspace = ['#0000FF', '#FF0000', '#00FF00']

        appMenu = AppMenu(tool)
        wizard = ProjectWizard(appMenu)

        self.assertTrue(tool.saved)
        self.assertTrue(wizard.wizard_window.winfo_exists())
        wizard._cancel_project()
        self.assertTrue(tool.saved)
        self.assertFalse(wizard.wizard_window.winfo_exists())
Beispiel #18
0
    def test_draw_left_pane(self):
        tool = AnnotationTool()
        tool.load_app(True)
        menu = AppMenu(tool)
        tool.annotations = []
        tool.class_list = []

        wizard = ProjectWizard(menu)
        self.assertTrue(hasattr(wizard, 'left_pane'))

        children = wizard.left_pane.winfo_children()

        self.assertEqual(len(children), 5)
        self.assertEqual(children[0].cget('text'), 'Import File(s) to Project')
        self.assertEqual(children[1].cget('text'),
                         'Import Entire Directory to Project')
        self.assertEqual(children[2].cget('text'),
                         'Project has 0 files for annotation.')
        self.assertEqual(children[3].cget('text'), 'Build Project')
        self.assertEqual(children[4].cget('text'), 'Main Menu')
Beispiel #19
0
    def test_rename_class_window(self):
        tool = AnnotationTool()
        tool.load_app(True)
        tool.annotations = []

        tool.class_list = ['winston', 'prince', 'duckie']
        tool.colorspace = ['#0000FF', '#FF0000', '#00FF00']
        tool.class_count = [5, 15, 501]

        tool.top_colors_free = ['#00FFFF', '#FF00FF', '#FFFF00']
        tool.top_colors_used = ['#0000FF', '#FF0000', '#00FF00']

        appMenu = AppMenu(tool)
        wizard = ProjectWizard(appMenu)

        wizard._rename_class_window(0)

        self.assertTrue(hasattr(wizard, 'rename_entry'))
        self.assertTrue(hasattr(wizard, 'rename_class_prompt'))

        frame_children = wizard.rename_class_prompt.winfo_children()[0] \
            .winfo_children()
        self.assertEqual(len(frame_children), 4)
        self.assertEqual(frame_children[0].cget("text"),
                         'Rename \"winston\" Class to:')
        self.assertEqual(frame_children[2].cget("text"), "Ok")
        self.assertEqual(frame_children[3].cget("text"), "Cancel")

        wizard._rename_class_window(1)

        self.assertTrue(hasattr(wizard, 'rename_entry'))
        self.assertTrue(hasattr(wizard, 'rename_class_prompt'))

        frame_children = wizard.rename_class_prompt.winfo_children()[0] \
            .winfo_children()
        self.assertEqual(len(frame_children), 4)
        self.assertEqual(frame_children[0].cget("text"),
                         'Rename \"prince\" Class to:')
        self.assertEqual(frame_children[2].cget("text"), "Ok")
        self.assertEqual(frame_children[3].cget("text"), "Cancel")
Beispiel #20
0
    def test_quit(self):
        tool = AnnotationTool()
        tool.load_app(True)

        tool.saved = False
        appMenu = AppMenu(tool)
        popup = appMenu._quit()

        children = popup.winfo_children()[0].winfo_children()

        arr = ["Quit without saving?", "Save", "Quit", "Cancel"]
        for i, child in enumerate(children):
            self.assertEqual(child.cget('text'), arr[i])

        tool.saved = True
        appMenu = AppMenu(tool)
        complete = appMenu._quit()
        self.assertTrue(complete)
Beispiel #21
0
    def test_init(self):
        tool = AnnotationTool()
        tool.load_app(True)
        menu = AppMenu(tool)
        tool.annotations = []
        tool.class_list = []

        wizard = ProjectWizard(menu)
        self.assertTrue(hasattr(wizard, 'root_app'))
        self.assertEqual(tool, wizard.root_app)
        self.assertTrue(hasattr(wizard, 'menu_app'))
        self.assertTrue(hasattr(wizard, 'window_width'))
        self.assertTrue(hasattr(wizard, 'window_height'))
        self.assertTrue(hasattr(wizard, 'left_pane_width'))
        self.assertTrue(hasattr(wizard, 'right_pane_width'))
        self.assertEqual(wizard.window_width, 1024)
        self.assertEqual(wizard.window_height, 768)
        self.assertEqual(wizard.left_pane_width, 300)
        self.assertEqual(wizard.right_pane_width, 723)

        self.assertTrue(hasattr(wizard, 'wizard_window'))
        self.assertTrue(hasattr(wizard, 'background'))
        self.assertEqual(wizard.background.cget('width'), 1024)
        self.assertEqual(wizard.background.cget('height'), 768)
Beispiel #22
0
    def test_file_to_annotation(self):
        tool = AnnotationTool()
        tool.load_app(True)
        tool.annotations = []

        appMenu = AppMenu(tool)

        complete = appMenu.file_to_annotation('test.jpg', MockMeta(6))
        self.assertTrue(complete)
        self.assertEqual(tool.annotations[-1].rotation, Image.ROTATE_270)

        complete = appMenu.file_to_annotation('test2.jpg', MockMeta(3))
        self.assertTrue(complete)
        self.assertEqual(tool.annotations[-1].rotation, Image.ROTATE_180)

        complete = appMenu.file_to_annotation('test3.jpg', MockMeta(8))
        self.assertTrue(complete)
        self.assertEqual(tool.annotations[-1].rotation, Image.ROTATE_90)

        complete = appMenu.file_to_annotation('test1.png', MockMeta(8))
        self.assertTrue(complete)
        self.assertEqual(tool.annotations[-1].rotation, Image.ROTATE_90)
Beispiel #23
0
    def test_draw_menu(self):
        tool = AnnotationTool()
        tool.load_app(True)

        appMenu = AppMenu(tool)
        menu, fileMenu, toolMenu, helpMenu = appMenu._draw_menu()

        self.assertTrue(menu.winfo_exists())
        self.assertEqual(len(menu.winfo_children()), 2)
        self.assertEqual(menu.entrycget(1, 'label'), 'File')
        self.assertEqual(menu.entrycget(2, 'label'), 'Help')

        self.assertTrue(fileMenu.winfo_exists())
        self.assertEqual(fileMenu.entrycget(1, 'label'), 'New Blank Project')
        self.assertEqual(fileMenu.entrycget(2, 'label'), 'New Project Wizard')
        self.assertEqual(fileMenu.entrycget(3, 'label'), 'Open Project')
        self.assertEqual(fileMenu.entrycget(5, 'label'), 'Quit')

        self.assertFalse(toolMenu)

        self.assertTrue(helpMenu.winfo_exists())
        self.assertEqual(helpMenu.entrycget(1, 'label'),
                         "OpenAnnotation Documentation")
        self.assertEqual(helpMenu.entrycget(2, 'label'),
                         "About OpenAnnotation")

        tool.project_open = True
        tool.annotations = []
        menu, fileMenu, toolMenu, helpMenu = appMenu._draw_menu()

        self.assertTrue(menu.winfo_exists())
        self.assertEqual(len(menu.winfo_children()), 3)
        self.assertEqual(menu.entrycget(1, 'label'), 'File')
        self.assertEqual(menu.entrycget(2, 'label'), 'Tools')
        self.assertEqual(menu.entrycget(3, 'label'), 'Help')

        self.assertTrue(fileMenu.winfo_exists())
        self.assertEqual(fileMenu.entrycget(1, 'label'), 'New Blank Project')
        self.assertEqual(fileMenu.entrycget(2, 'label'), 'New Project Wizard')
        self.assertEqual(fileMenu.entrycget(3, 'label'), 'Open Project')
        self.assertEqual(fileMenu.entrycget(4, 'label'), 'Save Project')
        self.assertEqual(fileMenu.entrycget(5, 'label'), 'Close Project')
        self.assertEqual(fileMenu.entrycget(7, 'label'), "Import File(s)")
        self.assertEqual(fileMenu.entrycget(8, 'label'),
                         "Import Entire Directory")
        self.assertEqual(fileMenu.entrycget(9, 'label'),
                         "Export Project to CSV")
        self.assertEqual(fileMenu.entrycget(11, 'label'), 'Quit')

        self.assertTrue(toolMenu.winfo_exists())
        self.assertEqual(toolMenu.entrycget(1, 'label'), "Class Manager")
        self.assertEqual(toolMenu.entrycget(2, 'label'), 'Options')
        self.assertEqual(toolMenu.entrycget(3, 'label'), "Options")

        self.assertTrue(helpMenu.winfo_exists())
        self.assertEqual(helpMenu.entrycget(1, 'label'),
                         "OpenAnnotation Documentation")
        self.assertEqual(helpMenu.entrycget(2, 'label'),
                         "About OpenAnnotation")

        tool.annotations.append(Annotation())
        self.assertTrue(toolMenu.winfo_exists())
        _, _, toolMenu, _ = appMenu._draw_menu()

        self.assertEqual(toolMenu.entrycget(1, 'label'), "Class Manager")
        self.assertEqual(toolMenu.entrycget(2, 'label'), 'Options')
        self.assertEqual(toolMenu.entrycget(3, 'label'), "Reset Image")
        self.assertEqual(toolMenu.entrycget(4, 'label'), 'Select Image #')
Beispiel #24
0
 def test_init(self):
     tool = AnnotationTool()
     menu = AppMenu(tool)
     self.assertEqual(menu.root_app, tool)
Beispiel #25
0
    def __init__(self):
        '''
        This is the main annotation tool object.  Running this .py file will
        open the application.
        
        Parameters
        ----------
        None
    
        Attributes
        ----------
        file_ext : list (Default = ['.jpg', '.png']) 
            Image file extensions currently supported by OpenAnnotation
        window_size_strings : list (Default = ["1024x768", "800x600"])
            These are the supported Window Sizes.
        window_size_index : int
            Which window size in window_size_strings is currently selected
        window_width : int
            The number of pixels the window width is
        window_height : int
            The number of pixels the window height is
        page : int
            The current page in the image Navigator
        navigator_width : int
            The number of images in the Image Navigator
        toolbar_height : int
            The number of pixels the Toolbar height is
        canvas_width : int
            The remaining window size is for the Canvas object
        canvas_height : int
            The remaining window size is for the Canvas object
        project_open : bool
            This tracks if the project is open for display purposes
        saved : bool
            This tracks if the current project is saved
        app_menu : The OpenAnnotation AppMenu object
            Initialize the menu across the top of the window
        top_colors : list
            The default colors are blue, red, green, cyan, yellow, and magenta
                
        Raises
        ------
        None
    
        Returns
        -------
        None

        '''
        self.file_ext = ['.jpg', '.png']
        self.window_size_strings = ["1024x768", "800x600"]
        self.window_size_index = 0
        self.window_width = 1024
        self.window_height = 768

        self.page = 0
        self.img_per_page = 50

        
        self.toolbar_height = 50
        self.navigator_width = 200      
        
        self.canvas_width = self.window_width - self.navigator_width
        self.canvas_height = self.window_height - self.toolbar_height
            
        self.project_open = False
        self.saved = True
        self.app_menu = AppMenu(self)
        self.top_colors = ['#0000FF', '#FF0000', '#00FF00', '#00FFFF', 
                           '#FF00FF', '#FFFF00'] 
Beispiel #26
0
    def test_select_image_action(self):
        tool = AnnotationTool()
        tool.load_app(True)
        tool.annotations = [Annotation(), Annotation(), Annotation()]

        appMenu = AppMenu(tool)
        appMenu.select_image()
        appMenu.prompt_entry.insert(0, "1")
        complete = appMenu.select_image_action()
        self.assertTrue(complete)

        appMenu.select_image()
        appMenu.prompt_entry.insert(0, "4")
        complete = appMenu.select_image_action()
        self.assertFalse(complete)

        appMenu.select_image()
        appMenu.prompt_entry.insert(0, "-1")
        complete = appMenu.select_image_action()
        self.assertFalse(complete)
Beispiel #27
0
class AnnotationTool(object):
    
    def __init__(self):
        '''
        This is the main annotation tool object.  Running this .py file will
        open the application.
        
        Parameters
        ----------
        None
    
        Attributes
        ----------
        file_ext : list (Default = ['.jpg', '.png']) 
            Image file extensions currently supported by OpenAnnotation
        window_size_strings : list (Default = ["1024x768", "800x600"])
            These are the supported Window Sizes.
        window_size_index : int
            Which window size in window_size_strings is currently selected
        window_width : int
            The number of pixels the window width is
        window_height : int
            The number of pixels the window height is
        page : int
            The current page in the image Navigator
        navigator_width : int
            The number of images in the Image Navigator
        toolbar_height : int
            The number of pixels the Toolbar height is
        canvas_width : int
            The remaining window size is for the Canvas object
        canvas_height : int
            The remaining window size is for the Canvas object
        project_open : bool
            This tracks if the project is open for display purposes
        saved : bool
            This tracks if the current project is saved
        app_menu : The OpenAnnotation AppMenu object
            Initialize the menu across the top of the window
        top_colors : list
            The default colors are blue, red, green, cyan, yellow, and magenta
                
        Raises
        ------
        None
    
        Returns
        -------
        None

        '''
        self.file_ext = ['.jpg', '.png']
        self.window_size_strings = ["1024x768", "800x600"]
        self.window_size_index = 0
        self.window_width = 1024
        self.window_height = 768

        self.page = 0
        self.img_per_page = 50

        
        self.toolbar_height = 50
        self.navigator_width = 200      
        
        self.canvas_width = self.window_width - self.navigator_width
        self.canvas_height = self.window_height - self.toolbar_height
            
        self.project_open = False
        self.saved = True
        self.app_menu = AppMenu(self)
        self.top_colors = ['#0000FF', '#FF0000', '#00FF00', '#00FFFF', 
                           '#FF00FF', '#FFFF00'] 
        
    def load_app(self, test=False):
        '''
        This loads the main window for the OpenAnnotation applications
        
        Parameters
        ----------
        test : bool (Default = False)
            If test=True, then the window is not actually drawn
    
        Attributes
        ----------
        window : tkinter Tk object
            This is the main application window
        background : tkinter Frame object
            This is the frame that covers the entire window object
                
        Raises
        ------
        None
    
        Returns
        -------
        complete : bool
            Returns True for unittesting

        '''        
        # Build Window
        self.window = tk.Tk()
            
        self.window.title("OpenAnnotation 0.2.1")  # to define the title
        self.window.geometry("%dx%d" % (self.window_width,self.window_height))
        self.app_menu._draw_menu()
                   
        self.background = Frame(self.window,
                                width=self.window_width,
                                height=self.window_height)
        self.background.pack()
                
        # Create Load Screen Buttons
        new_button = Button(self.background, text="New Blank Project", 
                            width = 20,
                            height=3, 
                            command=self.app_menu._new)
        new_button.grid(row=0, column=0, sticky='n', pady=2 )

        new_wiz_button = Button(self.background, 
                                     text="New Project Wizard", 
                                     width = 20,
                                     height=3, 
                                     command=self.app_menu._new_project_wizard)
        new_wiz_button.grid(row=1, column=0, sticky='n', pady=2 )

        load_button = Button(self.background, text="Load Project", 
                            width=20,
                            height=3, 
                            command=self.app_menu._open)
        load_button.grid(row=2, column=0, sticky='n', pady=2)

        quit_button = Button(self.background, text="Quit", 
                            width=20, 
                            height=3, 
                            command=self.app_menu._quit)
        quit_button.grid(row=3, column=0, sticky='n', pady=2)
        
        if not test:
            self.window.mainloop()

        return True
        
    def _draw_object_class_manager(self):
        '''
        This draws the Object Class Management Tool in a popup window
        
        Parameters
        ----------
        None
    
        Attributes
        ----------
        obj_mgr : OpenAnnotation ObjectClassManager object
            This is the Object Class Management tool accessible from the
            toolbar up top
                
        Raises
        ------
        None
    
        Returns
        -------
        complete : bool
            Returns True for unittesting

        '''          
        self.obj_mgr = ObjectClassManager(self)
        return True
        
    def _draw_workspace(self):
        '''
        This draws the main project in the background frame
        
        Parameters
        ----------
        None
    
        Attributes
        ----------
        background : tkinter Frame object
            This is the frame that covers the entire window object
            
        Raises
        ------
        None
    
        Returns
        -------
        complete : bool
            Returns True for unittesting
    
        '''         
        self.app_menu._draw_menu()
        
        self.background.destroy()
        
        # Build Background Frame                       
        self.background = Frame(self.window,
                                bg="gray",
                                width=self.window_width,
                                height=self.window_height)
        self.background.place(x=0, 
                              y=0,
                              width = self.window_width,
                              height = self.window_height)

        if self.annotations:
            self.num_pages = int(len(self.annotations)/self.img_per_page)

        # Draw Toolbar on Left
        toolbar = Toolbar(self)
           
        # Draw Canvas on Right
        self.draw_canvas()
                        
        if len(self.annotations):
            self.navigator = Navigator(self)

        return True


    def draw_canvas(self):
        '''
        This draws the canvas in the main window.
        
        Parameters
        ----------
        None
    
        Attributes
        ----------
        canvas : tkinter Canvas object
            This is what the image is drawn on
        aspect_ratio : float
            Compute the scale factor to shrink/increase the image to fit in
            the canvas
        boxes : list
            A list for the OpenAnnotation InteractiveBox objects
            
        Raises
        ------
        None
    
        Returns
        -------
        complete : bool
            Returns True for unittesting
    
        '''   
        
        # Draw Canvas on Right        
        canvas_frame = Frame(self.background, bg='green',
                    width=self.canvas_width,
                    height=self.canvas_height)
        canvas_frame.place(x=0,
                                y=self.toolbar_height, 
                                width = self.canvas_width,
                                height = self.canvas_height,
                                )
        
        self.canvas = Canvas(canvas_frame,
                                   width=self.canvas_width, 
                                   height=self.canvas_height)
        self.canvas.place(x=0,
                         y=0, 
                         width = self.canvas_width,
                         height = self.canvas_height,
                                )
                        
        if len(self.annotations):
            
            self.aspect_ratio = max(self.img.size[0]/(self.canvas_width),
                                    self.img.size[1]/(self.canvas_height)) 
                                
            new_size = (int(self.img.size[0]/self.aspect_ratio), 
                        int(self.img.size[1]/self.aspect_ratio))
            
            if self.window.winfo_ismapped():

                pil_img = ImageTk.PhotoImage(self.img.resize(new_size, 
                                                      Image.ANTIALIAS))
            else:
                pil_img = None
                
            self.canvas.image = pil_img
            self.canvas.create_image(0, 0, anchor=tk.NW, image=pil_img)
            
            self.boxes = []
            
            for i, roi in enumerate(self.annotations[self.current_file].roi):
                
                left, top, right, bottom = roi.getBox()
                lbl = self.annotations[self.current_file].label[i]
                
                left = left / self.aspect_ratio
                top = top / self.aspect_ratio
                right = right / self.aspect_ratio
                bottom = bottom / self.aspect_ratio
                color = self.colorspace[lbl]
                
                box = InteractiveBox(self, left, top, right, bottom, color)
                box.draw_box(i)
                self.boxes.append(box)

        # Only allow bounding boxes to be drawn if they can be tied to a class
        if len(self.class_list) and len(self.annotations):        
            self.canvas.bind("<Button-1>",self._on_click)
            self.canvas.bind("<ButtonRelease-1>",self._on_release)
            self.canvas.bind("<B1-Motion>", self._on_move_press)

        return True


    def _on_click(self, event):
        '''
        This handles the click-hold Event
        
        Parameters
        ----------
        event : tkinter Event
            Event that handles the mouse being clicked, creating the first of
            two bounding box corners
    
        Attributes
        ----------
        clicked : tuple
            The (x,y) coordinate for the mouse click event
        box_resize_mode : string
            Defines the type of box action that will occur.  Options are
            'RIGHT', 'LEFT', 'TOP', 'BOTTOM', or 'NEW'.
        resize_box_id : int
            This is which ROI object has been clicked on
            
        Raises
        ------
        None
    
        Returns
        -------
        complete : bool
            Returns True for unittesting
    
        '''    
        
        self.clicked = (event.x, event.y)
        
        for i, box in enumerate(self.boxes):
            if box.right_clicked(self.clicked[0], self.clicked[1]):
                self.box_resize_mode = 'RIGHT'
                self.resize_box_id = i
                return True
            elif box.left_clicked(self.clicked[0], self.clicked[1]):
                self.box_resize_mode = 'LEFT'
                self.resize_box_id = i
                return True
            elif box.top_clicked(self.clicked[0], self.clicked[1]):
                self.box_resize_mode = 'TOP'
                self.resize_box_id = i
                return True
            elif box.bottom_clicked(self.clicked[0], self.clicked[1]):
                self.box_resize_mode = 'BOTTOM'
                self.resize_box_id = i
                return True
        
        self.box_resize_mode = 'NEW'
        return True
    
    def _on_release(self, event):
        '''
        This handles when the mouse left-button has been released, which adds
        a new bounding box or resizes an existing box.
        
        Parameters
        ----------
        event : tkinter Event
            Event that handles the mouse being clicked, creating the first of
            two bounding box corners
    
        Attributes
        ----------
        None
            
        Raises
        ------
        None
    
        Returns
        -------
        complete : bool
            Returns True for unittesting
    
        '''            
        if self.box_resize_mode == 'NEW':

            top = min(self.clicked[1], event.y)
            bottom = max(self.clicked[1], event.y)
            left = min(self.clicked[0], event.x)
            right = max(self.clicked[0], event.x)
            label = self.class_list.index(self.selected_class.get())
            color = self.colorspace[label]
            
            box = InteractiveBox(self, left, top, right, bottom, color)
            
            self.canvas.delete(self.rect)
            del self.rect
            box.draw_box(len(self.annotations[self.current_file].roi))
            
            top = self.aspect_ratio * top
            bottom = self.aspect_ratio * bottom
            left = self.aspect_ratio * left
            right = self.aspect_ratio * right
            
            roi = ROI()
            roi.push(left, top)
            roi.push(right, bottom)
            self.annotations[self.current_file].push(roi,label)
            
            self.class_count[label] = self.class_count[label] + 1
        self.draw_canvas()
        self.saved = False
        self.box_resize_mode = 'NEW'
        return True
        
    def _on_move_press(self, event):
        '''
        This handles the event where the mouse left-button is held down and 
        the cursor is moved across the screen.
        
        Parameters
        ----------
        event : tkinter Event
            Event that handles the mouse being clicked, creating the first of
            two bounding box corners
    
        Attributes
        ----------
        rect : tkinter Canvas create_rectangle object
            The bounding box that will be drawn on the Canvas
        box_end : tuple
            The (x,y) coordinate for the mouse motion event
            
        Raises
        ------
        None
    
        Returns
        -------
        complete : bool
            Returns True for unittesting
    
        '''            
        if hasattr(self, 'resize_box_id'):
            box_id = self.resize_box_id
        
        if self.box_resize_mode != 'NEW':
            if hasattr(self.boxes[box_id],'close_button'):
                self.boxes[box_id].close_button.destroy()
               
        if self.box_resize_mode == 'RIGHT':
            self.canvas.coords(self.boxes[box_id].rect, 
                   self.boxes[box_id].left, 
                   self.boxes[box_id].top,
                   event.x,
                  self.boxes[box_id].bottom)
            self.boxes[box_id].right = event.x
            self.annotations[self.current_file].roi[box_id].points[1][0] =\
                event.x * self.aspect_ratio
        elif self.box_resize_mode == 'LEFT':
            self.canvas.coords(self.boxes[self.resize_box_id].rect, 
                   event.x, 
                   self.boxes[self.resize_box_id].top,
                   self.boxes[self.resize_box_id].right,
                   self.boxes[self.resize_box_id].bottom)
            self.boxes[self.resize_box_id].left = event.x
            self.annotations[self.current_file].roi[box_id].points[0][0] =\
                event.x * self.aspect_ratio
        elif self.box_resize_mode == 'TOP':
            self.canvas.coords(self.boxes[self.resize_box_id].rect, 
                   self.boxes[self.resize_box_id].left, 
                   event.y,
                   self.boxes[self.resize_box_id].right,
                   self.boxes[self.resize_box_id].bottom)
            self.boxes[self.resize_box_id].top = event.y
            self.annotations[self.current_file].roi[box_id].points[0][1] =\
                event.y * self.aspect_ratio
        elif self.box_resize_mode == 'BOTTOM':
            self.canvas.coords(self.boxes[self.resize_box_id].rect, 
                   self.boxes[self.resize_box_id].left, 
                   self.boxes[self.resize_box_id].top,
                   self.boxes[self.resize_box_id].right,
                   event.y)
            self.boxes[self.resize_box_id].bottom = event.y
            self.annotations[self.current_file].roi[box_id].points[1][1] =\
                event.y * self.aspect_ratio

        elif not hasattr(self, 'rect'):
    
            label = self.selected_class.get()
            color = self.colorspace[self.class_list.index(label)]
            self.rect = self.canvas.create_rectangle(self.clicked[0], 
                                                     self.clicked[1], 
                                                     self.clicked[0], 
                                                     self.clicked[1], 
                                                     width=5,
                                                     outline=color)
        else:
            self.box_end = (event.x, event.y)
            self.canvas.coords(self.rect, 
                               self.clicked[0], 
                               self.clicked[1],
                               event.x,
                               event.y)

        return True

        
    def _load_image_from_file(self):
        '''
        This uses PIL to load the current Image displayed in the project
        
        Parameters
        ----------
        None
    
        Attributes
        ----------
        img : PIL Image object
            The Image is opened and rotated upright using EXIF metadata
            
        Raises
        ------
        None
    
        Returns
        -------
        complete : bool
            Returns True for unittesting
    
        '''   

        if self.window.winfo_ismapped():
            self.img = Image.open(self.file_list[self.current_file])
        else:
            self.img = Image.new('RGB', (self.canvas_width, 
                                         self.canvas_height))
        
        rot = self.annotations[self.current_file].rotation
        if rot > 0:
            self.img = self.img.transpose(rot)
                
    def _reset_image(self):
        '''
        This deletes all annotations made on a given image
        
        Parameters
        ----------
        None
    
        Attributes
        ----------
        None
            
        Raises
        ------
        None
    
        Returns
        -------
        complete : bool
            Returns True for unittesting
    
        '''           
        for lbl in self.annotations[self.current_file].label:
            self.class_count[lbl] = self.class_count[lbl] - 1
        
        self.annotations[self.current_file].label = []
        self.annotations[self.current_file].roi = []
        self._draw_workspace()
        return True