# HG changeset patch # User Laman # Date 2019-04-26 17:38:11 # Node ID 1874230ef2bdde73a392de1bc417f18c474689d4 # Parent 634319abff9f8712bea280dea897bb09e8d5bdd5 annotations: separate board and grid, optional per directory annotation, deletable annotation diff --git a/exp/annotations.py b/exp/annotations.py --- a/exp/annotations.py +++ b/exp/annotations.py @@ -6,10 +6,20 @@ import json from typing import MutableMapping from analyzer.epoint import EPoint +from analyzer.corners import Corners + + +class Board: + def __init__(self,**kwargs): + self.board=Corners(kwargs.get("board") or []) + self.grid=Corners(kwargs.get("grid") or []) + + def isEmpty(self): + return len(self.board)==0 and len(self.grid)==0 class DataFile(MutableMapping): - """self._data: {filename: [EPoint,EPoint,EPoint,EPoint]}""" + """self.data: {filename: [Board, ...}""" def __init__(self,filename): self.filename=filename try: @@ -25,11 +35,15 @@ class DataFile(MutableMapping): def serialize(self,obj): if isinstance(obj,EPoint): return {"type": "EPoint", "val": [obj.x,obj.y]} + elif isinstance(obj,Board): + return {"type": "Board", "val": {"board": list(obj.board), "grid": list(obj.grid)}} raise TypeError(obj) def deserialize(self,obj): - if obj.get("type")!="EPoint": return obj - return EPoint(*obj["val"]) + type=obj.get("type") + if type=="EPoint": return EPoint(*obj["val"]) + elif type=="Board": return Board(**obj["val"]) + return obj def __getitem__(self, key): return self._data[key] def __setitem__(self, key, val): self._data[key]=val diff --git a/exp/color_sampler.py b/exp/color_sampler.py --- a/exp/color_sampler.py +++ b/exp/color_sampler.py @@ -8,8 +8,7 @@ from colorsys import rgb_to_hsv from PIL import Image,ImageTk -from annotations import DataFile -from analyzer.corners import Corners +from annotations import DataFile,Board class Sampler: @@ -18,6 +17,8 @@ class Sampler: 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 @@ -26,7 +27,7 @@ class Sampler: self.hsv=(0,0,0) self.pos=(0,0) self.m=0 - self._corners=[Corners()] + self._boards=[] self._dirty=False self._createGUI() @@ -55,8 +56,12 @@ class Sampler: self.canvas.configure(width=w,height=h) self.m=0 - corners=self.annotations.get(self.filenames[self.k]) or [] - self._corners=[Corners(c) for c in corners+[[]]] + 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): @@ -66,24 +71,43 @@ class Sampler: self.showImage() def switchCorners(self,step): - n=len(self._corners) + 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._dirty=True + self.showImage() + def addCorner(self,e): self.corners.add(e.x,e.y) - self.annotations[self.filenames[self.k]]=[list(corns) for corns in self._corners if len(corns)>0] + self._flush() self._dirty=True self._markCorners() def save(self): if self._dirty: self.annotations.save() - self.dirty=False + self._dirty=False + + def _flush(self): + self.annotations[self.filename]=[b for b in self._boards if not b.isEmpty()] def _createGUI(self): root=tk.Tk() @@ -108,6 +132,9 @@ class Sampler: 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.mainloop() @@ -119,26 +146,34 @@ class Sampler: 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) return bar def _markCorners(self): self.canvas.delete("mark") - for corns in self._corners: - for c in corns: - (x,y)=(c.x,c.y) - self.canvas.create_oval(x-2,y-2,x+2,y+2,fill="#00ff00",tags="mark") - if corns.is_canon(): - (a,b,c,d)=corns - dash=tuple() if corns 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") + 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") @property def corners(self): - return self._corners[self.m] + b=self._boards[self.m] + 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__":