# HG changeset patch
# User Laman
# Date 2019-05-03 18:09:55
# Node ID c96bd773ec28ffa82db80982d10470b3c1a9c088
# Parent  6d82b10803791b965058cbb9490cccc62fc1ec3a

random image transformations

diff --git a/exp/keras/prepare_data.py b/exp/keras/prepare_data.py
--- a/exp/keras/prepare_data.py
+++ b/exp/keras/prepare_data.py
@@ -3,14 +3,60 @@ import sys
 import re
 import random
 
+import numpy as np
 import cv2 as cv
 
 sys.path.append("../exp")
-from annotations import DataFile,computeBoundingBox
+from annotations import DataFile,computeBoundingBox,Corners
+from geometry import Line
+from keras.transformation_matrices import getIdentity,getRotation,getTranslation,getScale,getMirroring,getProjection
 
 random.seed(361)
 
 
+class Sample:
+	SIDE=256
+
+	def __init__(self,img,grid):
+		self.img=img
+		self.grid=grid
+
+	def transform(self):
+		center=self._getCenter()
+		m=getIdentity()
+		t1=getTranslation(-center.x,-center.y)
+		proj=getProjection()
+		rot=getRotation()
+		mir=getMirroring()
+		for mi in [t1,mir,proj,rot]:
+			m=np.matmul(mi,m)
+		m=np.matmul(self._computeCrop(m),m)
+		img=cv.warpPerspective(self.img,m,(self.SIDE,self.SIDE))
+		grid=Corners(c.transform(m) for c in self.grid)
+		Sample(img,grid).show()
+
+	def _getCenter(self):
+		(a,b,c,d)=self.grid
+		p=Line.fromPoints(a,c)
+		q=Line.fromPoints(b,d)
+		return p.intersect(q)
+
+	def _computeCrop(self,m):
+		grid=Corners(c.transform(m) for c in self.grid)
+		(x1,y1,x2,y2)=computeBoundingBox(grid)
+		(wg,hg)=(x2-x1,y2-y1)
+		(left,top,right,bottom)=[random.uniform(0.05,0.2) for i in range(4)]
+		t2=getTranslation(left*wg-x1, top*hg-y1)
+		scale=getScale(self.SIDE/(wg*(1+left+right)), self.SIDE/(hg*(1+top+bottom)))
+		return np.matmul(scale,t2)
+
+	def show(self):
+		img=np.copy(self.img)
+		for c in self.grid:
+			cv.circle(img,(int(c.x),int(c.y)),3,[0,255,0],-1)
+		show(img)
+
+
 def traverseDirs(root):
 	stack=[root]
 	while len(stack)>0:
@@ -31,24 +77,8 @@ def harvestDir(path):
 	for f in files:
 		img=cv.imread(f.path)
 		for b in boards:
-			crop(img,b)
-
-
-def crop(img,board):
-	margin=0.2
-	(hi,wi)=img.shape[:2]
-	(x1,y1,x2,y2)=computeBoundingBox(board.board)
-	(wb,hb)=(x2-x1,y2-y1)
-	dx1=min(int(wb*margin),x1)
-	dx2=min(int(wb*margin),wi-x2)
-	dy1=min(int(hb*margin),y1)
-	dy2=min(int(hb*margin),hi-y2)
-	xa=x1-random.randint(0,dx1)
-	xb=x2+random.randint(0,dx2)
-	ya=y1-random.randint(0,dy1)
-	yb=y2+random.randint(0,dy2)
-	show(img[ya:yb,xa:xb])
-	return img[ya:yb,xa:xb]
+			sample=Sample(img,b.grid)
+			sample.transform()
 
 
 def show(img,filename="x"):
diff --git a/exp/keras/transformation_matrices.py b/exp/keras/transformation_matrices.py
new file mode 100644
--- /dev/null
+++ b/exp/keras/transformation_matrices.py
@@ -0,0 +1,56 @@
+import math
+import random
+
+import numpy as np
+
+
+def getIdentity():
+	return np.float32([
+		[1,0,0],
+		[0,1,0],
+		[0,0,1]
+	])
+
+
+def getRotation():
+	alpha=random.random()*2*math.pi
+	return np.float32([
+		[math.cos(alpha),math.sin(alpha),0],
+		[-math.sin(alpha),math.cos(alpha),0],
+		[0,0,1]
+	])
+
+
+def getTranslation(dx,dy):
+	return np.float32([
+		[1,0,dx],
+		[0,1,dy],
+		[0,0,1]
+	])
+
+
+def getScale(kx,ky=0):
+	if not ky: ky=kx
+	return np.float32([
+		[kx,0,0],
+		[0,ky,0],
+		[0,0,1]
+	])
+
+
+def getMirroring():
+	return np.float32([
+		[random.choice((1,-1)),0,0],
+		[0,1,0],
+		[0,0,1]
+	])
+
+
+def getProjection():
+	dx=random.uniform(-0.001,0.001)
+	dy=random.uniform(-0.001,0.001)
+	return np.float32([
+		[1,0,0],
+		[0,1,0],
+		[dx,dy,1]
+	])
diff --git a/src/analyzer/corners.py b/src/analyzer/corners.py
--- a/src/analyzer/corners.py
+++ b/src/analyzer/corners.py
@@ -7,7 +7,7 @@ log=logging.getLogger(__name__)
 
 class Corners:
 	def __init__(self,cornerList=[]):
-		self._corners=cornerList[:]
+		self._corners=list(cornerList)
 		self._is_canon=False
 		self._canonizeOrder()