Newer
Older
SparseCodingDynamicOcclusions / ALOISampling / createMotionSequence.sh
@Hvitgar Hvitgar on 22 Sep 2016 9 KB Code, Data and Thesis added
#!/bin/bash

### Author: Benjamin Mitzkus
### This script generates random motion sequences where one or two objects
### move randomly on a background

## General Information:
## Vectors are always given as arrays in the notation a[0]=x, a[1]=y

ITERATION=${1}

# directory where the image patches are saved
OUTPUTDIR="output/${2}"

# subdirectory for occlusion patches
OCCOUTPUT=${OUTPUTDIR}/occlusion

# subdirectory for non-occlusion patches
NOOCCOUTPUT=${OUTPUTDIR}/motion

# directory where the image files are saved
IMAGEDIR="output/croppedImages"

# directory where the outline masks are saved
OUTLINEDIR="output/aloi_mask4_outline"

# list of image files
FILES=($(find ${IMAGEDIR} -name "*.png"))

# number of image files in $IMAGELIST
NUMFILES=${#FILES[@]}

# folder for temporary data, will be deleted on exit
TEMPDIR="tmp"

# size of the patches, always quadratic
PATCHSIZE=16

# number of frames for each sequence
NUMFRAMES=4

# boundaries for the velocity with which the images will move
MINVELOCITY=1.5 #Idea here: roughly sqrt(2) which means at least one pixel movement per frame
MAXVELOCITY=3

# seed to control pseudorandom number generation
SEED=0
SEED=$(awk "BEGIN{print ${SEED} + ($ITERATION*13)}")

### Help Functions

## random number generation
# Parameters: 1: return variable, 2: real or integer (r or i), 3: lower boundary, 4: upper boundary
function getRandomNumber {
	local AWKSCRIPT=" { srand(${SEED}); print rand() } "
	local rnd=`echo | awk "${AWKSCRIPT}"`
	echo $rnd >> rnd.log
	let SEED+=1
	local lower=${3}
	local upper=${4}
	local ret
	if [ ${2} == "i" ]
	then
		ret=$(awk "BEGIN{print ${rnd} * 1000000}")
		ret=${ret%.*}
		ret=$(awk "BEGIN{print ${ret}%(${upper}-(${lower}))+${lower}}")
	elif [ ${2} == "r" ]
	then
		ret=$(awk "BEGIN{print (${rnd}*(${upper}-(${lower})))+${lower}}")
	fi

	eval "$1=${ret}"	# return random number
}

## normalizing a vector
# Parameters: 1: return variable
function normalizeVector {
	local vector; declare -a vector
	local vectorname=$1[@]
	vector=("${!vectorname}")
	local length=$(awk "BEGIN{print sqrt((${vector[0]} * ${vector[0]}) + (${vector[1]} * ${vector[1]}))}")

	if [ ${length} == 0 ];then
		return 0 #avoid 0division here
	fi
	local x=$(awk "BEGIN{print ${vector[0]}/${length}}")
	local y=$(awk "BEGIN{print ${vector[1]}/${length}}")

	eval "${1}[0]=${x}"
	eval "${1}[1]=${y}"

}

## searches $IMAGEDIR for .png files and choses one randomly
# Parameters: 1: return variable
function getRandomImagePath {
	local RANDOMNUMBER
	getRandomNumber RANDOMNUMBER i 1 ${NUMFILES}
	eval "$1=${FILES[${RANDOMNUMBER}]}"
}

## finds the outline mask to a given image
# Parameters: 1: Image, 2: return variable
function findOutline {
	local path; declare -a path
	path=( $(echo ${1} | tr "/" "\n") )
	local file
	case "${path[2]}" in
		aloi_red4_col)
			file=${path[3]}_c1.png
			;;

		aloi_red4_ill)
			file=${path[3]}_${path[4] : (-6)}
			;;

		aloi_red4_view)
			local angle=$(echo ${path[4]} | cut -d"_" -f2)
			if [ ${angle} == "r0.png" ]
			then
				file=${path[3]}_c1.png
			else
				file=${path[3]}_${angle}
			fi
			;;
	esac

	eval "${2}=${OUTLINEDIR}/${path[3]}/${file}"
}

## returns a random point on the white outline of a mask
# Parameters: 1: return array, 2: path to outline image
function findOutlinePoint {
	local outlinepoints=($(convert ${2} txt:- | grep FFFFFF | sed "s/ //g" | cut -d":" -f1))
	local numpoints=${#outlinepoints[@]}

	local randomPoint
	getRandomNumber randomPoint i 1 ${numpoints}

	local outlineX=$(echo ${outlinepoints[${randomPoint}]} | cut -d"," -f1)
	local outlineY=$(echo ${outlinepoints[${randomPoint}]} | cut -d"," -f2)

	eval "${1}[0]=${outlineX}"
	eval "${1}[1]=${outlineY}"
}

## calculates the center of a given image (integer, rounded down)
# Parameters: 1: return variable, 2: image
function calculateImageCenter {
	local IMAGESIZE=$(identify ${2} | cut -d" " -f3)
	local width=$(echo ${IMAGESIZE} | cut -d"x" -f1)
	local height=$(echo ${IMAGESIZE} | cut -d"x" -f2)
	local midX=$(awk "BEGIN{print int(${width}/2)}")
	local midY=$(awk "BEGIN{print int(${height}/2)}")

	eval "${1}[0]=${midX}"
	eval "${1}[1]=${midY}"
}

## calculates the direction vector, images will move from the center to the outlinepoint
## with some random velocity between 0 and $MAXVELOCITY
# Parameters: 1: return variable, 2: image center, 3: outline point
function calculateMovement {
local centername=${2}[@]
local outlinename=${3}[@]

local imageCenter=("${!centername}")
local outlinePoint=("${!outlinename}")

local direction; declare -a direction
direction[0]=$(awk "BEGIN{print ${outlinePoint[0]} - ${imageCenter[0]}}")
direction[1]=$(awk "BEGIN{print ${outlinePoint[1]} - ${imageCenter[1]}}")

normalizeVector direction

local velocity
getRandomNumber velocity r ${MINVELOCITY} ${MAXVELOCITY}
local movement; declare -a movement

movement[0]=$(awk "BEGIN{print ${direction[0]} * ${velocity}}")
movement[1]=$(awk "BEGIN{print ${direction[1]} * ${velocity}}")
eval "${1}[0]=${movement[0]}"
eval "${1}[1]=${movement[1]}"
}

## finds a background patch with less than 10% transparent pixels
# Parameters: 1: return variable image path 2:return variable position of patch
function findBackgroundPatch {
	local numPixels=$(awk "BEGIN{print ${PATCHSIZE}*${PATCHSIZE}}")
	local maxTransparentPixels=$(awk "BEGIN{print int(${numPixels}*0.1)}")
	local numTransparentPixels=${numPixels}
	local transparentPixels; declare -a transparentPixels


	while [ ${numTransparentPixels} -gt ${maxTransparentPixels} ]
	do
		local width=0
		local height=0
		local size
		local image
		local x
		local y
		while [ ${width} -lt ${PATCHSIZE} -o ${height} -lt ${PATCHSIZE} ]
		do
			getRandomImagePath image
			size=$(identify ${image} | cut -d" " -f3)
			width=$(echo ${size} | cut -d"x" -f1)
			height=$(echo ${size} | cut -d"x" -f2)
		done
		getRandomNumber x i 0 $(awk "BEGIN{print ${width}-${PATCHSIZE} + 1}")
		getRandomNumber y i 0 $(awk "BEGIN{print ${height}-${PATCHSIZE} + 1}")
		transparentPixels=($(convert ${image} -crop "${PATCHSIZE}x${PATCHSIZE}+${x}+${y}" txt:- | grep "#......00"))
		numTransparentPixels=${#transparentPixels[@]}
	done
	eval "${1}=${image}"
	eval "${2}[0]=${x}"
	eval "${2}[1]=${y}"
}

### Data structure management

## creating a temp folder which will be deleted on exit
function createTmpDir {
	if [ -e ${TEMPDIR} ]
	then
		deleteTmpDir
	fi
	mkdir ${TEMPDIR}
}

function deleteTmpDir {
	rm -r ${TEMPDIR}
}

## Manages the creation of all folders
function mkDirs {
	createTmpDir
	if [ ! -d ${OUTPUTDIR} ]
	then
		mkdir ${OUTPUTDIR}
		mkdir ${OCCOUTPUT}
		mkdir ${NOOCCOUTPUT}
	fi
}

## creates a motion sequence where $NUMOBJECTS random objects move in random directions
## in $NUMFRAMES frames and overlap in some of them
# Parameters: 1: patchNumber
function createMotionSequence {
	# get one or two random image paths
	local IMAGE
	getRandomImagePath IMAGE
	local OUTLINE
	findOutline ${IMAGE} OUTLINE
	local OUTLINEPOINT; declare -a OUTLINEPOINT
	findOutlinePoint OUTLINEPOINT ${OUTLINE}

	local IMAGECENTER; declare -a IMAGECENTER
	calculateImageCenter IMAGECENTER ${IMAGE}

	local MOVEMENT; declare -a MOVEMENT
	calculateMovement MOVEMENT IMAGECENTER OUTLINEPOINT

	# calculate the point where the objects meet
	local STARTPOINT; declare -a STARTPOINT
	getRandomNumber STARTPOINT[0] i 0 $(awk "BEGIN{print int(${PATCHSIZE/4}) + 1}")
	getRandomNumber STARTPOINT[1] i 0 $(awk "BEGIN{print int(${PATCHSIZE/4}) + 1}")

	if [ $(echo "${MOVEMENT[0]}<0" | bc -l) ] #moving left, STARTPOINT should be in right half
	then
		STARTPOINT[0]=$(awk "BEGIN{print ${PATCHSIZE} - ${STARTPOINT[0]}}")
	fi
	if [ $(echo "${MOVEMENT[1]}<0" | bc -l) ] #moving up, STARTPOINT should be in lower half
	then
		STARTPOINT[1]=$(awk "BEGIN{print ${PATCHSIZE} - ${STARTPOINT[1]}}")
	fi

	local xOffset=$(awk "BEGIN{print ${STARTPOINT[0]} - ${OUTLINEPOINT[0]}}")
	local yOffset=$(awk "BEGIN{print ${STARTPOINT[1]} - ${OUTLINEPOINT[1]}}")

	local background="${TEMPDIR}/${1}background.png"
	local size="${PATCHSIZE}x${PATCHSIZE}"

	local backgroundPatch
	local patchPos
	findBackgroundPatch backgroundPatch patchPos
	convert ${backgroundPatch} -crop "${PATCHSIZE}x${PATCHSIZE}+${patchPos[0]}+${patchPos[1]} " png:- | composite png:- -size ${size} xc:white ${background}

	for frame in `seq 1 ${NUMFRAMES}`; do
		local occFile="${TEMPDIR}/${1}occFrame${frame}.png"
		local nooccFile="${TEMPDIR}/${1}nooccFrame${frame}.png"
		local xPosition=$(awk "BEGIN{print ${xOffset} + (${frame} * ${MOVEMENT[0]})}")
		local xPosition=$(echo ${xPosition} | awk '{printf "%.0f\n", $1}') # rounding to integer
		local yPosition=$(awk "BEGIN{print ${yOffset} + (${frame} * ${MOVEMENT[1]})}")
		local yPosition=$(echo ${yPosition} | awk '{printf "%.0f\n", $1}') # rounding to integer

		if [ ${xPosition} -ge 0 ]
		then
			xPosition="+${xPosition}"
		fi

		if [ ${yPosition} -ge 0 ]
		then
			yPosition="+${yPosition}"
		fi


		composite -geometry "${xPosition}${yPosition}" ${IMAGE} ${background} png:- | convert :- -colorspace Gray ${occFile}
		composite -geometry "${xPosition}${yPosition}" ${IMAGE} -size ${size} xc:white png:- | convert :- -colorspace Gray ${nooccFile}

	done


	local imageNr=$(echo ${IMAGE} | grep -o '[^/]*$'  |cut -d"_" -f1)
	local backgroundNr=$(echo ${backgroundPatch} | grep -o '[^/]*$' | cut -d"_" -f1)
	local occOutputfile=${OCCOUTPUT}/${1}_${imageNr}_${backgroundNr}.png
	local nooccOutputfile=${NOOCCOUTPUT}/${1}_${imageNr}.png
	cp ${TEMPDIR}/${1}occFrame1.png ${occOutputfile}
	cp ${TEMPDIR}/${1}nooccFrame1.png ${nooccOutputfile}
	local i
	for i in `seq 2 ${NUMFRAMES}`
	do
		convert ${occOutputfile} ${TEMPDIR}/${1}occFrame${i}.png +append ${occOutputfile}
		convert ${nooccOutputfile} ${TEMPDIR}/${1}nooccFrame${i}.png +append ${nooccOutputfile}
	done
}

### FUNCTION CALLS STARTING HERE ###
mkDirs
createMotionSequence ${ITERATION}
deleteTmpDir