深度学习python图像标记工具labelTool

深度学习训练需要标记图像位置和类别,之前用的时候是叫做BBox-Label-Tool-master,遇到大图像就显示不完整了,没有自适应缩放, 这是改进后的Python脚本。

目录结构:图片目录名images, 标签目录名labels,图像目录下各类别目录名要以001,002,003,...的格式命名。



这是运行labelTool ( python main.py)时的截屏,图像框记录的是比例值,

快捷键a,d前后切换图像,esc取消当前框


python脚本main.py:

[python]  view plain  copy
  1. # -*- coding:utf-8 -*-  
  2. #-------------------------------------------------------------------------------  
  3. # Name:        Object bounding box label tool  
  4. # Purpose:     Label object bboxes for ImageNet Detection data  
  5. # Author:      Qiushi  
  6. # Created:     06/06/2014  
  7.   
  8. #  
  9. #-------------------------------------------------------------------------------  
  10. from __future__ import division  
  11. from Tkinter import *  
  12. import tkMessageBox  
  13. from PIL import Image, ImageTk  
  14. import os  
  15. import glob  
  16. import random  
  17.   
  18. w0 = 1#图片原始宽度  
  19. h0 = 1#图片原始高度  
  20.   
  21. # colors for the bboxes  
  22. COLORS = ['red''blue''yellow''pink''cyan''green''black']  
  23. # image sizes for the examples  
  24. SIZE = 256256  
  25.   
  26. #指定缩放后的图像大小  
  27. DEST_SIZE = 500500   
  28.   
  29. class LabelTool():  
  30.     def __init__(self, master):  
  31.         # set up the main frame  
  32.         self.parent = master  
  33.         self.parent.title("LabelTool")  
  34.         self.frame = Frame(self.parent)  
  35.         self.frame.pack(fill=BOTH, expand=1)  
  36.         self.parent.resizable(width = TRUE, height = TRUE)  
  37.   
  38.         # initialize global state  
  39.         self.imageDir = ''  
  40.         self.imageList= []  
  41.         self.egDir = ''  
  42.         self.egList = []  
  43.         self.outDir = ''  
  44.         self.cur = 0  
  45.         self.total = 0  
  46.         self.category = 0  
  47.         self.imagename = ''  
  48.         self.labelfilename = ''  
  49.         self.tkimg = None  
  50.   
  51.         # initialize mouse state  
  52.         self.STATE = {}  
  53.         self.STATE['click'] = 0  
  54.         self.STATE['x'], self.STATE['y'] = 00  
  55.   
  56.         # reference to bbox  
  57.         self.bboxIdList = []  
  58.         self.bboxId = None  
  59.         self.bboxList = []  
  60.         self.hl = None  
  61.         self.vl = None  
  62.   
  63.         # ----------------- GUI stuff ---------------------  
  64.         # dir entry & load  
  65.         self.label = Label(self.frame, text = "Image Dir:")  
  66.         self.label.grid(row = 0, column = 0, sticky = E)  
  67.         self.entry = Entry(self.frame)  
  68.         self.entry.grid(row = 0, column = 1, sticky = W+E)  
  69.         self.ldBtn = Button(self.frame, text = "Load", command = self.loadDir)  
  70.         self.ldBtn.grid(row = 0, column = 2, sticky = W+E)  
  71.    
  72.         # main panel for labeling  
  73.         self.mainPanel = Canvas(self.frame, cursor='tcross')  
  74.         self.mainPanel.bind("<Button-1>"self.mouseClick)  
  75.         self.mainPanel.bind("<Motion>"self.mouseMove)  
  76.         self.parent.bind("<Escape>"self.cancelBBox)  # press <Espace> to cancel current bbox  
  77.         self.parent.bind("s"self.cancelBBox)  
  78.         self.parent.bind("a"self.prevImage) # press 'a' to go backforward  
  79.         self.parent.bind("d"self.nextImage) # press 'd' to go forward  
  80.         self.mainPanel.grid(row = 1, column = 1, rowspan = 4, sticky = W+N)  
  81.   
  82.         # showing bbox info & delete bbox  
  83.         self.lb1 = Label(self.frame, text = 'Bounding boxes:')  
  84.         self.lb1.grid(row = 1, column = 2,  sticky = W+N)  
  85.        
  86.         self.listbox = Listbox(self.frame, width = 28, height = 12)  
  87.         self.listbox.grid(row = 2, column = 2, sticky = N)  
  88.   
  89.         self.btnDel = Button(self.frame, text = 'Delete', command = self.delBBox)  
  90.         self.btnDel.grid(row = 3, column = 2, sticky = W+E+N)  
  91.         self.btnClear = Button(self.frame, text = 'ClearAll', command = self.clearBBox)  
  92.         self.btnClear.grid(row = 4, column = 2, sticky = W+E+N)  
  93.        
  94.         # control panel for image navigation  
  95.         self.ctrPanel = Frame(self.frame)  
  96.         self.ctrPanel.grid(row = 5, column = 1, columnspan = 2, sticky = W+E)  
  97.         self.prevBtn = Button(self.ctrPanel, text='<< Prev', width = 10, command = self.prevImage)  
  98.         self.prevBtn.pack(side = LEFT, padx = 5, pady = 3)  
  99.         self.nextBtn = Button(self.ctrPanel, text='Next >>', width = 10, command = self.nextImage)  
  100.         self.nextBtn.pack(side = LEFT, padx = 5, pady = 3)  
  101.         self.progLabel = Label(self.ctrPanel, text = "Progress:     /    ")  
  102.         self.progLabel.pack(side = LEFT, padx = 5)  
  103.         self.tmpLabel = Label(self.ctrPanel, text = "Go to Image No.")  
  104.         self.tmpLabel.pack(side = LEFT, padx = 5)  
  105.         self.idxEntry = Entry(self.ctrPanel, width = 5)  
  106.         self.idxEntry.pack(side = LEFT)  
  107.         self.goBtn = Button(self.ctrPanel, text = 'Go', command = self.gotoImage)  
  108.         self.goBtn.pack(side = LEFT)  
  109.   
  110.         # example pannel for illustration  
  111.         self.egPanel = Frame(self.frame, border = 10)  
  112.         self.egPanel.grid(row = 1, column = 0, rowspan = 5, sticky = N)  
  113.         self.tmpLabel2 = Label(self.egPanel, text = "Examples:")  
  114.         self.tmpLabel2.pack(side = TOP, pady = 5)  
  115.        
  116.         self.egLabels = []  
  117.         for i in range(3):  
  118.             self.egLabels.append(Label(self.egPanel))  
  119.             self.egLabels[-1].pack(side = TOP)  
  120.   
  121.         # display mouse position  
  122.         self.disp = Label(self.ctrPanel, text='')  
  123.         self.disp.pack(side = RIGHT)  
  124.   
  125.         self.frame.columnconfigure(1, weight = 1)  
  126.         self.frame.rowconfigure(4, weight = 1)  
  127.   
  128.         # for debugging  
  129. ##        self.setImage()  
  130. ##        self.loadDir()  
  131.   
  132.     
  133.     def loadDir(self, dbg = False):  
  134.         if not dbg:  
  135.             s = self.entry.get()  
  136.             self.parent.focus()  
  137.             self.category = int(s)  
  138.         else:  
  139.             s = r'D:\workspace\python\labelGUI'  
  140. ##        if not os.path.isdir(s):  
  141. ##            tkMessageBox.showerror("Error!", message = "The specified dir doesn't exist!")  
  142. ##            return  
  143.         # get image list  
  144.   
  145.     print 'self.category =%d'  %(self.category )  
  146.   
  147.         self.imageDir = os.path.join(r'./images''%03d' %(self.category))  
  148.     print(self.imageDir)   
  149.         self.imageList = glob.glob(os.path.join(self.imageDir, '*.jpg'))  
  150.         if len(self.imageList) == 0:  
  151.             print 'No .jpg images found in the specified dir!'  
  152.             return  
  153.     else:  
  154.         print 'num=%d'  %(len(self.imageList))  
  155.   
  156.         # default to the 1st image in the collection  
  157.         self.cur = 1  
  158.         self.total = len(self.imageList)  
  159.   
  160.          # set up output dir  
  161.         self.outDir = os.path.join(r'./labels''%03d' %(self.category))  
  162.         if not os.path.exists(self.outDir):  
  163.             os.mkdir(self.outDir)  
  164.   
  165.         # load example bboxes  
  166.         self.egDir = os.path.join(r'./Examples''%03d' %(self.category))  
  167.         #if not os.path.exists(self.egDir):  
  168.          #   return  
  169.   
  170.         filelist = glob.glob(os.path.join(self.egDir, '*.jpg'))  
  171.         self.tmp = []  
  172.         self.egList = []  
  173.         random.shuffle(filelist)  
  174.         for (i, f) in enumerate(filelist):  
  175.             if i == 3:  
  176.                 break  
  177.             im = Image.open(f)  
  178.             r = min(SIZE[0] / im.size[0], SIZE[1] / im.size[1])  
  179.             new_size = int(r * im.size[0]), int(r * im.size[1])  
  180.             self.tmp.append(im.resize(new_size, Image.ANTIALIAS))  
  181.             self.egList.append(ImageTk.PhotoImage(self.tmp[-1]))  
  182.             self.egLabels[i].config(image = self.egList[-1], width = SIZE[0], height = SIZE[1])  
  183.   
  184.         self.loadImage()  
  185.         print '%d images loaded from %s' %(self.total, s)  
  186.   
  187.   
  188.     def loadImage(self):  
  189.         # load image  
  190.         imagepath = self.imageList[self.cur - 1]  
  191.     pil_image = Image.open(imagepath)  
  192.   
  193.     # get the size of the image  
  194.     #获取图像的原始大小  
  195.     global w0,h0  
  196.     w0, h0 = pil_image.size  
  197.       
  198.     #缩放到指定大小  
  199.         pil_image = pil_image.resize((DEST_SIZE[0], DEST_SIZE[1]), Image.ANTIALIAS)  
  200.   
  201.     #pil_image = imgresize(w, h, w_box, h_box, pil_image)  
  202.         self.img =  pil_image  
  203.   
  204.         self.tkimg = ImageTk.PhotoImage(pil_image)  
  205.   
  206.         self.mainPanel.config(width = max(self.tkimg.width(), 400), height = max(self.tkimg.height(), 400))   
  207.         self.mainPanel.create_image(00, image = self.tkimg, anchor=NW)  
  208.         self.progLabel.config(text = "%04d/%04d" %(self.cur, self.total))  
  209.   
  210.         # load labels  
  211.         self.clearBBox()  
  212.         self.imagename = os.path.split(imagepath)[-1].split('.')[0]  
  213.         labelname = self.imagename + '.txt'  
  214.         self.labelfilename = os.path.join(self.outDir, labelname)  
  215.         bbox_cnt = 0  
  216.         if os.path.exists(self.labelfilename):  
  217.             with open(self.labelfilename) as f:  
  218.                 for (i, line) in enumerate(f):  
  219.                     if i == 0:  
  220.                         bbox_cnt = int(line.strip())  
  221.                         continue  
  222.             print line   
  223.                     tmp = [(t.strip()) for t in line.split()]  
  224.       
  225.                     print "********************"  
  226.             print DEST_SIZE  
  227.             #tmp = (0.1, 0.3, 0.5, 0.5)  
  228.             print "tmp[0,1,2,3]===%.2f, %.2f, %.2f, %.2f" %(float(tmp[0]), float(tmp[1]), float(tmp[2]), float(tmp[3]))  
  229.             #print "%.2f,%.2f,%.2f,%.2f" %(tmp[0] tmp[1] tmp[2] tmp[3] )  
  230.                
  231.                     print "********************"  
  232.   
  233.             #tx = (10, 20, 30, 40)    
  234.                     #self.bboxList.append(tuple(tx))  
  235.                     self.bboxList.append(tuple(tmp))  
  236.             tmp[0] = float(tmp[0])       
  237.             tmp[1] = float(tmp[1])  
  238.             tmp[2] = float(tmp[2])       
  239.             tmp[3] = float(tmp[3])  
  240.   
  241.             tx0 = int(tmp[0]*DEST_SIZE[0])  
  242.             ty0 = int(tmp[1]*DEST_SIZE[1])  
  243.   
  244.             tx1 = int(tmp[2]*DEST_SIZE[0])  
  245.             ty1 = int(tmp[3]*DEST_SIZE[1])  
  246.                 print "tx0, ty0, tx1, ty1"  
  247.             print tx0, ty0, tx1, ty1  
  248.   
  249.               
  250.                     tmpId = self.mainPanel.create_rectangle(tx0, ty0, tx1, ty1,\  
  251.                                                             width = 2, \  
  252.                                                             outline = COLORS[(len(self.bboxList)-1) % len(COLORS)])  
  253.   
  254.                    
  255.                     self.bboxIdList.append(tmpId)  
  256.             self.listbox.insert(END, '(%.2f,%.2f)-(%.2f,%.2f)' %(tmp[0], tmp[1], tmp[2], tmp[3]) )  
  257.   
  258.                    # self.listbox.insert(END, '(%d, %d) -> (%d, %d)' %(tmp[0], tmp[1], tmp[2], tmp[3]))  
  259.                     self.listbox.itemconfig(len(self.bboxIdList) - 1, fg = COLORS[(len(self.bboxIdList) - 1) % len(COLORS)])  
  260.   
  261.     def saveImage(self):  
  262.     #print "-----1--self.bboxList---------"  
  263.     print self.bboxList   
  264.     #print "-----2--self.bboxList---------"  
  265.   
  266.         with open(self.labelfilename, 'w') as f:  
  267.             f.write('%d\n' %len(self.bboxList))  
  268.             for bbox in self.bboxList:   
  269.                 f.write(' '.join(map(str, bbox)) + '\n')  
  270.         print 'Image No. %d saved' %(self.cur)  
  271.   
  272.   
  273.     def mouseClick(self, event):  
  274.         if self.STATE['click'] == 0:  
  275.             self.STATE['x'], self.STATE['y'] = event.x, event.y  
  276.         else:  
  277.             x1, x2 = min(self.STATE['x'], event.x), max(self.STATE['x'], event.x)  
  278.             y1, y2 = min(self.STATE['y'], event.y), max(self.STATE['y'], event.y)  
  279.   
  280.         x1, x2 = x1 / DEST_SIZE[0], x2 / DEST_SIZE[0];   
  281.             y1, y2 = y1 / DEST_SIZE[1], y2 / DEST_SIZE[1];   
  282.   
  283.             self.bboxList.append((x1, y1, x2, y2))  
  284.             self.bboxIdList.append(self.bboxId)  
  285.             self.bboxId = None  
  286.             self.listbox.insert(END, '(%.2f, %.2f)-(%.2f, %.2f)' %(x1, y1, x2, y2))  
  287.             self.listbox.itemconfig(len(self.bboxIdList) - 1, fg = COLORS[(len(self.bboxIdList) - 1) % len(COLORS)])  
  288.         self.STATE['click'] = 1 - self.STATE['click']  
  289.   
  290.     def mouseMove(self, event):  
  291.         self.disp.config(text = 'x: %.2f, y: %.2f' %(event.x/DEST_SIZE[0], event.y/DEST_SIZE[1]))  
  292.         if self.tkimg:  
  293.             if self.hl:  
  294.                 self.mainPanel.delete(self.hl)  
  295.             self.hl = self.mainPanel.create_line(0, event.y, self.tkimg.width(), event.y, width = 2)  
  296.             if self.vl:  
  297.                 self.mainPanel.delete(self.vl)  
  298.             self.vl = self.mainPanel.create_line(event.x, 0, event.x, self.tkimg.height(), width = 2)  
  299.         if 1 == self.STATE['click']:  
  300.             if self.bboxId:  
  301.                 self.mainPanel.delete(self.bboxId)  
  302.             self.bboxId = self.mainPanel.create_rectangle(self.STATE['x'], self.STATE['y'], \  
  303.                                                             event.x, event.y, \  
  304.                                                             width = 2, \  
  305.                                                             outline = COLORS[len(self.bboxList) % len(COLORS)])  
  306.   
  307.     def cancelBBox(self, event):  
  308.         if 1 == self.STATE['click']:  
  309.             if self.bboxId:  
  310.                 self.mainPanel.delete(self.bboxId)  
  311.                 self.bboxId = None  
  312.                 self.STATE['click'] = 0  
  313.   
  314.     def delBBox(self):  
  315.         sel = self.listbox.curselection()  
  316.         if len(sel) != 1 :  
  317.             return  
  318.         idx = int(sel[0])  
  319.         self.mainPanel.delete(self.bboxIdList[idx])  
  320.         self.bboxIdList.pop(idx)  
  321.         self.bboxList.pop(idx)  
  322.         self.listbox.delete(idx)  
  323.   
  324.     def clearBBox(self):  
  325.         for idx in range(len(self.bboxIdList)):  
  326.             self.mainPanel.delete(self.bboxIdList[idx])  
  327.         self.listbox.delete(0, len(self.bboxList))  
  328.         self.bboxIdList = []  
  329.         self.bboxList = []  
  330.   
  331.     def prevImage(self, event = None):  
  332.         self.saveImage()  
  333.         if self.cur > 1:  
  334.             self.cur -= 1  
  335.             self.loadImage()  
  336.   
  337.     def nextImage(self, event = None):  
  338.         self.saveImage()  
  339.         if self.cur < self.total:  
  340.             self.cur += 1  
  341.             self.loadImage()  
  342.   
  343.     def gotoImage(self):  
  344.         idx = int(self.idxEntry.get())  
  345.         if 1 <= idx and idx <= self.total:  
  346.             self.saveImage()  
  347.             self.cur = idx  
  348.             self.loadImage()  
  349.   
  350. ##    def setImage(self, imagepath = r'test2.png'):  
  351. ##        self.img = Image.open(imagepath)  
  352. ##        self.tkimg = ImageTk.PhotoImage(self.img)  
  353. ##        self.mainPanel.config(width = self.tkimg.width())  
  354. ##        self.mainPanel.config(height = self.tkimg.height())  
  355. ##        self.mainPanel.create_image(0, 0, image = self.tkimg, anchor=NW)  
  356.   
  357.     def imgresize(w, h, w_box, h_box, pil_image):  
  358.         ''''' 
  359.         resize a pil_image object so it will fit into 
  360.         a box of size w_box times h_box, but retain aspect ratio 
  361.         '''  
  362.         f1 = 1.0*w_box/w # 1.0 forces float division in Python2  
  363.         f2 = 1.0*h_box/h  
  364.         factor = min([f1, f2])  
  365.         #print(f1, f2, factor) # test  
  366.         # use best down-sizing filter  
  367.         width = int(w*factor)  
  368.         height = int(h*factor)  
  369.         return pil_image.resize((width, height), Image.ANTIALIAS)  
  370.   
  371.   
  372. if __name__ == '__main__':  
  373.     root = Tk()  
  374.     tool = LabelTool(root)  
  375.     root.mainloop()  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值