Files @ 5f42b982809c
Branch filter:

Location: OneEye/exp/color_sampler.py

Laman
deferred data preprocessing saving space
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._dirty=True
		self.showImage()

	def addCorner(self,e):
		self.corners.add(e.x,e.y)
		self._flush()
		self._dirty=True
		self._markCorners()

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

	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("<Motion>",self.sample)
		root.bind("<Left>",lambda e: self.switchImage(-1))
		root.bind("<Right>",lambda e: self.switchImage(1))
		root.bind("<Up>",lambda e: self.switchCorners(-1))
		root.bind("<Down>",lambda e: self.switchCorners(1))
		root.bind("<b>",lambda e: self.setLetter("b"))
		root.bind("<e>",lambda e: self.setLetter("e"))
		root.bind("<w>",lambda e: self.setLetter("w"))
		root.bind("<Key-period>",lambda e: self.switchAsterisk())
		root.bind("<Key-comma>",lambda e: self.switchGrid())
		root.bind("<d>",lambda e: self.deleteBoard())

		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)

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

	@property
	def corners(self):
		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__":
	dirname=sys.argv[1]
	annotations=sys.argv[2]

	s=Sampler(dirname,annotations)