Changeset - 6180b3bd7f3f
[Not reviewed]
default
0 2 1
Laman - 6 years ago 2019-01-01 11:10:26

generating synthetic samples
3 files changed with 83 insertions and 15 deletions:
0 comments (0 inline, 0 general)
exp/color_sampler.py
Show inline comments
 
import sys
 
sys.path.append("../src")
 

	
 
import os
 
import json
 
import gzip
 
from collections.abc import MutableMapping
 
import tkinter as tk
 
from tkinter import LEFT,N,S,E,W
 
from colorsys import rgb_to_hsv
 

	
 
from PIL import Image,ImageTk
 

	
 
from analyzer.epoint import EPoint
 
from analyzer.corners import Corners
 

	
 

	
 
dirname=sys.argv[1]
 
annotations=sys.argv[2]
 

	
 

	
 
class Sampler:
 
	def __init__(self):
 
	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.img=None
 
		self.photo=None
 

	
 
		self.letter="_"
 
		self.hsv=(0,0,0)
 
		self.pos=(0,0)
 
		self.corners=Corners()
 
		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):
 
		self.img=Image.open(os.path.join(self.dirname,self.filenames[self.k]))
 
		(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.corners=Corners(self.annotations.get(self.filenames[self.k]) or [])
 
		self._markCorners()
 

	
 
	def switchImage(self,step):
 
		self.save()
 
		n=len(self.filenames)
 
		self.k=(self.k+step+n)%n
 
		self.showImage()
 

	
 
	def setLetter(self,c):
 
		self.letter=c
 
		self.letterLabel.configure(text="Letter: {0}".format(c))
 

	
 
	def addCorner(self,e):
 
		self.corners.add(e.x,e.y)
 
		self.annotations[self.filenames[self.k]]=list(self.corners)
 
		self._dirty=True
 
		self._markCorners()
 

	
 
	def save(self):
 
		if self._dirty:
 
			self.annotations.save()
 
			self.dirty=False
 

	
 
	def _createGUI(self):
 
		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("<b>",lambda e: self.setLetter("b"))
 
		root.bind("<e>",lambda e: self.setLetter("e"))
 
		root.bind("<w>",lambda e: self.setLetter("w"))
 

	
 
		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)
 

	
 
		return bar
 

	
 
	def _markCorners(self):
 
		self.canvas.delete("mark")
 
		for c in self.corners:
 
			(x,y)=(c.x,c.y)
 
			self.canvas.create_oval(x-2,y-2,x+2,y+2,fill="#00ff00",tags="mark")
 
		if self.corners.is_canon():
 
			(a,b,c,d)=self.corners
 
			self.canvas.create_line(a.x,a.y,b.x,b.y,fill="#00ff00",tags="mark")
 
			self.canvas.create_line(b.x,b.y,c.x,c.y,fill="#00ff00",tags="mark")
 
			self.canvas.create_line(c.x,c.y,d.x,d.y,fill="#00ff00",tags="mark")
 
			self.canvas.create_line(d.x,d.y,a.x,a.y,fill="#00ff00",tags="mark")
 

	
 

	
 
class DataFile(MutableMapping):
 
	"""self._data: {filename: [EPoint,EPoint,EPoint,EPoint]}"""
 
	def __init__(self,filename):
 
		self.filename=filename
 
		try:
 
			with gzip.open(filename,mode="rt",encoding="utf8") as f:
 
				self._data=json.load(f,object_hook=self.deserialize)
 
		except OSError:
 
			self._data=dict()
 

	
 
	def save(self):
 
		with gzip.open(self.filename,mode="wt",encoding="utf8") as f:
 
			json.dump(self._data,f,default=self.serialize,indent="\t")
 

	
 
	def serialize(self,obj):
 
		if isinstance(obj,EPoint):
 
			return {"type": "EPoint", "val": [obj.x,obj.y]}
 
		raise TypeError(obj)
 

	
 
	def deserialize(self,obj):
 
		if obj.get("type")!="EPoint": return obj
 
		return EPoint(*obj["val"])
 

	
 
	def __getitem__(self, key): return self._data[key]
 
	def __setitem__(self, key, val): self._data[key]=val
 
	def __delitem__(self, key): del self._data[key]
 
	def __iter__(self): return iter(self._data)
 
	def __len__(self): return len(self._data)
 

	
 

	
 
if __name__=="__main__":
 
	s=Sampler()
 
	dirname=sys.argv[1]
 
	annotations=sys.argv[2]
 

	
 
	s=Sampler(dirname,annotations)
exp/createsamples.py
Show inline comments
 
import sys
 
sys.path.append("../src")
 

	
 
import os
 
import sys
 
import random
 

	
 
import PIL.Image
 
import PIL.ImageDraw
 
import PIL
 

	
 
from diagram import createDiagram
 
from color_sampler import DataFile
 

	
 

	
 
finalPosCount=5000
 
empty=True
 
perspective=False
 
random.seed(361)
 
inputDir=sys.argv[1]
 
outputDir=sys.argv[2]
 
negDir=sys.argv[3]
 
negFiles=os.listdir(negDir)
 
negFiles.sort()
 

	
 
annotations=DataFile("annotations.json.gz")
 
posCount=len(annotations)
 
multiple=int(round(finalPosCount/posCount+0.5))
 

	
 

	
 
def pickRandom():
 
	file=random.choice(negFiles)
 
	return PIL.Image.open(os.path.join(negDir,file))
 

	
 

	
 
def cropBackground(bgImg,w,h):
 
	(bgw,bgh)=bgImg.size
 
	scale=min(bgw/w,bgh/h)
 
	if scale<1: # minimal upscale
 
		bgImg=bgImg.resize((int(round(bgw/scale+0.5)),int(round(bgh/scale+0.5))),PIL.Image.BICUBIC)
 
		scale=1
 
	else: # random downscale
 
		r=1+random.random()*(scale-1)
 
		bgImg=bgImg.resize((int(bgw/r+0.5),int(bgh/r+0.5)),PIL.Image.BICUBIC)
 
	(bgw,bgh)=bgImg.size
 
	wRange=bgw-w
 
	hRange=bgh-h
 
	x=random.randint(0,wRange)
 
	y=random.randint(0,hRange)
 
	bg=bgImg.crop((x,y,x+w,y+h))
 
	if random.random()<0.5:
 
		bg=bg.transpose(PIL.Image.FLIP_LEFT_RIGHT)
 
	return bg
 

	
 

	
 
def extract(image,cornerList,i,filename):
 
	img=image.copy()
 
	x1=min(p.x for p in cornerList)
 
	x2=max(p.x for p in cornerList)
 
	y1=min(p.y for p in cornerList)
 
	y2=max(p.y for p in cornerList)
 
	w=x2-x1
 
	h=y2-y1
 

	
 
	bg=cropBackground(pickRandom(),w,h)
 

	
 
	mask=PIL.Image.new("1",bg.size,255)
 
	d=PIL.ImageDraw.Draw(mask)
 
	d.polygon([(p.x-x1,p.y-y1) for p in cornerList], fill=0, outline=0)
 
	img.paste(bg,(x1,y1),mask=mask)
 

	
 
	relevantArea=img.crop((x1,y1,x2,y2))
 
	if random.random()<0.5:
 
		relevantArea=relevantArea.transpose(PIL.Image.FLIP_LEFT_RIGHT)
 
	outputPath=os.path.join(outputDir,filename.replace(".","-{0}.".format(i)))
 
	relevantArea.save(outputPath)
 
	print(outputPath,1,0,0,x2-x1,y2-y1)
 

	
 

	
 
for (filename,cornerList) in annotations.items():
 
	path=os.path.join(inputDir, filename)
 
	if not os.path.isfile(path):
 
		print("{0} not found, ignored".format(path))
 
		continue
 
def generate(background,i,outputDir):
 
	bg=background.copy()
 
	img=createDiagram([[]])
 
	maxSize=min(*img.size,*bg.size)
 
	size=random.randint(min(80,maxSize),maxSize)
 
	img=img.resize((size,size),PIL.Image.BICUBIC)
 
	wRange=bg.size[0]-img.size[0]
 
	hRange=bg.size[1]-img.size[1]
 
	x=random.randint(0,wRange)
 
	y=random.randint(0,hRange)
 
	bg.paste(img,(x,y))
 
	outputPath=os.path.join(outputDir,"{0:04}.jpg".format(i))
 
	bg.save(outputPath)
 
	rect=[
 
		max(x-5,0),
 
		max(y-5,0),
 
		img.size[0]+min(10,bg.size[0]-x),
 
		img.size[1]+min(10,bg.size[1]-y)
 
	]
 
	print(outputPath,1,*rect,flush=True)
 

	
 
	img=PIL.Image.open(path)
 
	for i in range(multiple):
 
		extract(img,cornerList,i,filename)
 
# for (filename,cornerList) in annotations.items():
 
# 	path=os.path.join(inputDir, filename)
 
# 	if not os.path.isfile(path):
 
# 		print("{0} not found, ignored".format(path))
 
# 		continue
 
#
 
# 	img=PIL.Image.open(path)
 
# 	for i in range(multiple):
 
# 		extract(img,cornerList,i,filename)
 

	
 
for i in range(finalPosCount):
 
	generate(pickRandom(),i,outputDir)
exp/diagram.py
Show inline comments
 
new file 100644
 
import PIL.Image
 
import PIL.ImageDraw
 

	
 

	
 
width=360
 
height=width
 
padding=12
 
stoneSize=(width-2*padding)/18
 
yellow=(255,200,0)
 
white=(255,255,255)
 
black=(0,0,0)
 

	
 

	
 
def createDiagram(board):
 
	img=PIL.Image.new("RGB",(width,height),yellow)
 
	canvas=PIL.ImageDraw.Draw(img)
 

	
 
	# grid
 
	for i in range(19):
 
		canvas.line((padding,padding+i*stoneSize,width-padding,padding+i*stoneSize),black,1)
 
		canvas.line((padding+i*stoneSize,padding,padding+i*stoneSize,height-padding),black,1)
 

	
 
	# stars
 
	radius=2
 
	for r in range(3,19,6):
 
		for c in range(3,19,6):
 
			x=c*stoneSize+padding
 
			y=r*stoneSize+padding
 
			canvas.ellipse((x-radius,y-radius,x+radius,y+radius),black)
 

	
 
	# stones
 
	radius=stoneSize/2
 
	for (r,row) in enumerate(board):
 
		for (c,color) in enumerate(row):
 
			if color=="X" or color=="O":
 
				x=c*stoneSize+padding
 
				y=r*stoneSize+padding
 
				canvas.ellipse((x-radius,y-radius,x+radius,y+radius),black if color=="X" else white)
 

	
 
	return img
 
\ No newline at end of file
0 comments (0 inline, 0 general)