def defineActiveLevels(prect, mep1, mep2, params): """ % defines the levels on which we need to operate... % the rule is: there must be at least params.min_pix(1) % pixels to work on """ s = rectSize(prect) #################### # TODO - part 3 newSize = s[0] * s[1] maxLevel = 0 thold = params['min_pix'][0] i = 0 while (newSize >= thold): maxLevel = maxLevel + 1 if (maxLevel >= len(mep1) or maxLevel >= len(mep2)): break if ((mep1[i].im.shape[0] * mep2[i].im.shape[1]) <= thold): break i = i + 1 newSize = newSize / 4 minlev = 1 maxlev = maxLevel #################### Ls = list(range(minlev, maxlev + 1)) return Ls
def resampleMei(coi, srect, drect): isrect = coi2imcoord(coi, srect) crect = np.array([ np.floor(isrect[0]), np.ceil(isrect[1]), np.floor(isrect[2]), np.ceil(isrect[3]) ]).astype(np.int) cutim = coi.im[crect[2] - 1:crect[3], crect[0] - 1:crect[1]] cisrect = isrect - np.array([crect[0], crect[0], crect[2], crect[2] ]) + 1 s = rectSize(drect) + 1 rim = resample1D(cutim, cisrect[2:], s[1], 1) rim = resample1D(rim, cisrect[:2], s[0], 2) return rim
def coiCut(coi, rect, safety_border=0): """ % coiCut cut a rectangular region from ME image coi % % ccoi = coiCut(coi, rect, safety_border) % % The rect is first rounded (according to our rect rules). % Use safety_border if you belive the edge of the image might be suspect, and % should not be used. If rect is larger than imageRect-safety_border, the % intersection area is returned. % """ rect = rectIntersect(rect, rectEnlarge(coiImageRect(coi), -1 * safety_border)) if rectSize(rect).prod() > 0: imrect = rect2int(coi2imcoord(coi, rect)) origin = 1 - im2coicoord(coi, imrect[[0, 2]]) im = coi.im[(imrect[2] - 1):imrect[3], (imrect[0] - 1):imrect[1]] else: im = np.zeros((0, 0)) origin = [0, 0] return coimage(im, origin, '{}_c'.format(coi.label), coi.level)
def LKonPyramid(prevPyr, curPyr, prect, init_mot, varargin): """ % LKonPyramid perform Lukas-Kande on multiresolution image pyramid % % mot = LKonPyramid(prevPyr, curPyr, prect, init_mot, params) % % finds the image within rectangle prect of the previous frame (prevPyr) in % the current frame (curPyr), using Lukas-Kanade tracking within the pyramid % mot is a uvs vector [x y scale x_0 y_0] (see functions uvs* ) % params is defined by LKinitParams % % Note: All motions (input and output) are expressed in the base level of % the input pyramids (prevPyr{1}.level). % % features: % if params.do_scale==t, then scale is optimized, else it is kept equal % to init_mot's scale % % debugging - if params.show_fig~=0, then we open figures for each level and % show the motion and residual error after each iteration % % this calls LKonCoImage for each level """ params = LKinitParams(varargin) assert prevPyr[0].level == curPyr[ 0].level, 'Pyramid base levels must be the same.' # %what levels of the pyramid should we run over Ls = defineActiveLevels(prect, prevPyr, curPyr, params) mot = init_mot.copy() plev = prevPyr[0].level for lev in Ls[::-1]: mot = uvsChangeLevel(mot, plev, lev) lprect = rectChangeLevel(prect, 1, lev) cparams = params.copy() # % if num pixels is less then min_pix(2), estimate only u,v on this lev if np.prod(rectSize(lprect)) < params['min_pix'][-1]: cparams['do_scale'] = False if params['show_fig']: cparams['show_fig'] = lev print('Lev {} in {} : {}'.format(prevPyr[lev - 1].level, uvs2String(mot), rect2int(lprect))) plev = lev # % track in this level mot, err = LKonCoImage(prevPyr[lev - 1], curPyr[lev - 1], lprect, mot, cparams) plt.show() # % change motion back to level 1 (in case last level was not 1) # % Note: this 'lev' is the index of level (as in pyr{lev}, not # % neccessarily the real level (as in pyr{lev}.level). # % Thus the motion is always given in the base level of the pyrmaid. mot = uvsChangeLevel(mot, plev, 1) return mot
def uvsWarp(mot, coi, destrect, crop_it=True): """ % uvsWarp warp the image using mot and cut the result to destrect % % wcoi = uvsWarp(mot, coi, destrect) % % if mot is the motion from A -> B, then this function warps a piece of A % (input coi) (aka. source) to be aligned with B (aka. dest). The pixels that % should exist in the result is defined by rounding destrect, which is in B's % coordinate system. % % destrect - (o) me rect, and is rounded by rect2int to find the pixels that % will exist in the final image. Note: this means that an "integer" sized and % pixel aligned rectangle typically looks like [-1.5 1.5 -2.5 2.5], not [-1 1 % -2 2]. If not given, the whole input image is warped and the resulting % image will be assumed to be integer aligned. % % crop_it - (o) default: true; if true and if destrect is too large for % warped image, the 2 are intersected - similar to coiCut (Note: it's pixel offset is still used for the final image % pixel offset. Also if true, any nan rows/columns are removed (due to % input image) """ def resampleMei(coi, srect, drect): isrect = coi2imcoord(coi, srect) crect = np.array([ np.floor(isrect[0]), np.ceil(isrect[1]), np.floor(isrect[2]), np.ceil(isrect[3]) ]).astype(np.int) cutim = coi.im[crect[2] - 1:crect[3], crect[0] - 1:crect[1]] cisrect = isrect - np.array([crect[0], crect[0], crect[2], crect[2] ]) + 1 s = rectSize(drect) + 1 rim = resample1D(cutim, cisrect[2:], s[1], 1) rim = resample1D(rim, cisrect[:2], s[0], 2) return rim def resample1D(Ain, source, dests, dim): A = Ain.astype(np.float) rr = np.linspace(source[0], source[1], dests) lp = np.floor(rr).astype(np.int) - 1 rp = np.ceil(rr).astype(np.int) - 1 rw = np.mod(rr, 1) lw = 1 - rw if dim == 1: B = A[lp, :] * lw.T[:, np.newaxis] + A[rp, :] * rw.T[:, np.newaxis] elif dim == 2: B = A[:, lp] * lw + A[:, rp] * rw return B crect = coiImageRect(coi) idestrect = rect2int(destrect) if crop_it: wirect = uvsRWarp(mot, rectEnlarge(crect, -0.99)) assert np.all(np.mod(rectSize(destrect), 1) == 0) doffset = np.mod(destrect[0:3:2] + 0.5, 1) destrect = rect2int(rectIntersect(wirect, destrect)) idestrect = rect2int(destrect, doffset) if np.any(rectSize(destrect) < 1): wim = np.zeros((0, 0)) else: srect = uvsRBackwardWarp(mot, idestrect) wim = resampleMei(coi, srect, idestrect) wcoi = coimage(wim, tuple(1 - idestrect[0:3:2]), '{}_warp'.format(coi.label), coi.level) return wcoi