3

I'm trying to create the slow-motion of a 5 second video. In order to maintain the same frame-rate I need more frames. I extracted all the frames from the video and doubled them in number by creating new ones. Every frame has been combined with its successor to create an average frame to insert between them.

average = (predecessor + successor)/2

The result is spatially correct but it isn't in terms of colour. The average image is significantly darker than the originals. I'm trying to slow down a video of Federer playing tennis. The average image finds a middle ground between the original image and its successor. This effect can be seen between frames where the players and ball move significantly. The images below show the difference in colour that I'm trying to eliminate (Left: average, Right: Original)

enter image description herePredecessor (Original)

Why does this happen? Is there any better way to achieve what I'm trying to do?.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
Maurizio Brini
  • 216
  • 1
  • 12
  • 4
    In MATLAB, adding up two uint8 arrays uses saturated addition: 200 + 200 = 255. Convert both to floating-point to compute the mean, then convert back to uint8. – Cris Luengo Jul 03 '23 at 15:57
  • 1
    exactly. what does `average = uint8((single(predecessor) + single(successor))/2)` return? – Ander Biguri Jul 03 '23 at 16:16
  • 1
    @CrisLuengo Thank you, this solved my problem. If you want you can post this as an answer so that I can give it the green check – Maurizio Brini Jul 03 '23 at 16:22
  • 1
    For the actual task at hand I would suggest using something like `ffmpeg` to generate interpolated frames instead. It can do simple blending like this, but also has tricks for doing motion compensation. See e.g. https://stackoverflow.com/questions/63152626/is-it-good-to-use-minterpolate-in-ffmpeg-for-reducing-blurred-frames – Mikael Öhman Jul 03 '23 at 16:44

1 Answers1

5

When working with integer arrays, MATLAB uses saturation arithmetic. This means that uint8(200) + uint8(200) == uint8(255).

Assuming your images are uint8, adding up two white pixels leads to saturation, maximally bright white, which you then divide by two to get medium gray.

To avoid this convert the images to a floating-point type, MATLAB defaults to double:

average = uint8((double(predecessor) + double(successor))/2);

But you can also use single if you’re worried about memory usage, as suggested by Ander in a comment..

Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • 1
    My memory optimizing hat is always on because I am used to work with 2000^3 images, but indeed, `double` is good enough! – Ander Biguri Jul 03 '23 at 20:37
  • 1
    @AnderBiguri I also usually work with single-precision floats, it's enough precision for most applications in image processing. It's just that in MATLAB it's easier to work with `double` most of the time. – Cris Luengo Jul 03 '23 at 20:48