MakeLabel图片标注工具
发布时间:2021-07-28 12:30:00    阅读次数:671
MakeLabel是一款用Python编写的,用于给图片区域内容作标注的工具软件。它的目的是给YOLOV5样本图片作标注,并生成可供YOLOV5训练使用的标签文件。

label.txt

标签类别文件,声明训练所要标注的类别。一行一个类别,第1个是类别名称,第2个是序号。中间用英文逗号分隔。

		人,0
		猫,1
		狗,2
		


makelabel.py

主程序,程序很简单,所以没有做标注。主要是用Tkinter和PIL来实现。要和label.txt放在同一个目录内。

		import tkinter as tk
		from tkinter import ttk
		import sys,os
		#import win32api,win32con
		from tkinter import filedialog
		from PIL import Image,ImageTk
		import tkinter.font
		#=======================================================

		def get_img(nid):
			global Values
			c = 0
			
			for key,value in Values["Img_File"].items():
				if(nid == c):
					return key
				c+=1
				
			return ""
		#=======================================================
		def show_img():
			global Values,bottom_Canvas,colors
			
			if(Values["Img_Dir"]=="" or Values["Label_Dir"]==""):
				Values["nID"] = 0
				return

			nid = Values["nID"]
			if(nid >= len(Values["Img_File"])):
				nid = len(Values["Img_File"])-1
			
			if(nid<0):
				nid = 0
			
			Values["nID"] = nid
			
			fn = get_img(nid)
				
			if(fn==""):
				return
				
			fname = Values["Img_Dir"]+"\\"+fn 
			
			label_F = Values["Label_Dir"] + "\\" + Values["Img_File"][fn]
			
			if(os.path.exists(label_F)==False):
				file = open(label_F,'w')
				file.close()
				Values["Cur_Rt"] = []
			else:
				Values["Cur_Rt"] = []
				file = open(label_F,'r')        
				cline = file.readline()
				while(cline):
					cline = cline.split()
					T = [0,0,0,0,0]
					T[0] = int(cline[0])
					T[1] = float(cline[1])
					T[2] = float(cline[2])
					T[3] = float(cline[3])
					T[4] = float(cline[4])
					
					T[1] = T[1] - T[3]/2
					T[2] = T[2] - T[4]/2
					
					Values["Cur_Rt"].append(T)
					
					cline = file.readline()        
				
				file.close()
				
				
			img = Image.open(fname)
			w = img.size[0]
			h = img.size[1]
				
			v1 = 1
			if(w<h and h>600):
				v1 = h / 600
				h /= v1
				w /= v1
			elif(w>h and w>1100):
				v1 = w / 1100
				w /= v1
				h /= v1
					
			w = int(w)
			h = int(h)            
				
			if(Values["Img_Data"]!=0):
				bottom_Canvas.delete(Values["Img_Data"])
				
			img = img.resize((w,h))
			Values["Img_Data"] = ImageTk.PhotoImage(img)
				
			sx = (1200 - w ) //2
			sy = (650 - h) //2
			
			Values["Cur_Size"] = [sx,sy,w,h]
			bottom_Canvas.delete(tk.ALL)
			bottom_Canvas.create_image(sx,sy,anchor='nw', image=Values["Img_Data"])
		   
				
			for rt in Values["Cur_Rt"]:
				
				color = colors[rt[0]]
				
					
				x1 = int(w * rt[1])+sx
				y1 = int(h * rt[2])+sy
				x2 = int(w * rt[3] + x1)
				y2 = int(h * rt[4] + y1)     
				
				bottom_Canvas.create_rectangle(x1,y1,x2,y2,width=2,outline=color)
				

		#=======================================================
		def find_jpg():
			global Values
			Values["Img_File"] = {}
			Values["nID"] = 0
			
			for root,dirs,files in os.walk(Values["Img_Dir"]):
				for file in files:                        
					if(file.endswith(".jpg") or file.endswith(".JPG") or file.endswith(".jpeg") or file.endswith(".JPEG")):
						f1 = os.path.splitext(file)[0]
						Values["Img_File"][file] = f1+".txt"
						
			show_img()
					

		#=======================================================
		def prev_bn():
			global Values    
			Values["nID"] -=1
			show_img()
			
		#=======================================================
		def next_bn():
			global Values
			
			Values["nID"] +=1
			show_img()    
		#=======================================================
		def clear_bn():
			Values["Cur_Rt"] = []
			
			nid = Values["nID"]
			if(nid >= len(Values["Img_File"])):
				nid = len(Values["Img_File"])-1
			
			if(nid<0):
				return
			
			fn = get_img(nid)
			
			label_F = Values["Label_Dir"] + "\\" + Values["Img_File"][fn]
			os.remove(label_F)
			
			show_img()
		#=======================================================
		def OnMouseMove(event):
			global Values,bottom_Canvas,Ctrl_List,colors
				
			if(Values["Sel_Mode"]<0):
				return
			
			if(Values["Tmp_Rt"][0]==0):
				Values["Tmp_Rt"][0] = 1
				Values["Tmp_Rt"][1] = event.x
				Values["Tmp_Rt"][2] = event.y
				
			else:
				Values["Tmp_Rt"][3] = event.x
				Values["Tmp_Rt"][4] = event.y
				
				if(Values["Tmp_Rt"][5]!=0):
					bottom_Canvas.delete(Values["Tmp_Rt"][5])
				
				
				ncolor = colors[Values["Sel_Mode"]]
				  
				
				Values["Tmp_Rt"][5] = bottom_Canvas.create_rectangle(Values["Tmp_Rt"][1],Values["Tmp_Rt"][2],Values["Tmp_Rt"][3],Values["Tmp_Rt"][4],width=2,outline=ncolor)
				
				
			
		#=======================================================
		def OnRelease(event):
			global Values,Ctrl_List,Label_List
			
			if(Values["Tmp_Rt"][0] ==0):
				return
				
			fn = get_img(Values["nID"])
				
			if(fn==""):
				return            
						
			label_F = Values["Label_Dir"] + "\\" + Values["Img_File"][fn]        
					
			item = Ctrl_List.get()
			pID = -1

			pID = Label_List[item]
					
			if(pID==-1):
				return
				
			if(Values["Tmp_Rt"][1] > Values["Tmp_Rt"][3]):
				t = Values["Tmp_Rt"][1]
				Values["Tmp_Rt"][1] = Values["Tmp_Rt"][3]
				Values["Tmp_Rt"][3] = t
					
			if(Values["Tmp_Rt"][2] > Values["Tmp_Rt"][4]):
				t = Values["Tmp_Rt"][1]
				Values["Tmp_Rt"][2] = Values["Tmp_Rt"][4]
				Values["Tmp_Rt"][4] = t
				
			ff = open(label_F,"a")
				
			sx =round((Values["Tmp_Rt"][1]-Values["Cur_Size"][0]) / Values["Cur_Size"][2],4)
			sy = round((Values["Tmp_Rt"][2]-Values["Cur_Size"][1]) /  Values["Cur_Size"][3],4)
			w = round((Values["Tmp_Rt"][3]-Values["Tmp_Rt"][1] )  /   Values["Cur_Size"][2],4)
			h = round((Values["Tmp_Rt"][4]-Values["Tmp_Rt"][2] ) /   Values["Cur_Size"][3],4)
			
			
			sx += w/2
			sy += h/2
			
			if(sx<0):
				sx=0
			if(sx>1):
				sx=1
				
			if(sy<0):
				sy=0
			if(sy>1):
				sy=1
				
			if(w>1):
				w=1
			if(h>1):
				h=1
				
			ff.write(str(pID)+" "+str(sx)+" "+str(sy)+" "+ str(w)+" "+ str(h)+"\n")
				
			ff.close()
			
			
			Values["Tmp_Rt"][0] = 0
			Values["Tmp_Rt"][5] = 0

		#=======================================================
		def ch_Img_Dir(event):
			global Values,Img_Dir_Label    
			Values["Img_Dir"] = filedialog.askdirectory()
			Values["Img_Dir"] = Values["Img_Dir"].replace("/","\\")
			Img_Dir_Label["text"] = Values["Img_Dir"]
			find_jpg()
		#======================================================
		def ch_Label_Dir(event):
			global Values,Label_Dir_Label
			Values["Label_Dir"] = filedialog.askdirectory()
			Values["Label_Dir"] = Values["Label_Dir"].replace("/","\\")
			Label_Dir_Label["text"] = Values["Label_Dir"]    
			show_img()
			
		#======================================================
		def OnSelect(event):
			global Ctrl_List,Values,Label_List
			item = Ctrl_List.get()
					
			if(item=="清除标签"):
				Values["Sel_Mode"] = -1
			else:
				Values["Sel_Mode"] = Label_List[item]
		#======================================================
		def Open_Label():
			global Label_List
			Label_List = {}
			f = open("label.txt",'r',encoding='utf-8')
			while True:
				line = f.readline()
				if(len(line)==0):
					break
				
				tmp = line.split(",")
				tmp[1] = tmp[1].replace('\n','')
				Label_List[tmp[0]] = int(tmp[1])
			
			f.close()
			
		#======================================================
		def Init_GUI(root):
			global Img_Dir_Label,Label_Dir_Label,bottom_Canvas,Ctrl_List,Label_List
			
			font1 = tk.font.Font(family='黑体',size=12);
			top_Frame = tk.PanedWindow(height=50,bg='#3f3f3f')
			top_Frame.pack(fill=tk.BOTH,expand=1)
			
			Img_Dir_Label = tk.Label(top_Frame,text="图片目录",bg='#7f7f7f',font=font1,fg='white',width=30,height=2)
			Label_Dir_Label = tk.Label(top_Frame,text="标签目录",bg='#7f7f7f',font=font1,fg='white',width=30,height=2)
			Img_Dir_Label.bind("<Button-1>",ch_Img_Dir)
			Label_Dir_Label.bind("<Button-1>",ch_Label_Dir)
			
			Prev_Button = tk.Button(top_Frame,text="前一张",bg='#7f7f7f',font=font1,fg='white',width=10,height=2,command=prev_bn)
			Next_Button = tk.Button(top_Frame,text="后一张",bg='#7f7f7f',font=font1,fg='white',width=10,height=2,command=next_bn)
			Clear_Button = tk.Button(top_Frame,text="清除标记",bg='#7f7f7f',font=font1,fg='white',width=10,height=2,command=clear_bn)
			
			Open_Label()
			Ctrl_List = ttk.Combobox(top_Frame,font=font1,width=5,state="readonly")
			
			TM = []
			for key,value in Label_List.items():        
				TM.append(key)
			
			Ctrl_List['value'] = TM
				
			Ctrl_List.bind("<ComboboxSelected>",OnSelect)
			Label_TIP_Label = tk.Label(top_Frame,text="MakeLabel V2021",bg='#7f7f7f',font=font1,fg='white',width=20,height=2)
			
			top_Frame.add(Img_Dir_Label)
			top_Frame.add(Label_Dir_Label)
			
			top_Frame.add(Prev_Button)
			top_Frame.add(Next_Button)
			top_Frame.add(Ctrl_List)
			top_Frame.add(Clear_Button)
			top_Frame.add(Label_TIP_Label)
			
			
			bottom_Canvas = tk.Canvas(root,height=650,bg='#3f3f3f')
			bottom_Canvas.pack(fill=tk.BOTH,expand=1)
			bottom_Canvas.bind("<B1-Motion>",OnMouseMove)
			bottom_Canvas.bind("<ButtonRelease-1>",OnRelease)
			
		#================================================
		if __name__ == '__main__':

			colors =["#ffffff","#ff0000","#00ff00","#0000ff","#7f0000","#007f00","#00007f"]
			Values = {"nID":0,"Img_Dir":"","Label_Dir":"","Img_File":{},"Img_Data":0,"Tmp_Rt":[0,-1,-1,-1,-1,0],"Cur_Rt":[],"Sel_Mode":0,"Cur_Size":[]}
			Img_Dir_Label = 0
			Label_Dir_Label = 0
			bottom_Canvas = 0
			Ctrl_List = 0
			Label_List = 0;
			#---------------------
			root = tk.Tk()
			root.title("Make Label")
			root.resizable(0,0)
			root.geometry("1200x700+0+0")
			#s_Width = win32api.GetSystemMetrics(win32con.SM_CXSCREEN)
			#s_Height = win32api.GetSystemMetrics(win32con.SM_CYSCREEN)
			
			#sx = (s_Width-1200)//2
			#sy = (s_Height-700)//2
			sx=0
			sy=0
			
			root.geometry("%sx%s+%s+%s" % (1200,700,sx,sy))
			
			Init_GUI(root)
			
			root.mainloop()

	


运行效果



桂ICP备11003301号-1 公安备案号:45040302000027 Copyright @ 2021- 2022 By Sun zi chao

阅读统计: 1.93W 文章数量: 76 运行天数: 416天 返回cmnsoft