Writing simple optical flow in python. Part 3

Today, my imaginary readers, we improve our optical flow dramatically. Lets see, what our algorithm produces for images that have more than 1-pixel shifts.

I0 I1
OF results:


You can see, that the algorithm cannot deal with too large displacements. Even with multiple warps.
Lets apply multiscale scheme now. We need to construct image pyramid:


#from flow_huber_py import construct_image_pyramid
def construct_image_pyramid(I, pyrlevels, pyrfactor):
    factor = 2. ** .5
    smooth_sigma = (1. / pyrfactor) ** .5 / factor
    pyr = []
    tmp = I
    pyr.append(I) # add original image to pyramid
    for m in range(pyrlevels - 1):
        shape = (numpy.array(tmp.shape) * pyrfactor).astype('int32')

        idx, idy = np.meshgrid(np.arange(shape[1]), np.arange(shape[0]))
        idx = idx *tmp.shape[1] / shape[1].astype('float32')
        idy = idy *tmp.shape[0] / shape[0].astype('float32')

        filt1 = scipy.ndimage.filters.gaussian_filter(tmp, smooth_sigma, order=0, output=None, mode='reflect', cval=0.0, truncate=2.0)
        filt1r = interp2linear(filt1, idx, idy,)

        tmp = filt1r
        pyr.append(filt1r)
    return pyr
Construct our pyramid with 2 layers:
pyrfactor = .7
pyrlevels = 1

I0pyr = construct_image_pyramid(I0, pyrlevels, pyrfactor)
I1pyr = construct_image_pyramid(I1, pyrlevels, pyrfactor)
Let the show begin:
import scipy.ndimage

for level in range(pyrlevels - 1, -1, -1):
    M, N = I0pyr[level].shape
    if level == pyrlevels - 1:
        print "asdasd"
        u = numpy.zeros_like(I0pyr[level])
        v = numpy.zeros_like(I0pyr[level])
    else:
        rescale_v, rescale_u = numpy.array([M, N], dtype='float32') / I0pyr[level + 1].shape
        u = scipy.ndimage.zoom(u, [rescale_v, rescale_u], order=3) * rescale_u
        v = scipy.ndimage.zoom(v, [rescale_v, rescale_u], order=3) * rescale_v
        if u.shape != I0pyr[level].shape or v.shape != I0pyr[level].shape:
            raise Exception("Resize failed during transition to higher levels. Need better resize implementation.")

    u0, v0 = u.copy(), v.copy()
    
    I0_ = I0pyr[level]
    I1_ = I1pyr[level]
    
    print I1_.shape, u0.shape, I0pyr[level].shape
    wrpr = Warper( I0_.shape, u0, v0, I0_, I1_, 
              train_function = TrainFunctionTV(u0, v0, rate=0.1, num_steps = 1000, alpha = 0.1), display=0)
    warps = 10
    for i in range(warps):
        wrpr.warp()
    u, v = wrpr.u, wrpr.v
    

    plt.figure()
    plt.subplot(1,2,1)
    plt.imshow( I0pyr[level])
    plt.quiver( u, v, scale_units='xy', angles='xy', scale = 1., color='g')
    plt.subplot(1,2,2)
    plt.imshow( I1pyr[level])

OF results:


Now optical flow is much more adequate.

No comments:

Post a Comment