import sys sys.path.append("../src") import os import tkinter as tk from tkinter import LEFT,N,S,E,W from colorsys import rgb_to_hsv from PIL import Image,ImageTk from annotations import DataFile,Board class Sampler: def __init__(self,dirname,annotations): self.dirname=dirname self.annotations=DataFile(annotations) self.filenames=[f for f in sorted(os.listdir(self.dirname)) if f.endswith(".jpg")] self.k=0 self.asterisk=False self.isGrid=False self.img=None self.photo=None self.letter="_" self.hsv=(0,0,0) self.pos=(0,0) self.m=0 self._boards=[] self._dirty=False self._createGUI() def sample(self,e): try: (r,g,b)=(x/255 for x in self.img.getpixel((e.x,e.y))) except IndexError: return (h,s,v)=map(lambda x: round(x,3), rgb_to_hsv(r,g,b)) self.hsv=(h,s,v) self.pos=(e.x,e.y) self.posLabel.configure(text="({0},{1})".format(e.x,e.y)) self.colorLabel.configure(text="HSV: ({0}, {1}, {2})".format(round(h*360),s,v)) def printSample(self): print("\t".join(map(str, (self.filenames[self.k],*self.pos,self.letter,*self.hsv)))) def showImage(self): filename=self.filenames[self.k] self.img=Image.open(os.path.join(self.dirname,filename)) self.root.title(filename) (w,h)=self.img.size self.photo=ImageTk.PhotoImage(self.img) self.canvas.delete("all") self.canvas.create_image(0,0,image=self.photo,anchor="nw") self.canvas.configure(width=w,height=h) self.m=0 self.isGrid=False f=self.filename if f in self.annotations: self._boards=self.annotations[f]+[Board()] else: self._boards=[Board()] self._markCorners() def switchImage(self,step): self.save() n=len(self.filenames) self.k=(self.k+step+n)%n self.showImage() def switchCorners(self,step): n=len(self._boards) self.m=(self.m+step+n)%n self.isGrid=False self._markCorners() def setLetter(self,c): self.letter=c self.letterLabel.configure(text="Letter: {0}".format(c)) def switchAsterisk(self): self.asterisk=not self.asterisk self.asteriskLabel.configure(text="*" if self.asterisk else "()") self._markCorners() def switchGrid(self): self.isGrid=not self.isGrid self._markCorners() def deleteBoard(self): self._boards.pop(self.m) self._flush() self.showImage() def addCorner(self,e): self.corners.add(e.x,e.y) self._flush() self._markCorners() def setGrade(self,g): self.board.setGrade(g) self._flush() if len([b for b in self._boards if not b.isEmpty()])>1: self.switchCorners(1) else: self.switchImage(1) def save(self): if self._dirty: self.annotations.save() self._dirty=False def _flush(self): self.annotations[self.filename]=[b for b in self._boards if not b.isEmpty()] self._dirty=True def _createGUI(self): self.root=root=tk.Tk() frame=tk.Frame(root) frame.grid(column=0,row=0,sticky=(N,S,E,W)) self.canvas=tk.Canvas(frame) self.canvas.grid(row=1,column=0) bar=self._createBar(frame) bar.grid(row=2,column=0,sticky=(E,W)) self.showImage() self.canvas.bind('<1>',lambda e: self.printSample()) self.canvas.bind('<3>',self.addCorner) self.canvas.bind("",self.sample) root.bind("",lambda e: self.switchImage(-1)) root.bind("",lambda e: self.switchImage(1)) root.bind("",lambda e: self.switchCorners(-1)) root.bind("",lambda e: self.switchCorners(1)) root.bind("",lambda e: self.setLetter("b")) root.bind("",lambda e: self.setLetter("e")) root.bind("",lambda e: self.setLetter("w")) root.bind("",lambda e: self.switchAsterisk()) root.bind("",lambda e: self.switchGrid()) root.bind("",lambda e: self.deleteBoard()) root.bind("",lambda e: self.setGrade(Board.CLEAR)) root.bind("",lambda e: self.setGrade(Board.GOOD)) root.bind("",lambda e: self.setGrade(Board.POOR)) root.mainloop() def _createBar(self,frame): bar=tk.Frame(frame,height=20,borderwidth=1,relief="sunken") self.letterLabel=tk.Label(bar,width=8,text="Letter: _") self.letterLabel.pack(side=LEFT) self.posLabel=tk.Label(bar,width=16,text="(,)") self.posLabel.pack(side=LEFT) self.colorLabel=tk.Label(bar,width=20,text="HSV: (,,)") self.colorLabel.pack(side=LEFT) self.asteriskLabel=tk.Label(bar,width=4,text="()") self.asteriskLabel.pack(side=LEFT) self.gradeLabel=tk.Label(bar,width=8,text="") self.gradeLabel.pack(side=LEFT) return bar def _markCorners(self): self.canvas.delete("mark") for b in self._boards: for corners in (b.board,b.grid): for c in corners: (x,y)=(c.x,c.y) self.canvas.create_oval(x-2,y-2,x+2,y+2,fill="#00ff00",tags="mark") if corners.is_canon(): (a,b,c,d)=corners dash=tuple() if corners is self.corners else (4,4) self.canvas.create_line(a.x,a.y,b.x,b.y,fill="#00ff00",dash=dash,tags="mark") self.canvas.create_line(b.x,b.y,c.x,c.y,fill="#00ff00",dash=dash,tags="mark") self.canvas.create_line(c.x,c.y,d.x,d.y,fill="#00ff00",dash=dash,tags="mark") self.canvas.create_line(d.x,d.y,a.x,a.y,fill="#00ff00",dash=dash,tags="mark") self.gradeLabel.configure(text=Board.labels[self.board.grade]) @property def board(self): return self._boards[self.m] @property def corners(self): b=self.board return b.grid if self.isGrid else b.board @property def filename(self): return "." if self.asterisk else self.filenames[self.k] if __name__=="__main__": dirname=sys.argv[1] annotations=sys.argv[2] s=Sampler(dirname,annotations)