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
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
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