diff --git a/main.py b/main.py index ed1d687..59e72d8 100755 --- a/main.py +++ b/main.py @@ -53,6 +53,9 @@ def __init__(self, parent, UpdateUI, get_type): self.box_id = -1 self.xy_magnifier = [] self.show_scale_proportion = 0 + self.key_status = {"shift": 0, "ctrl": 0, "alt": 0} + self.indextablegui = None + self.aboutgui = None self.icon = wx.Icon(get_resource_path( 'mulimgviewer.ico'), wx.BITMAP_TYPE_ICO) self.SetIcon(self.icon) @@ -326,13 +329,15 @@ def delete_box(self, event): self.SetStatusText_(["delete all box", "-1", "-1", "-1"]) def up_img(self, event): + speed = self.get_speed(name="pixel") + if self.select_img_box.Value: if self.box_id != -1: box_point = self.xy_magnifier[self.box_id][0:4] show_scale = self.xy_magnifier[self.box_id][4:6] x, y = self.get_center_box(box_point) x = x+0 - y = y-1 + y = y-speed self.xy_magnifier[self.box_id][0:4] = self.move_box_point( x, y, show_scale) self.refresh(event) @@ -343,19 +348,21 @@ def up_img(self, event): self.position[1] = int( self.scrolledWindow_img.GetScrollPos(wx.VERTICAL)/self.Uint[1]) if self.position[1] > 0: - self.position[1] -= 1 + self.position[1] -= speed self.scrolledWindow_img.Scroll( self.position[0]*self.Uint[0], self.position[1]*self.Uint[1]) self.SetStatusText_(["Up", "-1", "-1", "-1"]) def down_img(self, event): + speed = self.get_speed(name="pixel") + if self.select_img_box.Value: if self.box_id != -1: box_point = self.xy_magnifier[self.box_id][0:4] show_scale = self.xy_magnifier[self.box_id][4:6] x, y = self.get_center_box(box_point) x = x+0 - y = y+1 + y = y+speed self.xy_magnifier[self.box_id][0:4] = self.move_box_point( x, y, show_scale) self.refresh(event) @@ -366,7 +373,7 @@ def down_img(self, event): self.position[1] = int( self.scrolledWindow_img.GetScrollPos(wx.VERTICAL)/self.Uint[1]) if (self.position[1]-1)*self.Uint[1] < size[1]: - self.position[1] += 1 + self.position[1] += speed self.scrolledWindow_img.Scroll( self.position[0]*self.Uint[0], self.position[1]*self.Uint[1]) else: @@ -375,12 +382,14 @@ def down_img(self, event): self.SetStatusText_(["Down", "-1", "-1", "-1"]) def right_img(self, event): + speed = self.get_speed(name="pixel") + if self.select_img_box.Value: if self.box_id != -1: box_point = self.xy_magnifier[self.box_id][0:4] show_scale = self.xy_magnifier[self.box_id][4:6] x, y = self.get_center_box(box_point) - x = x+1 + x = x+speed y = y+0 self.xy_magnifier[self.box_id][0:4] = self.move_box_point( x, y, show_scale) @@ -392,7 +401,7 @@ def right_img(self, event): self.position[1] = int( self.scrolledWindow_img.GetScrollPos(wx.VERTICAL)/self.Uint[1]) if (self.position[0]-1)*self.Uint[0] < size[0]: - self.position[0] += 1 + self.position[0] += speed self.scrolledWindow_img.Scroll( self.position[0]*self.Uint[0], self.position[1]*self.Uint[1]) else: @@ -401,12 +410,14 @@ def right_img(self, event): self.SetStatusText_(["Right", "-1", "-1", "-1"]) def left_img(self, event): + speed = self.get_speed(name="pixel") + if self.select_img_box.Value: if self.box_id != -1: box_point = self.xy_magnifier[self.box_id][0:4] show_scale = self.xy_magnifier[self.box_id][4:6] x, y = self.get_center_box(box_point) - x = x-1 + x = x-speed y = y+0 self.xy_magnifier[self.box_id][0:4] = self.move_box_point( x, y, show_scale) @@ -418,7 +429,7 @@ def left_img(self, event): self.position[1] = int( self.scrolledWindow_img.GetScrollPos(wx.VERTICAL)/self.Uint[1]) if self.position[0] > 0: - self.position[0] -= 1 + self.position[0] -= speed self.scrolledWindow_img.Scroll( self.position[0]*self.Uint[0], self.position[1]*self.Uint[1]) self.SetStatusText_(["Left", "-1", "-1", "-1"]) @@ -531,6 +542,12 @@ def img_left_move(self, event): RGBA = self.ImgManager.img.getpixel((int(x), int(y))) self.m_statusBar1.SetStatusText(str(x)+","+str(y)+"/"+str(RGBA), 0) + # focus img + if self.indextablegui or self.aboutgui: + pass + else: + self.img_panel.Children[0].SetFocus() + def img_left_release(self, event): if self.magnifier.Value != False: self.start_flag = 0 @@ -616,14 +633,18 @@ def get_center_box(self, box, more=False): def img_wheel(self, event): # https://wxpython.org/Phoenix/docs/html/wx.MouseEvent.html + + # zoom i_cur = 0 status_toggle = [self.magnifier, self.rotation, self.flip] - if status_toggle[i_cur].Value: + if status_toggle[i_cur].Value and (self.key_status["ctrl"] == 1): if event.GetWheelDelta() >= 120: + speed = self.get_speed(name="scale") + if event.GetWheelRotation() > 0: - self.show_scale_proportion = self.show_scale_proportion+0.1 + self.show_scale_proportion = self.show_scale_proportion+speed else: - self.show_scale_proportion = self.show_scale_proportion-0.1 + self.show_scale_proportion = self.show_scale_proportion-speed if self.show_scale_proportion > 0: show_scale = [1*(1+self.show_scale_proportion), @@ -638,12 +659,54 @@ def img_wheel(self, event): round(show_scale[0], 2))+","+str(round(show_scale[1], 2)) self.refresh(event) - else: pass else: pass + # move + if self.key_status["ctrl"] == 0 and event.GetWheelDelta() >= 120: + if event.WheelAxis == 0: + if event.GetWheelRotation() > 0: + self.up_img(event) + else: + self.down_img(event) + else: + if event.GetWheelRotation() > 0: + self.right_img(event) + else: + self.left_img(event) + + def key_down_detect(self, event): + if event.GetKeyCode() == wx.WXK_CONTROL: + self.key_status["ctrl"] = 1 + elif event.GetKeyCode() == wx.WXK_SHIFT: + if self.key_status["shift"] == 0: + self.key_status["shift"] = 1 + elif self.key_status["shift"] == 1: + self.key_status["shift"] = 0 + + def key_up_detect(self, event): + if event.GetKeyCode() == wx.WXK_CONTROL: + self.key_status["ctrl"] = 0 + elif event.GetKeyCode() == wx.WXK_SHIFT: + pass + + def get_speed(self, name="pixel"): + if name == "pixel": + if self.key_status["shift"] == 1: + speed = 5 + else: + speed = 1 + elif name == "scale": + if self.key_status["shift"] == 1: + speed = 0.5 + else: + speed = 0.1 + else: + speed = None + return speed + def magnifier_fc(self, event): self.start_flag = 0 self.show_scale.Value = "1,1" @@ -804,6 +867,7 @@ def set_img_layout(self): self.show_crop.Value, # 18 self.parallel_to_sequential.Value, # 19 self.one_img.Value, # 20 + self.box_position, # 21 self.checkBox_orientation.Value] def show_img(self): @@ -819,8 +883,9 @@ def show_img(self): self.ImgManager.input_path, self.ImgManager.type, parallel_to_sequential) self.show_img_init() self.ImgManager.set_action_count(action_count) - self.index_table.show_id_table( - self.ImgManager.name_list, self.ImgManager.layout_params) + if self.index_table_gui: + self.index_table_gui.show_id_table( + self.ImgManager.name_list, self.ImgManager.layout_params) except: pass @@ -852,6 +917,7 @@ def show_img(self): wx.Size(self.img_size[0]+100, self.img_size[1]+100)) self.img_last = wx.StaticBitmap(parent=self.img_panel, bitmap=bmp) + self.img_panel.Children[0].SetFocus() self.img_panel.Children[0].Bind( wx.EVT_LEFT_DOWN, self.img_left_click) self.img_panel.Children[0].Bind( @@ -864,6 +930,10 @@ def show_img(self): wx.EVT_RIGHT_DOWN, self.img_right_click) self.img_panel.Children[0].Bind( wx.EVT_MOUSEWHEEL, self.img_wheel) + self.img_panel.Children[0].Bind( + wx.EVT_KEY_DOWN, self.key_down_detect) + self.img_panel.Children[0].Bind( + wx.EVT_KEY_UP, self.key_up_detect) # status if self.ImgManager.type == 2 or ((self.ImgManager.type == 0 or self.ImgManager.type == 1) and self.parallel_sequential.Value): @@ -948,8 +1018,8 @@ def auto_layout(self, frame_resize=False): self.Refresh() def about_gui(self, event): - about = About(None) - about.Show(True) + self.aboutgui = About(None) + self.aboutgui.Show(True) def index_table_gui(self, event): if self.ImgManager.img_num != 0: @@ -961,10 +1031,10 @@ def index_table_gui(self, event): self.SetStatusText_( ["-1", "-1", "index_table.txt saving...", "-1"]) if self.ImgManager.type == 3: - self.index_table = IndexTable( + self.indextablegui = IndexTable( None, self.ImgManager.path_list, self.ImgManager.layout_params, self.ImgManager.dataset_mode, self.out_path_str, self.ImgManager.type, self.parallel_sequential.Value) else: - self.index_table = IndexTable( + self.indextablegui = IndexTable( None, self.ImgManager.name_list, self.ImgManager.layout_params, self.ImgManager.dataset_mode, self.out_path_str, self.ImgManager.type, self.parallel_sequential.Value) if self.ImgManager.dataset_mode: self.SetStatusText_( diff --git a/main_gui.py b/main_gui.py index 149009e..a42d524 100644 --- a/main_gui.py +++ b/main_gui.py @@ -121,7 +121,7 @@ def __init__( self, parent ): fgSizer4.Add( self.m_staticText1, 0, wx.ALL, 5 ) - self.img_panel = wx.Panel( self.scrolledWindow_img, wx.ID_ANY, wx.DefaultPosition, wx.Size( -1,-1 ), wx.TAB_TRAVERSAL ) + self.img_panel = wx.Panel( self.scrolledWindow_img, wx.ID_ANY, wx.DefaultPosition, wx.Size( -1,-1 ), wx.BORDER_NONE ) fgSizer4.Add( self.img_panel, 1, wx.EXPAND |wx.ALL, 5 ) @@ -349,6 +349,11 @@ def __init__( self, parent ): self.line_width = wx.TextCtrl( self.scrolledWindow_set, wx.ID_ANY, u"2", wx.DefaultPosition, wx.Size( 40,-1 ), 0 ) wSizer7.Add( self.line_width, 0, wx.ALL, 5 ) + box_positionChoices = [ u"middle bottom", u"left bottom", u"right bottom", u"left top", u"right top" ] + self.box_position = wx.Choice( self.scrolledWindow_set, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, box_positionChoices, 0 ) + self.box_position.SetSelection( 0 ) + wSizer7.Add( self.box_position, 0, wx.ALL, 5 ) + fgSizer3.Add( wSizer7, 1, wx.EXPAND, 5 ) diff --git a/utils_img.py b/utils_img.py index 35b0608..ce052d2 100644 --- a/utils_img.py +++ b/utils_img.py @@ -127,7 +127,7 @@ def draw_rectangle(self, img, xy_grids, bounding_boxs, color_list, line_width=2, img = Image.fromarray(img_array.astype('uint8')).convert('RGBA') return img - def cal_magnifier_size(self, magnifier_scale, crop_size, img_mode, gap, img_size, num_box, show_original, vertical=False): + def cal_magnifier_size(self, magnifier_scale, crop_size, img_mode, gap, img_size, num_box, show_original, box_position=0, vertical=False): delta_x = 0 delta_y = 0 width, height = crop_size @@ -383,7 +383,8 @@ def layout_2d(self, layout_list, gap_color, img_list, img_preprocessing, img_pre # img preprocessing if img_list[iy_0, ix_0, iy_1, ix_1] != []: im = img_list[iy_0, ix_0, iy_1, ix_1][0] - im = img_preprocessing(im,id=iy_1*Col['level_1']+ix_1) + im = img_preprocessing( + im, id=iy_1*Col['level_1']+ix_1) xy_grids_output.append( [x_offset_0+x_offset_1, y_offset_0+y_offset_1]) @@ -706,6 +707,7 @@ def get_dir_num(self): num = (self.path_list).shape return num[0] + class ImgManager(ImgDatabase): """Multi-image manager. Multi-image parallel magnification, stitching, saving, rotation""" @@ -808,7 +810,8 @@ def stitch_img_init(self, img_mode, draw_points): self.show_original = self.layout_params[16] self.one_img = self.layout_params[20] num_per_img = self.layout_params[1] if self.one_img else 1 - self.to_size = [int(self.img_resolution[0]/num_per_img),self.img_resolution[1]] + self.to_size = [ + int(self.img_resolution[0]/num_per_img), self.img_resolution[1]] if self.show_original: layout_level_2.append(1) img_preprocessing_sub.append(self.ImgF.identity_transformation) @@ -831,7 +834,7 @@ def stitch_img_init(self, img_mode, draw_points): crop_width = self.crop_points[0][2]-self.crop_points[0][0] crop_height = self.crop_points[0][3]-self.crop_points[0][1] _, _, magnifier_img_all_size = self.ImgF.cal_magnifier_size( - self.layout_params[8], [crop_width, crop_height], 0, self.layout_params[3][4], self.to_size, len(self.crop_points), self.show_original, vertical=self.vertical) + self.layout_params[8], [crop_width, crop_height], 0, self.layout_params[3][4], self.to_size, len(self.crop_points), self.show_original, box_position=self.layout_params[21], vertical=self.vertical) img_preprocessing_sub.append(self.magnifier_preprocessing) width_2.append(magnifier_img_all_size[0]) height_2.append(magnifier_img_all_size[1]) @@ -1056,10 +1059,10 @@ def img_preprocessing(self, img, id=None): img = self.ImgF.add_alpha(img, self.img_alpha) # n img -> one img, split width - if id!=None and self.one_img: + if id != None and self.one_img: sub_img_width = int(width/self.layout_params[1]) img = np.array(img) - img = img[:,id*sub_img_width:(id+1)*sub_img_width,:] + img = img[:, id*sub_img_width:(id+1)*sub_img_width, :] img = Image.fromarray(np.uint8(img)) return img @@ -1128,7 +1131,7 @@ def magnifier_preprocessing(self, img, img_mode=0, id=0): # get the size of magnifier img to_resize, delta, magnifier_img_all_size = self.ImgF.cal_magnifier_size( - magnifier_scale, list(img_list[0].size), img_mode, gap, self.to_size, len(self.crop_points), self.show_original, vertical=self.vertical) + magnifier_scale, list(img_list[0].size), img_mode, gap, self.to_size, len(self.crop_points), self.show_original, box_position=self.layout_params[21], vertical=self.vertical) # resize images line_width = self.layout_params[10] @@ -1314,7 +1317,7 @@ def save_select(self, dir_name): self.check.append(0) if self.layout_params[11]: - if self.action_count==0: + if self.action_count == 0: action_count = 0 else: action_count = self.action_count-1 @@ -1405,7 +1408,7 @@ def save_magnifier(self, dir_name): img = self.img_list[i_] img_list = self.magnifier_preprocessing( - self.img_preprocessing(img,id=self.get_img_id(i_)), img_mode=1) + self.img_preprocessing(img, id=self.get_img_id(i_)), img_mode=1) i = 0 for img in img_list: f_path_output = Path( @@ -1418,7 +1421,7 @@ def save_magnifier(self, dir_name): i = 0 for img in self.img_list: img_list = self.magnifier_preprocessing( - self.img_preprocessing(img,id=self.get_img_id(i)), img_mode=1) + self.img_preprocessing(img, id=self.get_img_id(i)), img_mode=1) if not (Path(self.out_path_str)/dir_name/(Path(self.flist[i]).parent).stem).is_dir(): os.makedirs(Path(self.out_path_str) / dir_name / (Path(self.flist[i]).parent).stem) @@ -1444,7 +1447,7 @@ def save_origin_img_magnifier(self): sub_dir_name) i = 0 for img in self.img_list: - img = self.img_preprocessing(img,id=self.get_img_id(i)) + img = self.img_preprocessing(img, id=self.get_img_id(i)) if self.show_box: img = self.ImgF.draw_rectangle(img, self.xy_grid, self.crop_points, self.layout_params[9], line_width=self.layout_params[10], single_box=True) @@ -1456,15 +1459,15 @@ def save_origin_img_magnifier(self): img.save(f_path_output) i += 1 - def get_img_id(self,i): - if i!=None and self.one_img: + def get_img_id(self, i): + if i != None and self.one_img: row = self.layout_params[0] numperimg = self.layout_params[1] col = self.layout_params[2] kernel = list(range(numperimg)) L = [] for k in range(row*col): - L=L+kernel + L = L+kernel return L[i] else: return None diff --git a/wxFromBuilder/main_gui.fbp b/wxFromBuilder/main_gui.fbp index 9081d01..600de45 100644 --- a/wxFromBuilder/main_gui.fbp +++ b/wxFromBuilder/main_gui.fbp @@ -1207,11 +1207,11 @@ none 1 0 - + 5 wxALL|wxEXPAND 1 - + 1 1 1 @@ -1264,7 +1264,7 @@ wxHSCROLL|wxVSCROLL - + 1 wxBOTH @@ -1391,7 +1391,7 @@ - wxTAB_TRAVERSAL + wxBORDER_NONE @@ -3966,6 +3966,70 @@ + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + "middle bottom" "left bottom" "right bottom" "left top" "right top" + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + box_position + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + +