MakeLabel图片标注工具

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

运行效果

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值