""" myTk008.py 为指定文件夹中图片加注释文字,相关信息保存到json数据文件中。 2022年8月 在python3.7下调试通过。 """ import os from tkinter import * import tkinter as ttk from PIL import Image,ImageTk from mylx2 import myfiles,mysystem,myfile_list import tkinter.filedialog as tkf from time import sleep import json import codecs def call_back(event): print(event.keysym) class MyTk_001(ttk.Frame): def __init__(self, master: Tk,title,width, height,path='D:/2022/image', **kw): # 变量X和Y用来记录鼠标左键按下的位置 self.X = ttk.IntVar(value=0) self.Y = ttk.IntVar(value=0) self.selectPosition = None super().__init__(master, **kw) self.mroot = master self.mainframe = ttk.Frame(master,bg='black') self.mainframe.pack() #self.mainframe.grid(column=0, row=0, sticky=NSEW) self.width = width self.height = height self.canvas = Canvas(self.mainframe, width=self.width, height=self.height, background='gray55') self.canvas.pack() # set window's title. self.master.title(title + ' 鼠标:左键定位,中键换页,右键选标注') # set window's geometry size ss='%sx%s+%s+%s' % (width,160+height,50,50) self.master.geometry(ss) self.canvas.bind(sequence='<Button-1>', func=self._onLeftButtonDown) self.canvas.bind(sequence='<B1-Motion>', func=self._onLeftButtonMove) self.canvas.bind(sequence='<ButtonRelease-1>',func=self._onLeftButtonUp) self.canvas.bind(sequence='<Button-2>', func=self._PriNext) self.canvas.bind(sequence='<Button-3>', func=self._select) self.canvas.pack(fill=ttk.BOTH, expand=ttk.YES) h = self.height h1 = 100 # 标注 label_Biaozhu = ttk.Label(self.mroot,text='标注:') label_Biaozhu.place(x=50, y=h+50) #global input_valueText self.inputText = ttk.Entry(self.mroot, width=12) self.inputText.place(x=100, y=h+40, width=180, height=30, anchor=NW) self.inputText.bind('<Return>',func=self._mytext) App = ttk.Button(self.mroot, text='追加', command=self._save) App.place(x=350, y=h+40, w=100, h=40) Exit = ttk.Button(self.mroot, text='退出', command=(ttk._exit)) Exit.place(x=50, y=h+h1, w=100, h=40) Lood = ttk.Button(self.mroot, text='加载', command=self._get_files) Lood.place(x=200, y=h+h1, w=100, h=40) #save_jsonfile Save_json = ttk.Button(self.mroot, text='Save_json', command=self._save_jsonfile) Save_json.place(x=350, y=h + h1, w=100, h=40) # open_jsonfile Open_json = ttk.Button(self.mroot, text='Open_json', command=self._open_jsonfile) Open_json.place(x=500, y=h + h1, w=100, h=40) # 系统提示 # self.stateValue.set('系统提示:') self.stateValue = ttk.Label(self.mroot) self.stateValue.place(x=10, y=h+10) self._init_selectPosition() self.id = 0 self.bz_id = 0 self.mydict = {} self.Factor_Dict = {} self._get_files0(path) self._resizes() self._show0() self._show_state() def _show_state(self): k = str(self.id) if k in self.mydict.keys(): self.bz_list = self.mydict[k] else: self.bz_list = [] bzlen = len(self.bz_list) mstate = '目录名:%s 文件名:%s %s/%s 标注:%s/%s' % (self.path, self.file_list[self.id], self.id + 1, len(self.file_list), self.bz_id + 1, bzlen) self.stateValue['text'] = mstate # 鼠标左键按下的位置 def _onLeftButtonDown(self,event): self.X.set(event.x) self.Y.set(event.y) # 开始截图 self.sel = True # 鼠标左键移动,显示选取的区域 def _onLeftButtonMove(self,event): if not self.sel: return global lastDraw try: # 删除刚画完的图形,要不然鼠标移动的时候是黑乎乎的一片矩形 self.canvas.delete(lastDraw) except Exception as e: pass lastDraw = self.canvas.create_rectangle(self.X.get(), self.Y.get(), event.x, event.y, outline='red') # 获取鼠标左键抬起的位置,保存区域截图 def _onLeftButtonUp(self,event): self.sel = False try: self.canvas.delete(lastDraw) except Exception as e: pass sleep(0.1) # 考虑鼠标左键从右下方按下而从左上方抬起的截图 myleft, myright = sorted([self.X.get(), event.x]) mytop, mybottom = sorted([self.Y.get(), event.y]) print(myleft,mytop,myright,mybottom) # Position : x , y, w, h self.selectPosition = (myleft,mytop,myright,mybottom) self._show_BzOne() def _PriNext(self,event): self._Delete_Bz() self.inputText.delete(0, END) if event.x < self.width // 2: #private self.id -= 1 if self.id < 0: self.id = len(self.file_list) -1 else: #Next self.id += 1 if self.id == len(self.file_list): self.id = 0 self._show0() self._show_Bz0() self._show_state() def _select(self,event): self._show_BzId(self.bz_id) x = event.x y = event.y find = False i = 0 k = str(self.id) if k in self.mydict.keys(): self.bz_list = self.mydict[k] for bz in self.bz_list: box = bz[1] if (x >= box[0]) and (x <= box[2]) and (y >= box[1]) and (y <= box[3]): self.bz_id = i find = True break i += 1 if find == True: self._show_BzId(self.bz_id) self.bz_id = i bz = self.bz_list[self.bz_id] mtext = bz[0] self.selectPosition = bz[1] self.inputText.delete(0, END) self.inputText.insert(0, mtext) self._show_BzOne() else: self.bz_id = i self._show_BzOne() self.inputText.delete(0, END) self._show_state() def _mytext(self,event): k = str(self.id) if k in self.mydict.keys(): self.bz_list = self.mydict[k] else: self.bz_list = [] self._show_BzOne() if self.bz_id == len(self.bz_list): pass else: self._save() def _save(self): mtext = self.inputText.get() if len(mtext) == 0: print('标注不能为空!') return item = (mtext, self.selectPosition) k = str(self.id) if k not in self.mydict.keys(): self.bz_list = [] else: self.bz_list = self.mydict[k] if self.bz_id == len(self.bz_list): self.bz_list.append((mtext,self.selectPosition)) print(self.bz_list) self.mydict[k] = self.bz_list self._show_BzId(self.bz_id) self.bz_id += 1 self.inputText.delete(0, END) self._init_selectPosition() self._show_BzOne() else: self.bz_list[self.bz_id] = (mtext,self.selectPosition) self.mydict[k] = self.bz_list self._show_state() def _show_BzOne(self): bzname = 'bzname%d' % self.bz_id try: self.canvas.delete(bzname) except: pass mtext = self.inputText.get() print(self.selectPosition) x = (self.selectPosition[0] + self.selectPosition[2]) // 2 y = (self.selectPosition[1] + self.selectPosition[3]) // 2 h = (self.selectPosition[3] - self.selectPosition[1]) w = (self.selectPosition[2] - self.selectPosition[0]) #underline #self.canvas.create_text(x, y, text=mtext, tag=bzname, font=('SimHei', h, 'normal')) self.canvas.create_text(x, y, text=mtext, tag=bzname, font=('SimHei', h, 'underline')) def _show_BzId(self,bzid): bzname = 'bzname%d' % bzid try: self.canvas.delete(bzname) except: pass if bzid == len(self.bz_list): mtext = self.inputText.get() box = self.selectPosition else: bz = self.bz_list[bzid] mtext = bz[0] box = bz[1] x = (box[0] + box[2]) // 2 y = (box[1] + box[3]) // 2 h = (box[3] - box[1]) w = (box[2] - box[0]) self.canvas.create_text(x, y, text=mtext, tag=bzname, font=('SimHei', h, 'normal')) def _Delete_Bz(self): self.bz_id = 0 k = str(self.id) if k in self.mydict.keys(): self.bz_list = self.mydict[k] else: self.bz_list = [] for bz in self.bz_list: bzname = 'bzname%s' % self.bz_id self.canvas.delete(bzname) self.bz_id += 1 bzname = 'bzname%s' % self.bz_id self.canvas.delete(bzname) def _init_selectPosition(self): x = self.width // 2 y = self.height // 2 h = 10 self.selectPosition = (x - 5 * h, y - h, x + 5 * h, y + h) def _show_Bz0(self): self.bz_id = 0 k = str(self.id) if k in self.mydict.keys(): self.bz_list = self.mydict[k] for bz in self.bz_list: bzname = 'bzname%s' % self.bz_id mtext = bz[0] box = bz[1] x = (box[0] + box[2]) // 2 y = (box[1] + box[3]) // 2 h = (box[3] - box[1]) self.canvas.create_text(x, y, text=mtext, tag=bzname, font=('SimHei', h, 'normal')) self.bz_id += 1 self._init_selectPosition() self._show_BzOne() def _show0(self): global image global im global out filen = self._getfilen(self.id) if filen == None: return image = Image.open(filen) if self.id in self.Factor_Dict.keys(): out = self._resize1(image) else : out = self._resize(self.width, self.height, image) im = ImageTk.PhotoImage(out) w = (self.width - im.width()) // 2 h = (self.height - im.height()) // 2 self.canvas.delete('image') self.canvas.create_image(self.width // 2, self.height // 2, image=im, tag='image') def _Load_image(self): self._Delete_Bz() self.inputText.delete(0, END) self.id += 1 if self.id == len(self.file_list): self.id = 0 self._show0() self._show_Bz0() def _private(self): if self.bz_id>0 : self._show_BzId(self.bz_id) self.bz_id -= 1 bz = self.bz_list[self.bz_id] mtext = bz[0] self.selectPosition = bz[1] self.inputText.delete(0,END) self.inputText.insert(0,mtext) self._show_BzOne() else: k = str(self.id) if k in self.mydict.keys(): self.bz_list = self.mydict[k] self.bz_id = len(self.bz_list) else: self.bz_id = 0 self.bz_list = [] self._init_selectPosition() self.inputText.delete(0, END) def _resize(self,w_box, h_box, pil_image): # get the size of the image # 获取图像的原始大小 w, h = pil_image.size print(w,h,w_box, h_box) ''' resize a pil_image object so it will fit into a box of size w_box times h_box, but retain aspect ratio 对一个pil_image对象进行缩放,让它在一个矩形框内,还能保持比例 ''' f1 = 1.0 * w_box / w # 1.0 forces float division in Python2 f2 = 1.0 * h_box / h factor = min([f1, f2]) # print(f1, f2, factor) # test # use best down-sizing filter width = int(w * factor) height = int(h * factor) #print('_resize') temp = (factor,(w_box-width) // 2,(h_box-height) // 2) self.Factor_Dict[self.id] = temp return pil_image.resize((width, height), Image.DEFAULT_STRATEGY) #Image.ANTIALIAS def _resize1(self,pil_image): temp = self.Factor_Dict[self.id] width = self.width - temp[1] * 2 height = self.height - temp[2] * 2 #print('_resize1') return pil_image.resize((width, height), Image.DEFAULT_STRATEGY) def _resizes(self): self.Factor_Dict.clear() for i in range(0,len(self.file_list)-1): #print(i) filen = self._getfilen(i) #print(i,filen) pil_image = Image.open(filen) w, h = pil_image.size f1 = 1.0 * self.width / w f2 = 1.0 * self.height / h factor = min([f1, f2]) print("factor:",type(factor)) width = int(w * factor) height = int(h * factor) temp = (factor, (self.width - width) // 2, (self.height - height) // 2) self.Factor_Dict[i] = temp def _getfilen(self,i): #print(id) if (i >= 0) and (i < len(self.file_list) - 1): filen = os.path.join(self.path, self.file_list[i]) return filen # 打开图片文件并显示 def _get_files(self): path = tkf.askdirectory() if path: self._get_files0(path) def _get_files0(self,path): mclass = myfile_list(path, "jpg|png") self.path = path self.file_list = mclass.file_list self.Factor_Dict.clear() self.mydict.clear() self.id = 0 self.id = 0 self.bz_id = 0 if len(mclass.file_list) > 0: self._resizes() self._Load_image() self._show_state() def _save_jsonfile(self): json_content = {} json_content['path'] = self.path json_content['files'] = self.file_list json_content['Factor_Dict'] = self.Factor_Dict json_content['mydict'] = self.mydict # 存入json文件 final_json = json.dumps(json_content, ensure_ascii=False) jsonfileName = "d:\\2022\\data\\data_json.json" with codecs.open(jsonfileName, 'a', 'utf-8') as file: file.write(final_json) file.close() print('save_jsonfile:%s' % jsonfileName) def _open_jsonfile(self): jsonfileName = "d:\\2022\\data\\data_json.json" with codecs.open(jsonfileName, 'r','utf-8') as file: data = json.load(file) file.close() print('open_jsonfile:%s' % jsonfileName) print(data['path']) print(data['files']) print(data['Factor_Dict']) print(data['mydict']) self._get_files1(data) def _get_files1(self,data): self.path = data['path'] self.file_list = data['files'] self.Factor_Dict.clear() self.Factor_Dict = data['Factor_Dict'] self.mydict.clear() self.mydict = data['mydict'] print('mydict-len=',len(self.mydict)) self.id = 0 self.id = 0 self.bz_id = 0 if len(self.file_list) > 0: self._Load_image() self._show_state() def _call_back(event): print(event.keysym) root = Tk() # 不允许改变窗口大小 root.resizable(False, False) root.focusmodel() mytk = MyTk_001(root,"窗口程序__图片标注",800,600) root.mainloop()
学习python日记
于 2022-08-06 07:38:34 首次发布