DataAugmentation
			
			
			
			
			
			"""
			
			    WarpAffine(σ = 0.1) <: ProjectiveTransform
			
			A three-point affine warp calculated by randomly moving 3 corners
			of an item. Similar to a random translation, shear and rotation.
			"""
			
			
			
			struct
			
			 
	
			WarpAffine
			 
			<:
			 
	
			ProjectiveTransform
			
			
    
			σ
			
			end
			
			
			
			
			
	
			getrandstate
			(
			
			::
	
			WarpAffine
			)
			 
			=
			 
			
			abs
			(
			
			rand
			(
			Int
			)
			)
			
			
			
			
			function
			 
			
	
			getprojection
			(
			
        
			
			tfm
			::
	
			WarpAffine
			,
			
        
			
			bounds
			::
			
	
			Bounds
			{
			2
			}
			
			;
			
        
			
			randstate
			 
			=
			 
			
	
			getrandstate
			(
			tfm
			)
			)
			
			
    
			
			T
			 
			=
			 
			Float32
			
    
			
			rng
			 
			=
			 
			
			
			Random
			.
			
			seed!
			(
			
			
			Random
			.
			
			MersenneTwister
			(
			)
			,
			 
			randstate
			)
			
    
			
			scale
			 
			=
			 
			
			sqrt
			(
			
			prod
			(
			
			length
			.
			
			(
			
			bounds
			.
			
			rs
			)
			)
			)
			
			
    
			
			srcps
			 
			=
			 
			
			
			shuffle
			(
			rng
			,
			 
			
			
			SVector
			{
			2
			,
			 
			T
			}
			.
			
			(
			
	
			corners
			(
			bounds
			)
			)
			)
			[
			
			1
			:
			3
			]
			
    
			
			offsets
			 
			=
			 
			
			rand
			(
			rng
			,
			 
			
			SVector
			{
			2
			,
			 
			T
			}
			,
			 
			3
			)
			
	
			
			offsets
			 
			=
			 
			
			map
			(
			
			v
			 
			->
			
			 
			(
			
			
			v
			 
			.*
			 
			(
			
			2
			
			
			one
			(
			T
			)
			)
			 
			.-
			 
			
			one
			(
			T
			)
			)
			 
			.*
			 
			
			convert
			(
			T
			,
			 
			
			scale
			 
			*
			 
			
			tfm
			.
			
			σ
			)
			,
			 
			offsets
			)
			
			
	
			
			return
			 
			
	
			threepointwarpaffine
			(
			srcps
			,
			 
			
			srcps
			 
			.+
			 
			offsets
			)
			
			endAdapted from
			
			
			
			
			
			"""
			
			    threepointwarpaffine(srcps, dstps)
			
			Calculate an affine [`CoordinateTransformations.LinearMap`](#)
			from 3 source points to 3 destination points.
			
			Adapted from  [CoordinateTransformations.jl#30](https://github.com/JuliaGeometry/CoordinateTransformations.jl/issues/30#issuecomment-610337378).
			"""
			
			
			function
			 
			
			
	
			threepointwarpaffine
			(
			
        
			
			srcps
			::
			T
			,
			 
			
			dstps
			::
			T
			)
			 
			where
			 
			{
			V
			,
			 
			
			T
			<:
			
			AbstractArray
			{
			
			<:
			
			SVector
			{
			2
			,
			V
			}
			}
			}
			
			
	
			
			X
			 
			=
			 
			
			
			vcat
			(
			
			hcat
			(
			
			dstps
			...
			)
			,
			 
			
			ones
			(
			1
			,
			3
			)
			)
			'
			
    
			
			Y
			 
			=
			 
			
			
			hcat
			(
			
			srcps
			...
			)
			'
			
    
			
			c
			 
			=
			 
			
			(
			
			X
			 
			\
			 
			Y
			)
			'
			
    
			
			A
			 
			=
			 
			
			
			SMatrix
			{
			2
			,
			 
			2
			,
			 
			V
			}
			(
			
			c
			[
			:
			,
			 
			
			1
			:
			2
			]
			)
			
    
			
			b
			 
			=
			 
			
			
			SVector
			{
			2
			,
			 
			V
			}
			(
			
			c
			[
			:
			,
			 
			3
			]
			)
			
    
			
			return
			 
			
			AffineMap
			(
			A
			,
			 
			b
			)
			
			end
			
			
			
			
			function
			 
			
	
			corners
			(
			
			bounds
			::
	
			Bounds
			)
			
			
    
			(
			
			
			Tuple
			(
			x
			)
			 
			for
			
			 
			x
			 
			in
			 
			
			
			ImageTransformations
			.
			
			CornerIterator
			(
			
			CartesianIndices
			(
			
			bounds
			.
			
			rs
			)
			)
			)
			
			end