yolo-annotation-tool-new-'s People
Forkers
chaiso-krit tiravata iayanmisra chamecall tunahansalih neuralji shalevy1 braedyn-au anirudhtunga rsamf legroslezard af-lazuardi karan1914 keokichang pinsondg zhenhaitapei arunishkumar totally-random-productions william-vu tejas4888 amirunpri2018 sahadevpoudel jingweimo rsvarma95 dev-299792 jorge-mendes vishalchak saved-dse-project-tu-delft-2020 openamiguel thibaudmagne jrojoci3 jai1904 pawanw17 aegle-drone fabricejumel hxdaze vpattanaik pavankumarms ajg707 pratimavermaa fsantibanezleal galang30 tabishkhan96 umamanasir ayeshalashkarwala marshelld mm802-mmcommunications filipeas shen0512 shaileshshr holidayjo hadar-hezi vrushali-anil-chaudhari aakashvardhanyolo-annotation-tool-new-'s Issues
Annotation for yolov3
Thanks for this repo. The other tool is more difficult to use,but this is very easy and useful but I wonder something . Can I use these annotations for yolov3 ? or only yolov2
Picture not totally shown during GUI
Hi there,
It is not really an issue that needs huge means to correct, but the gui for manual bounding boxes drawing does not support any size of pictures. What I mean is some part of the picture is not shown when loaded. Perhaps it happened only to me, but just as a notice
Updated main.py for Anaconda and Python3.7+
Deps from pip work w current version of conda just fine.
Install updated/newest version of tk:
pip install tk
- Run in cmd line:
python3 main-py3.py
Please merge or add as main-py3.py for updated option to run:
#-------------------------------------------------------------------------------
# Name: Object bounding box label tool
# Purpose: Label object bboxes for ImageNet Detection data
# Author: Qiushi
# Created: 06/06/2014
# Updated for Python3.7 by Joe Hoeller
#
#-------------------------------------------------------------------------------
from __future__ import division
from tkinter import *
from tkinter import messagebox as tkMessageBox
from PIL import Image, ImageTk
import os
import sys
import glob
import random
MAIN_COLORS = ['darkolivegreen', 'darkseagreen', 'darkorange', 'darkslategrey', 'darkturquoise', 'darkgreen', 'darkviolet', 'darkgray', 'darkmagenta', 'darkblue', 'darkkhaki','darkcyan', 'darkred', 'darksalmon', 'darkslategray', 'darkgoldenrod', 'darkgrey', 'darkslateblue', 'darkorchid','skyblue','yellow','orange','red','pink','violet','green','brown','gold','Olive','Maroon', 'blue', 'cyan', 'black','olivedrab', 'lightcyan', 'silver']
# image sizes for the examples
SIZE = 256, 256
classes = []
try:
with open('classes.txt','r') as cls:
classes = cls.readlines()
classes = [cls.strip() for cls in classes]
except IOError as io:
print("[ERROR] Please create classes.txt and put your all classes")
sys.exit(1)
COLORS = random.sample(set(MAIN_COLORS), len(classes))
class LabelTool():
def __init__(self, master):
# set up the main frame
self.curimg_h = 0
self.curimg_w = 0
self.cur_cls_id = -1
self.parent = master
self.parent.title("Yolo Annotation Tool")
self.frame = Frame(self.parent)
self.frame.pack(fill=BOTH, expand=1)
self.parent.resizable(width = FALSE, height = FALSE)
# initialize global state
self.imageDir = ''
self.imageList= []
self.egDir = ''
self.egList = []
self.outDir = ''
self.cur = 0
self.total = 0
self.category = 0
self.imagename = ''
self.labelfilename = ''
self.tkimg = None
# initialize mouse state
self.STATE = {}
self.STATE['click'] = 0
self.STATE['x'], self.STATE['y'] = 0, 0
# reference to bbox
self.bboxIdList = []
self.bboxId = None
self.bboxList = []
self.bboxListCls = []
self.hl = None
self.vl = None
# ----------------- GUI stuff ---------------------
# dir entry & load
self.label = Label(self.frame, text = "Image Dir:")
self.label.grid(row = 0, column = 0, sticky = E)
self.entry = Entry(self.frame)
self.entry.focus_set()
self.entry.bind('<Return>', self.loadEntry)
self.entry.grid(row = 0, column = 1, sticky = W+E)
self.ldBtn = Button(self.frame, text = "Load", command = self.loadDir)
self.ldBtn.grid(row = 0, column = 2, sticky = W+E)
# main panel for labeling
self.mainPanel = Canvas(self.frame, cursor='tcross')
self.mainPanel.bind("<Button-1>", self.mouseClick)
self.mainPanel.bind("<Motion>", self.mouseMove)
self.parent.bind("<Escape>", self.cancelBBox) # press <Espace> to cancel current bbox
self.parent.bind("s", self.cancelBBox)
self.parent.bind("<Left>", self.prevImage) # press 'a' to go backforward
self.parent.bind("<Right>", self.nextImage) # press 'd' to go forward
self.mainPanel.grid(row = 1, column = 1, rowspan = 4, sticky = W+N)
# showing bbox info & delete bbox
self.tkvar = StringVar(self.parent)
self.cur_cls_id = 0
self.tkvar.set(classes[0]) # set the default option
self.popupMenu = OptionMenu(self.frame, self.tkvar, *classes,command = self.change_dropdown)
self.popupMenu.grid(row = 1, column =2, sticky = E+S)
self.chooselbl = Label(self.frame, text = 'Choose Class:')
self.chooselbl.grid(row = 1, column = 2, sticky = W+S)
self.lb1 = Label(self.frame, text = 'Bounding boxes:')
self.lb1.grid(row = 2, column = 2, sticky = W+N)
self.listbox = Listbox(self.frame, width = 30, height = 12)
self.listbox.grid(row = 3, column = 2, sticky = N)
self.btnDel = Button(self.frame, text = 'Delete', command = self.delBBox)
self.btnDel.grid(row = 4, column = 2, sticky = W+E+N)
self.btnClear = Button(self.frame, text = 'ClearAll', command = self.clearBBox)
self.btnClear.grid(row = 5, column = 2, sticky = W+E+N)
# control panel for image navigation
self.ctrPanel = Frame(self.frame)
self.ctrPanel.grid(row = 6, column = 1, columnspan = 2, sticky = W+E)
self.prevBtn = Button(self.ctrPanel, text='<< Prev', width = 10, command = self.prevImage)
self.prevBtn.pack(side = LEFT, padx = 5, pady = 3)
self.nextBtn = Button(self.ctrPanel, text='Next >>', width = 10, command = self.nextImage)
self.nextBtn.pack(side = LEFT, padx = 5, pady = 3)
self.progLabel = Label(self.ctrPanel, text = "Progress: / ")
self.progLabel.pack(side = LEFT, padx = 5)
self.tmpLabel = Label(self.ctrPanel, text = "Go to Image No.")
self.tmpLabel.pack(side = LEFT, padx = 5)
self.idxEntry = Entry(self.ctrPanel, width = 5)
self.idxEntry.pack(side = LEFT)
self.goBtn = Button(self.ctrPanel, text = 'Go', command = self.gotoImage)
self.goBtn.pack(side = LEFT)
# example pannel for illustration
self.egPanel = Frame(self.frame, border = 10)
self.egPanel.grid(row = 1, column = 0, rowspan = 5, sticky = N)
self.tmpLabel2 = Label(self.egPanel, text = "Examples:")
self.tmpLabel2.pack(side = TOP, pady = 5)
self.egLabels = []
for i in range(3):
self.egLabels.append(Label(self.egPanel))
self.egLabels[-1].pack(side = TOP)
# display mouse position
self.disp = Label(self.ctrPanel, text='')
self.disp.pack(side = RIGHT)
self.frame.columnconfigure(1, weight = 1)
self.frame.rowconfigure(4, weight = 1)
def loadEntry(self,event):
self.loadDir()
def loadDir(self, dbg = False):
if not dbg:
try:
s = self.entry.get()
self.parent.focus()
self.category = s
except ValueError as ve:
tkMessageBox.showerror("Error!", message = "The folder should be numbers")
return
if not os.path.isdir('./Images/%s' % self.category):
tkMessageBox.showerror("Error!", message = "The specified dir doesn't exist!")
return
# get image list
self.imageDir = os.path.join(r'./Images', '%s' %(self.category))
self.imageList = glob.glob(os.path.join(self.imageDir, '*.jpg'))
if len(self.imageList) == 0:
print('No .jpg images found in the specified dir!')
tkMessageBox.showerror("Error!", message = "No .jpg images found in the specified dir!")
return
# default to the 1st image in the collection
self.cur = 1
self.total = len(self.imageList)
# set up output dir
if not os.path.exists('./Labels'):
os.mkdir('./Labels')
self.outDir = os.path.join(r'./Labels', '%s' %(self.category))
if not os.path.exists(self.outDir):
os.mkdir(self.outDir)
self.loadImage()
print('%d images loaded from %s' %(self.total, s))
def loadImage(self):
# load image
imagepath = self.imageList[self.cur - 1]
self.img = Image.open(imagepath)
self.curimg_w, self.curimg_h = self.img.size
self.tkimg = ImageTk.PhotoImage(self.img)
self.mainPanel.config(width = max(self.tkimg.width(), 400), height = max(self.tkimg.height(), 400))
self.mainPanel.create_image(0, 0, image = self.tkimg, anchor=NW)
self.progLabel.config(text = "%04d/%04d" %(self.cur, self.total))
# load labels
self.clearBBox()
# self.imagename = os.path.split(imagepath)[-1].split('.')[0]
self.imagename = os.path.splitext(os.path.basename(imagepath))[0]
labelname = self.imagename + '.txt'
self.labelfilename = os.path.join(self.outDir, labelname)
bbox_cnt = 0
if os.path.exists(self.labelfilename):
with open(self.labelfilename) as f:
for (i, line) in enumerate(f):
yolo_data = line.strip().split()
tmp = self.deconvert(yolo_data[1:])
self.bboxList.append(tuple(tmp))
self.bboxListCls.append(yolo_data[0])
tmpId = self.mainPanel.create_rectangle(tmp[0], tmp[1], \
tmp[2], tmp[3], \
width = 2, \
outline = COLORS[int(yolo_data[0])])
self.bboxIdList.append(tmpId)
self.listbox.insert(END, '(%d, %d) -> (%d, %d) -> (%s)' %(tmp[0], tmp[1], tmp[2], tmp[3], classes[int(yolo_data[0])]))
self.listbox.itemconfig(len(self.bboxIdList) - 1, fg = COLORS[int(yolo_data[0])])
def saveImage(self):
with open(self.labelfilename, 'w') as f:
for bbox,bboxcls in zip(self.bboxList,self.bboxListCls):
xmin,ymin,xmax,ymax = bbox
b = (float(xmin), float(xmax), float(ymin), float(ymax))
bb = self.convert((self.curimg_w,self.curimg_h), b)
f.write(str(bboxcls) + " " + " ".join([str(a) for a in bb]) + '\n')
print('Image No. %d saved' %(self.cur))
def mouseClick(self, event):
if self.STATE['click'] == 0:
self.STATE['x'], self.STATE['y'] = event.x, event.y
else:
x1, x2 = min(self.STATE['x'], event.x), max(self.STATE['x'], event.x)
y1, y2 = min(self.STATE['y'], event.y), max(self.STATE['y'], event.y)
self.bboxList.append((x1, y1, x2, y2))
self.bboxListCls.append(self.cur_cls_id)
self.bboxIdList.append(self.bboxId)
self.bboxId = None
self.listbox.insert(END, '(%d, %d) -> (%d, %d) -> (%s)' %(x1, y1, x2, y2, classes[self.cur_cls_id]))
self.listbox.itemconfig(len(self.bboxIdList) - 1, fg = COLORS[self.cur_cls_id])
self.STATE['click'] = 1 - self.STATE['click']
def mouseMove(self, event):
self.disp.config(text = 'x: %d, y: %d' %(event.x, event.y))
if self.tkimg:
if self.hl:
self.mainPanel.delete(self.hl)
self.hl = self.mainPanel.create_line(0, event.y, self.tkimg.width(), event.y, width = 2)
if self.vl:
self.mainPanel.delete(self.vl)
self.vl = self.mainPanel.create_line(event.x, 0, event.x, self.tkimg.height(), width = 2)
if 1 == self.STATE['click']:
if self.bboxId:
self.mainPanel.delete(self.bboxId)
self.bboxId = self.mainPanel.create_rectangle(self.STATE['x'], self.STATE['y'], \
event.x, event.y, \
width = 2, \
outline = COLORS[self.cur_cls_id])
def cancelBBox(self, event):
if 1 == self.STATE['click']:
if self.bboxId:
self.mainPanel.delete(self.bboxId)
self.bboxId = None
self.STATE['click'] = 0
def delBBox(self):
sel = self.listbox.curselection()
if len(sel) != 1 :
return
idx = int(sel[0])
self.mainPanel.delete(self.bboxIdList[idx])
self.bboxIdList.pop(idx)
self.bboxList.pop(idx)
print(self.bboxListCls,idx)
self.bboxListCls.pop(idx)
self.listbox.delete(idx)
def clearBBox(self):
for idx in range(len(self.bboxIdList)):
self.mainPanel.delete(self.bboxIdList[idx])
self.listbox.delete(0, len(self.bboxList))
self.bboxIdList = []
self.bboxList = []
self.bboxListCls = []
def prevImage(self, event = None):
self.saveImage()
if self.cur > 1:
self.cur -= 1
self.loadImage()
else:
tkMessageBox.showerror("Information!", message = "This is first image")
def nextImage(self, event = None):
self.saveImage()
if self.cur < self.total:
self.cur += 1
self.loadImage()
else:
tkMessageBox.showerror("Information!", message = "All images annotated")
def gotoImage(self):
idx = int(self.idxEntry.get())
if 1 <= idx and idx <= self.total:
self.saveImage()
self.cur = idx
self.loadImage()
def change_dropdown(self,*args):
cur_cls = self.tkvar.get()
self.cur_cls_id = classes.index(cur_cls)
def convert(self,size, box):
dw = 1./size[0]
dh = 1./size[1]
x = (box[0] + box[1])/2.0
y = (box[2] + box[3])/2.0
w = box[1] - box[0]
h = box[3] - box[2]
x = x*dw
w = w*dw
y = y*dh
h = h*dh
return (x,y,w,h)
def deconvert(self,annbox):
ox = float(annbox[0])
oy = float(annbox[1])
ow = float(annbox[2])
oh = float(annbox[3])
x = ox*self.curimg_w
y = oy*self.curimg_h
w = ow*self.curimg_w
h = oh*self.curimg_h
xmax = (((2*x)+w)/2)
xmin = xmax-w
ymax = (((2*y)+h)/2)
ymin = ymax-h
return [int(xmin),int(ymin),int(xmax),int(ymax)]
if __name__ == '__main__':
root = Tk()
tool = LabelTool(root)
root.resizable(width = True, height = True)
root.mainloop()
Annotation-Tool
Hi, we are work also on an Image Annotation Tool our version is currently only for Windows systems, maybe you can help us build to an linux client. We would be happy if you take a look at our project and maybe we can work together.
Our Project
https://github.com/AlturosDestinations/Alturos.ImageAnnotation
'No .jpg images found in the specified dir!'
Thanks so much for providing this tool ,i run main.py in win10 and ubuntu ,but both of them give an error as 'No .jpg images found in the specified dir!', Sorry ,i'm totally new for this ,could you pls give any information for this error? I tried both Yolo-Annotation-Tool and Yolo-Annotation-Tool-New, they behaved the same , i have no idea about this .
process.py does not work
please comment line 8 in procees.py as it is assigning the string to the current directory
#current_dir = 'Your dataset path.'
class Image has no attribute 'open'
After the python3 update, it get this error. And could you please add if no label added save the empty .txt file for the picture.
Dataset path
Hi,
In process.py, i dont understand which file is dataset path.
Please help me on this..
scrollbar for the image
Hi,
I have large images, they are not fitting the panel,any idea how to add scroll bars to image panel?
yolov3 dataset formart
Hello,
i fellow the instruction of https://github.com/qqwweee/keras-yolo3 and try to build custom dataset,
One row for one image;
Row format: image_file_path box1 box2 ... boxN;
Box format: x_min,y_min,x_max,y_max,class_id (no space).
and i found an example
/home/zhangyang/yolo/VOC2007/JPEGImages/00040.jpg 64,52,162,106,1
/home/zhangyang/yolo/VOC2007/JPEGImages/00010.jpg 67,321,500,411,0
/home/zhangyang/yolo/VOC2007/JPEGImages/00007.jpg 36,342,451,483,0
So i use Yolo-Annotation-Tool-New to lable,and got lots txt file like this
0 0.508 0.545180722892 0.7 0.801204819277 from lable folder, they looks like not the same as
keras-yolo3 required,
I saw your post in keras-yolov3 issue264 ,
Please use my new yolo annotation tool.
Because it will return the yolo format class_id,x_min,y_min,x_max,y_max not x,y,width and height.
Did i do something wrong ?Or i need to do some extra job manully ?
REQUEST: Create bounding box from single center-point click
I was curious if anyone had experimenting creating a bounding box from a single center-point click. Each class could have a specified width and height parameter so that the bounding box can be created after clicking the center point.
Let's say you could snap to center of a coin and click a single point in the center of the penny. Then every penny bounding box could have the same center position. When you inference, provided you calibrated mm/px, you could determine distance between pennies.
Would this be a very complicated feature to implement?
License (MIT?)
Hi Mannivannan, Could you add a MIT license, like you have for some of your other projects? Very valuable tool, but I am unable to use it for my project otherwise. Thank you very much!
Restarting Mac
When trying to run this code on MacOs Mojave, the code forces my computer to restart. Previously working fine, until I updated my OS.
Do not deal with dot in image name
Hi dude,
Line 197 of your main, you are writing :
self.imagename = os.path.split(imagepath)[-1].split('.')[0]
So, if my image is "2.1.jpg", I will get : "2"
os.path.splitext(os.path.basename(imagepath))
instead ;)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.