Exemplo n.º 1
0
class ImageSelectWindow(object):
    def __init__(self):
        self.image_Wid = 300
        self.image_Hei = 300
        self.image_interval = 10
        self.canvas_Wid = 930
        self.canvas_Hei = 600
        self.window_wid = self.canvas_Wid + 160
        self.window_Hei = self.canvas_Hei

        # init state control variable
        self.has_select_root_path = False  # sign has select root path(where the sub-directories save) or not
        self.root_path = ''
        self.group_list = []

        # create main window
        self.mainWin = Tkinter.Tk()
        self.mainWin.geometry(
            str(self.window_wid) + 'x' +
            str(self.window_Hei))  # init the size of window
        self.mainWin.title("image select tool")
        self.mainWin.tk.eval('package require Tix')
        # bind the key press event(space to pass, q to quit)
        self.mainWin.bind('<KeyPress>', self._keyPressEvent)

        # create init image(a black background)
        self.img_path_list = []
        self.photo_img_list = []

        # create Canvas control
        self.max_shown_num = 90
        self.cv = Canvas(self.mainWin,
                         bg='white',
                         width=self.canvas_Wid,
                         height=self.canvas_Hei,
                         scrollregion=(0, 0, self.canvas_Wid,
                                       (self.image_Hei + self.image_interval) *
                                       math.ceil(self.max_shown_num / 3)))
        self.vbar = Scrollbar(self.cv, orient=Tkinter.VERTICAL)
        self.vbar.pack(side=Tkinter.RIGHT, fill=Tkinter.Y)
        self.vbar.config(command=self.cv.yview)
        self.cv.config(yscrollcommand=self.vbar.set)
        self.cv.pack(side=Tkinter.LEFT, expand=True, fill=Tkinter.BOTH)
        # bind the mouse click event
        self.cv.bind('<Button-1>', self._mouseClickEvent)
        # bind the mouse wheel event
        self.cv.bind_all('<MouseWheel>', self._mouseWheelEvent)

        # create total Frame to lay out all components
        self.frame = Frame(self.mainWin, width=250, height=self.window_Hei)
        self.frame.pack(side=Tkinter.LEFT)

        # create text control
        self.save_path = './image_select_result'
        self.entry = Entry(self.frame, state='normal')
        self.entry.pack(side=Tkinter.TOP)
        self.entry.insert(0, self.save_path)

        # create 'START' button
        self.btn_start = Button(self.frame,
                                text='START',
                                command=self._selectPath,
                                activeforeground='blue',
                                activebackground='white',
                                bg='blue',
                                fg='white')
        self.btn_start.pack(side=Tkinter.TOP, pady=30)

        # create data annotation label button
        self.btn_pass = Button(self.frame,
                               text='PASS',
                               command=lambda: self._passCurrentGroup(),
                               activeforeground='black',
                               activebackground='blue',
                               bg='white',
                               fg='black')
        self.btn_pass.pack(side=Tkinter.TOP, pady=30)

        #NumericUpDown控件
        self.num_count = Control(self.frame,
                                 integer=True,
                                 max=-1,
                                 min=-1,
                                 value=-1,
                                 step=1,
                                 label='current Image:',
                                 command=self._showImages)
        self.num_count.label.config(font='Helvetica -14 bold')
        self.num_count.pack(side=Tkinter.TOP, pady=30)

        # create 'QUIT' button
        self.btn_quit = Button(self.frame,
                               text='QUIT',
                               command=self.mainWin.quit,
                               activeforeground='blue',
                               activebackground='white',
                               bg='red',
                               fg='white')
        self.btn_quit.pack(side=Tkinter.BOTTOM, pady=100)

    def _keyPressEvent(self, event):
        if event.keycode == 32:
            self._passCurrentGroup()
        elif event.keycode == 81:
            self.mainWin.destroy()

    def _mouseClickEvent(self, event):
        # get coordinate of x
        x_coordinate = event.x

        # compute coordinate of y
        # get the location of the scrollBar in the scroll range
        scale = self.vbar.get()[0]
        start_y = scale * ((self.image_Hei + self.image_interval) *
                           math.ceil(self.max_shown_num / 3))
        y_coordinate = start_y + event.y
        self._selectOneImage(x_coordinate, y_coordinate)

    def _mouseWheelEvent(self, event):
        self.cv.yview_scroll(-1 * (event.delta / 20), "units")

    def _showImages(self, ev=None):
        if self.has_select_root_path:
            if int(self.num_count['value']) == -1:
                # clear the images draw before first
                for idx in range(len(self.img_path_list)):
                    self.cv.delete(self.img_path_list[idx])

                self.img_path_list = []
                self.photo_img_list = []
                return
            else:
                # clear the images draw before first
                for idx in range(len(self.img_path_list)):
                    self.cv.delete(self.img_path_list[idx])

                # get the current group path and images list
                img_group_path = self.group_list[int(self.num_count['value'])]
                self.img_path_list = self._getImagePathList(img_group_path)
                self.img_path_list = self.img_path_list[:min(
                    len(self.img_path_list), self.max_shown_num)]
                self.photo_img_list = []
                for idx in range(len(self.img_path_list)):
                    # load the current image
                    cur_img_path = self.img_path_list[idx]
                    cur_img = Image.open(cur_img_path).resize(
                        (self.image_Wid, self.image_Hei))
                    self.photo_img_list.append(ImageTk.PhotoImage(cur_img))
                    # draw cur image to the appropriate location by index
                    x_coordinate = (idx % 3) * (self.image_Wid +
                                                self.image_interval)
                    y_coordinate = math.floor(
                        idx / 3) * (self.image_Hei + self.image_interval)
                    self.cv.create_image((x_coordinate, y_coordinate),
                                         anchor=Tkinter.NW,
                                         image=self.photo_img_list[idx],
                                         tags=self.img_path_list[idx])
                    # give a tag is convenient for delete later

    def _passCurrentGroup(self):
        cur_idx = int(self.num_count['value'])
        if cur_idx != -1:
            # check has next group or not
            if cur_idx + 1 < len(self.group_list):
                self.num_count['value'] = str(cur_idx + 1)
            else:
                tkMessageBox.showinfo(
                    title='thanks',
                    message='all the image select mission has finished~')

    def _selectOneImage(self, x_coordinate, y_coordinate):
        cur_idx = int(self.num_count['value'])
        if cur_idx == -1:
            return
        col = math.floor(x_coordinate / (self.image_Wid + self.image_interval))
        row = math.floor(y_coordinate / (self.image_Hei + self.image_interval))
        idx = int(row * 3 + col)
        if idx < len(self.img_path_list):
            img_click_path = self.img_path_list[idx]
            cur_img = Image.open(img_click_path)
            img_name = img_click_path.split('\\')[-1]
            cur_save_path = os.path.join(self.save_path, img_name)
            cur_img.save(cur_save_path)

    def _selectPath(self):
        self.root_path = tkFileDialog.askdirectory()
        self.group_list = self._getGroupPathList()
        if len(self.group_list) > 0:
            self.has_select_root_path = True
            self.num_count.config(max=len(self.group_list) - 1)
            self.num_count['value'] = str(0)
        else:
            self.has_select_root_path = False
            self.num_count['value'] = str(-1)
            self.num_count.config(max=-1)
            tkMessageBox.showwarning(
                'warning',
                'No available sub-directories detected! please re-select root path and start'
            )

    def _getGroupPathList(self):
        group_list = []
        for root, dirs, files in os.walk(self.root_path):
            for dir_name in dirs:
                cur_group_path = os.path.join(root, dir_name)
                group_list.append(cur_group_path)
        return group_list

    def _getImagePathList(self, img_group_path):
        img_path_list = []
        for root, dirs, files in os.walk(img_group_path):
            for file_name in files:
                cur_img_path = os.path.join(img_group_path, file_name)
                img_path_list.append(cur_img_path)
        return img_path_list
Exemplo n.º 2
0
class DataAnnotationWindow(object):
    def __init__(self):
        self.img_Wid = 500
        self.img_Hei = 500
        self.win_wid = self.img_Wid + 200
        self.win_Hei = self.img_Hei

        # init state control variable
        self.has_select_path = False  # sign has select image path(to do data annotation) or not
        self.img_path = ''
        self.img_list = []

        # create main window
        self.mainWin = Tkinter.Tk()
        self.mainWin.geometry(str(self.win_wid) + 'x' +
                              str(self.win_Hei))  # init the size of window
        self.mainWin.title("data annotation tool")
        self.mainWin.tk.eval('package require Tix')

        # create init image(a black background)
        self.img = Image.new("RGB", (self.img_Wid, self.img_Hei), (0, 0, 0))
        self.photo_img = ImageTk.PhotoImage(self.img)

        # create Canvas control
        self.cv = Canvas(self.mainWin,
                         bg='white',
                         width=self.img_Wid,
                         height=self.img_Hei)
        self.cv.create_image((0, 0), anchor=Tkinter.NW, image=self.photo_img)
        self.cv.pack(side=Tkinter.LEFT, expand=True)

        # create total Frame to lay out all components
        self.frame = Frame(self.mainWin)
        self.frame.pack(fill=Tkinter.X, expand=Tkinter.YES, side=Tkinter.LEFT)

        # create text control
        root_save_path = './data_annotation_result'
        self.entry = Entry(self.frame, state='normal')
        self.entry.pack(side=Tkinter.TOP, fill=Tkinter.X)
        self.entry.insert(0, root_save_path)
        # mkdir of annotation result
        self.categoryList = ['Dog', 'Cat']
        self.category_savepath_list = []
        for category in self.categoryList:
            cur_category_save_path = os.path.join(root_save_path, category)
            self.category_savepath_list.append(cur_category_save_path)
            if os.path.exists(cur_category_save_path) == False:
                os.mkdir(cur_category_save_path)

        # create 'START' button
        self.btn_start = Button(self.frame,
                                text='START',
                                command=self._selectPath,
                                activeforeground='blue',
                                activebackground='white',
                                bg='blue',
                                fg='white')
        self.btn_start.pack(side=Tkinter.TOP, pady=30)

        # create data annotation label button
        self.btn_dog = Button(self.frame,
                              text='Dog',
                              command=lambda: self._labelButtonClick('Dog'),
                              activeforeground='black',
                              activebackground='blue',
                              bg='white',
                              fg='black')
        self.btn_dog.pack(side=Tkinter.TOP, pady=10)

        # create data annotation label button
        self.btn_cat = Button(self.frame,
                              text='Cat',
                              command=lambda: self._labelButtonClick('Cat'),
                              activeforeground='black',
                              activebackground='blue',
                              bg='white',
                              fg='black')
        self.btn_cat.pack(side=Tkinter.TOP, pady=10)

        #NumericUpDown控件
        self.num_count = Control(self.frame,
                                 integer=True,
                                 max=-1,
                                 min=-1,
                                 value=-1,
                                 step=1,
                                 label='current Image:',
                                 command=self._showImage)
        self.num_count.label.config(font='Helvetica -14 bold')
        self.num_count.pack(side=Tkinter.TOP, pady=50)

        # create 'QUIT' button
        self.btn_quit = Button(self.frame,
                               text='QUIT',
                               command=self.mainWin.quit,
                               activeforeground='blue',
                               activebackground='white',
                               bg='red',
                               fg='white')
        self.btn_quit.pack(side=Tkinter.BOTTOM, pady=10)

    def _showImage(self, ev=None):
        if self.has_select_path:
            if int(self.num_count['value']) == -1:
                # create init image(a black background)
                self.img = Image.new("RGB", (self.img_Wid, self.img_Hei),
                                     (0, 0, 0))
                self.photo_img = ImageTk.PhotoImage(self.img)
                self.cv.create_image((0, 0),
                                     anchor=Tkinter.NW,
                                     image=self.photo_img)
                return
            else:
                img_cur_path = self.img_list[int(self.num_count['value'])]
                self.img = Image.open(img_cur_path).resize(
                    (self.img_Wid, self.img_Hei))
                self.photo_img = ImageTk.PhotoImage(self.img)
                self.cv.create_image((0, 0),
                                     anchor=Tkinter.NW,
                                     image=self.photo_img)

    def _labelButtonClick(self, label):
        cur_idx = int(self.num_count['value'])
        if cur_idx != -1:
            # save cur image's annotation result
            catgory_idx = self.categoryList.index(label)
            save_path = self.category_savepath_list[catgory_idx]
            cur_img_name = self.img_list[cur_idx].split('\\')[-1]
            save_path = os.path.join(save_path, cur_img_name)
            self.img.save(save_path)

            # check has next image or not
            if cur_idx + 1 < len(self.img_list):
                self.num_count['value'] = str(cur_idx + 1)
            else:
                tkMessageBox.showinfo(
                    title='thanks',
                    message='all the data annotation mission has finished~')

    def _selectPath(self):
        self.img_path = tkFileDialog.askdirectory()
        self.img_list = self._getImagList()
        if len(self.img_list) > 0:
            self.has_select_path = True
            self.num_count.config(max=len(self.img_list))
            self.num_count['value'] = str(0)
        else:
            self.has_select_path = False
            self.num_count['value'] = str(-1)
            self.num_count.config(max=-1)
            tkMessageBox.showwarning(
                'warning',
                'No available images detected! please re-select image path and start'
            )

    def _getImagList(self):
        img_list = []
        img_suffix = ['jpg', 'png', 'jpeg', 'bmp']
        for root, dirs, files in os.walk(self.img_path):
            for file_name in files:
                suffix = file_name.split('.')[-1]
                if suffix in img_suffix:
                    cur_img_path = os.path.join(root, file_name)
                    img_list.append(cur_img_path)
        return img_list
Exemplo n.º 3
0
class DataAnnotationWindow(object):
    def __init__(self):
        self.img_Wid = 500
        self.img_Hei = 500
        self.win_wid = self.img_Wid + 200
        self.win_Hei = self.img_Hei
        
        # init state control variable
        self.has_select_path = False  # sign has select image path(to do data annotation) or not
        self.img_path = ''
        self.img_list = []
        
        # create main window
        self.mainWin = Tkinter.Tk()  
        self.mainWin.geometry(str(self.win_wid) + 'x' + str(self.win_Hei))  # init the size of window
        self.mainWin.title("data annotation tool")
        self.mainWin.tk.eval('package require Tix') 
        # bind the key press event(space to pass, d to delete, q to quit) 
        self.mainWin.bind('<KeyPress>', self._keyPressEvent)
        
        # create init image(a black background)
        self.img = Image.new("RGB", (self.img_Wid, self.img_Hei), (0,0,0))
        self.photo_img = ImageTk.PhotoImage(self.img)
            
        # create Canvas control
        self.cv = Canvas(self.mainWin, bg = 'white', width = self.img_Wid, height = self.img_Hei) 
        self.cv.create_image((0,0), anchor=Tkinter.NW, image=self.photo_img) 
        self.cv.pack(side=Tkinter.LEFT, expand=True)

        
        # create total Frame to lay out all components
        self.frame = Frame(self.mainWin)
        self.frame.pack(fill=Tkinter.X, expand=Tkinter.YES, side=Tkinter.LEFT)
        

        # create text control
        root_save_path = './data_annotation_result'
        if os.path.exists(root_save_path) == False:
            os.mkdir(root_save_path)
        self.entry= Entry(self.frame, state = 'normal')
        self.entry.pack(side = Tkinter.TOP, fill = Tkinter.X)
        self.entry.insert(0, root_save_path)
        # mkdir of annotation result
        self.categoryList = ['category1', 'category2', 'category3']
        self.category_savepath_list = []
        for category in self.categoryList:
            cur_category_save_path = os.path.join(root_save_path, category)
            self.category_savepath_list.append(cur_category_save_path)
            if os.path.exists(cur_category_save_path) == False:
                os.mkdir(cur_category_save_path)
        
        # create 'START' button
        self.btn_start = Button(self.frame, text='START', command=self._selectPath, activeforeground='blue',
                        activebackground='white', bg='blue', fg='white')  
        self.btn_start.pack(side = Tkinter.TOP, pady=30)
        
        
        # create data annotation label button
        self.btn_category1 = Button(self.frame, text='Category 1',command=lambda:self._labelButtonClick('category1'), activeforeground='black',
                        activebackground='blue', bg='white', fg='black')  
        self.btn_category1.pack(side = Tkinter.TOP, pady=10)
        
        # create data annotation label button
        self.btn_category2 = Button(self.frame, text='Category 2',command=lambda:self._labelButtonClick('category2'), activeforeground='black',
                        activebackground='blue', bg='white', fg='black')  
        self.btn_category2.pack(side = Tkinter.TOP, pady=10)
        
        # create data annotation label button
        self.btn_category3 = Button(self.frame, text='Category 3',command=lambda:self._labelButtonClick('category3'), activeforeground='black',
                        activebackground='blue', bg='white', fg='black')  
        self.btn_category3.pack(side = Tkinter.TOP, pady=10)
        
        #NumericUpDown
        self.num_count = Control(self.frame,integer=True, max=-1, min=-1, value=-1, step=1,
                                 label='current Image:', command=self._showImage)
        self.num_count.label.config(font='Helvetica -14 bold')
        self.num_count.pack(side = Tkinter.TOP, pady=50)
        
        
        # create 'QUIT' button
        self.btn_quit = Button(self.frame, text='QUIT',command=self.mainWin.quit,activeforeground='blue',
                        activebackground='white', bg='red', fg='white')  
        self.btn_quit.pack(side = Tkinter.BOTTOM, pady=10)
    
    
    def _keyPressEvent(self, event):
        if event.keycode == 81:
            self._labelButtonClick('category1')
        elif event.keycode == 87:
            self._labelButtonClick('category2')
        elif event.keycode == 69:
            self._labelButtonClick('category3')


    def _showImage(self, ev=None):
        if self.has_select_path:
            if int(self.num_count['value']) == -1:
                # create init image(a black background)
                self.img = Image.new("RGB", (self.img_Wid, self.img_Hei), (0,0,0))
                self.photo_img = ImageTk.PhotoImage(self.img)
                self.cv.create_image((0,0), anchor=Tkinter.NW, image=self.photo_img) 
                return
            else:
                img_cur_path = self.img_list[int(self.num_count['value'])]
                self.img = self._loadImage(img_cur_path)
                self.photo_img = ImageTk.PhotoImage(self.img)
                self.cv.create_image((0,0), anchor=Tkinter.NW, image=self.photo_img) 
    
    
    def _labelButtonClick(self, label):
        cur_idx = int(self.num_count['value'])
        if cur_idx != -1:
            # get cur image's annotation label and file name
            catgory_idx = self.categoryList.index(label)
            cur_img_name = self.img_list[cur_idx].split('\\')[-1]
            
            # check if cur_img_name exist(undo last annotation operation)
            for cur_dir in self.category_savepath_list:
                for file in os.listdir(cur_dir):
                    if file == cur_img_name:
                        os.remove(os.path.join(cur_dir, file))
                        break
            
            # save cur image's annotation result
            save_path = self.category_savepath_list[catgory_idx]
            save_path = os.path.join(save_path, cur_img_name)
            src_path = os.path.join(self.img_path, cur_img_name)
            shutil.copy(src_path, save_path)
            #self.img.save(save_path)
            
            # check has next image or not
            if cur_idx + 1 < len(self.img_list):
                self.num_count['value'] = str(cur_idx + 1)
            else:
                tkMessageBox.showinfo(title='thanks', message='all the data annotation mission has finished~')
    
    
    def _selectPath(self):
        self.img_path = tkFileDialog.askdirectory()
        self.img_list = self._getImagList()
        if len(self.img_list) > 0:
            self.has_select_path = True
            self.num_count.config(max = len(self.img_list))
            self.num_count['value'] = str(0)
        else:
            self.has_select_path = False
            self.num_count['value'] = str(-1)
            self.num_count.config(max = -1)
            tkMessageBox.showwarning('warning','No available images detected! please re-select image path and start')


    def _getImagList(self):
        img_list = []
        for root, dirs, files in os.walk(self.img_path):
            for file_name in files:
                cur_img_path = os.path.join(root, file_name)
                img_list.append(cur_img_path)
        return img_list
    
    
    def _loadImage(self, img_path):
        img_back = Image.new("RGB", (self.img_Wid, self.img_Hei), (0,0,0))
        src_img = Image.open(img_path)
        src_width = src_img.width
        src_height = src_img.height
        if src_width > src_height:
            resize_width = self.img_Wid
            resize_height = int(src_height * self.img_Wid /src_width)
            resize_img = src_img.resize((resize_width, resize_height))
            start_idx = int((self.img_Hei - resize_height)/2)
            for y_offset in range(resize_height):
                for x_offset in range(resize_width):
                    x = x_offset
                    y = start_idx + y_offset
                    img_back.putpixel((x, y), resize_img.getpixel((x_offset, y_offset)))
        else:
            resize_height = self.img_Hei
            resize_width = int(src_width * self.img_Hei /src_height)
            resize_img = src_img.resize((resize_width, resize_height))
            start_idx = int((self.img_Wid - resize_width)/2)
            for y_offset in range(resize_height):
                for x_offset in range(resize_width):
                    x = start_idx + x_offset
                    y = y_offset
                    img_back.putpixel((x, y), resize_img.getpixel((x_offset, y_offset)))
        return img_back