Tech: Motion compensated denoise for multiple images.

I’ve played with using motion compensation to align image stacks for noise reduction before, but I thought I would have another go.

Denoise compare centre
Denoise compare edge

These images are from a real estate agent’s building near my house. I shot 7 handheld images underexposed about 2 stops at ISO 1600. I then used Avisynth and Virtualdub to created motion compensated frames to match the reference image. That is, every 8×8 pixel block is shifted from the its position in the current image to match the position in the reference image. The result is 7 images that overlap near perfectly. I them used a median filter to blend the now matching frames together to create an image with reduced noise and added detail. Using a median filter helps reduce errors from poor motion compensation from showing up in the final image.

In the images above you can see the original crop; an attempt at manually aligning and blending the whole image, which results in softness and blur; A motion compensated and blended version; a version of the reference image with standard noise reduction applied; and a version with motion compensated blending and standard noise reduction applied afterwards.

The processing is pretty quick by noise reduction standards. Even if you are only using 2 or 3 images you get noticeable improvements in details and reduced noise. Problems occur with parallax and other large changes between images, I’ve tried it photos of people on a windy day, and it does fail in some areas due to the wind, but where it works it works well. I’m not sure why this method is not an option used by more noise reduction software.

For the interested here is my Avisynth script. I first created an uncompressed AVI file of the 7 frames I shot to make things easier


super = MSuper()
backward_vectors = MAnalyse(super, isb = true,blksize=8, searchparam=4)
backward_vectors2 = MAnalyse(super, isb = true,blksize=8, searchparam=4, delta=2)
backward_vectors3 = MAnalyse(super, isb = true,blksize=8, searchparam=4, delta=3)
forward_vectors = MAnalyse(super, isb = false,blksize=8, searchparam=4)
forward_vectors2 = MAnalyse(super, isb = false,blksize=8,searchparam=4, delta=2)
forward_vectors3 = MAnalyse(super, isb = false,blksize=8,searchparam=4, delta=3)

forward_compensation3 = MCompensate(super, forward_vectors3, thSCD1=6000)
forward_compensation2 = MCompensate(super, forward_vectors2, thSCD1=6000)
forward_compensation = MCompensate(super, forward_vectors, thSCD1=6000)
backward_compensation = MCompensate(super, backward_vectors, thSCD1=6000)
backward_compensation2 = MCompensate(super, backward_vectors2, thSCD1=6000)
backward_compensation3 = MCompensate(super, backward_vectors3, thSCD1=6000)

# create interleaved 5 frames sequences
interleave(forward_compensation3, forward_compensation2, forward_compensation, last, backward_compensation, backward_compensation2, backward_compensation3)

medianblurt(radiusy=0, radiusu=0, radiusv=0, temporalradius=3)



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s