Page MenuHomec4science

cropRoutines.py
No OneTemporary

File Metadata

Created
Wed, May 1, 23:27

cropRoutines.py

# at times it may be beneficial to process a big block of data (volume, image)
# in little crops, one crop at a time
# since contex is important when using a convolutional neural network,
# we want to ensure that each element of output has been generated
# with enough context
# thus, when breaking down a large volume into little crops, we should
# generate crops that overlap, and only retain the output elements for each crop
# that have been generated with enough context
# the first crop XXXXXXXXXX
# the second crop OOOOOOOOOO
# the outputs combined XXXXXXXOOOOOOO
import math
def noCrops(inSize, cropSize, marginSize, startDim=0):
# inSize
# cropSize - can be shorter than inSize, if not all dims are cropped
# in this case startDim > 0
# marginSize - same length as cropSize; stores size of a single margin;
# the resulting overlap between crops is 2*marginSize
# startDim - all dimensions starting from this one are cropped;
# for example, if dim 0 indexes batches and dim 1 indexes channels
# startDim would typically equal 2
nCrops=1
for dim in range(startDim, len(inSize)):
relDim=dim-startDim
nCropsPerDim=(inSize[dim]-2*marginSize[relDim])/ \
(cropSize[relDim]-2*marginSize[relDim])
if nCropsPerDim<=0:
nCropsPerDim=1
nCrops*=math.ceil(nCropsPerDim)
return nCrops
def noCropsPerDim(inSize,cropSize,marginSize,startDim=0):
# nCropsPerDim - number of crops per dimension, starting from startDim
# cumNCropsPerDim - number of crops for one index step along a dimension
# starting from startDim-1; i.e. it has one more element
# than nCropsPerDim, and is misaligned by a difference
# in index of 1
nCropsPerDim=[]
cumNCropsPerDim=[1]
for dim in reversed(range(startDim,len(inSize))):
relDim=dim-startDim
nCrops=(inSize[dim]-2*marginSize[relDim])/ \
(cropSize[relDim]-2*marginSize[relDim])
if nCrops<=0:
nCrops=1
nCrops=math.ceil(nCrops)
nCropsPerDim.append(nCrops)
cumNCropsPerDim.append(nCrops*cumNCropsPerDim[len(inSize)-dim-1])
nCropsPerDim.reverse()
cumNCropsPerDim.reverse()
return nCropsPerDim, cumNCropsPerDim
def cropInds(cropInd,cumNCropsPerDim):
# given a single index into the crops of a given data chunk
# this function returns indexes of the crop along all its dimensions
assert cropInd<cumNCropsPerDim[0]
rem=cropInd
cropInds=[]
for dim in range(1,len(cumNCropsPerDim)):
cropInds.append(rem//cumNCropsPerDim[dim])
rem=rem%cumNCropsPerDim[dim]
return cropInds
def coord(cropInd,cropSize,marg,inSize):
# this function maps an index of a volume crop
# to the starting and end coordinate of a crop
# it is meant to be used for a single dimension
assert inSize>=cropSize
startind=cropInd*(cropSize-2*marg) #starting coord of the crop in the big vol
startValidInd=marg #starting coord of valid stuff in crop
endValidInd=cropSize-marg
if startind >= inSize-cropSize:
startValidInd=cropSize+startind-inSize+marg
startind=inSize-cropSize
endValidInd=cropSize
if cropInd==0:
startValidInd=0
return slice(int(startind),int(startind+cropSize)), \
slice(int(startValidInd),int(endValidInd))
def coords(cropInds,cropSizes,margs,inSizes,startDim):
# this function maps a table of crop indeces
# to the starting and end coordinates of the crop
cropCoords=[]
validCoords=[]
for i in range(startDim):
cropCoords. append(slice(0,inSizes[i]))
validCoords.append(slice(0,inSizes[i]))
for i in range(startDim,len(inSizes)):
reli=i-startDim
c,d=coord(cropInds[reli],cropSizes[reli],margs[reli],inSizes[i])
cropCoords.append(c)
validCoords.append(d)
return cropCoords, validCoords
def cropCoords(cropInd,cropSize,marg,inSize,startDim):
# a single index in, a table of crop coordinates out
nCropsPerDim,cumNCropsPerDim=noCropsPerDim(inSize,cropSize,marg,startDim)
cropIdx=cropInds(cropInd,cumNCropsPerDim)
cropCoords, validCoords=coords(cropIdx,cropSize,marg,inSize,startDim)
return cropCoords, validCoords

Event Timeline