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:
```[](https://www.blogger.com/blogger.g?blogID=636453477220885924" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;)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.