I'm trying to create a barrel distortion effect using FFmpeg. The lenscorrection filter can do this, but depending on the source material the results can be pretty bad, with moire patterns / bad interpolation.

Source image

enter image description here

Result with FFmpeg

enter image description here
(using: -vf lenscorrection=k1=0.1:k2=0.1): terrible moire interference here. My guess is that the lenscorrection filter uses nearest-neighbor interpolation, and this doesn't seem to be configurable.

I get better results from both ImageMagick and Photoshop here's a Photoshop example for comparison.

enter image description here

For single images that works fine, but I need a way to do this with FFmpeg for video.

Is there a better way? Any tips?

Edit, following the comments: there are at least two ways to improve the FFmpeg results, but they don't really work for real-world usage since they have roughly the same (big) drawback:

  1. Upscale the image by a large factor before feeding it to lenscorrection, and downscale it afterwards. This effectively eliminates moire, and looks even better if I add a little gaussian blur as a lowpass filter. For example:
    ffmpeg -i in.png -vf "scale=iw*8:ih*8:flags=neighbor, lenscorrection=k1=.1:k2=.1, gblur=9:1:15:2, scale=iw/8:ih/8:flags=lanczos" out.png

    enter image description here
    Drawback: the larger the scaling factor, the better the result; it starts looking acceptable at 8x, but for large videos these scale factors are hardly practical, due to extreme CPU/memory overhead.

  2. Use the v360 filter, which does support better interpolation methods (default is bilinear). For instance: ffmpeg -i 1s.png -vf v360=flat:fisheye:ih_fov=60:v_fov=45:h_fov=60:v_fov=45:w=360:h=240 out.png -

    enter image description here
    Drawback: I can't find an intuitive way to control the amount of distortion. It can be reduced by padding the frame, so that the image occupies a smaller proportion of its area (=equivalent to moving the 'lens' further away). But then, for smaller distortions, the frame sizes quickly become unmanageable - same problem as method #1.

So I'm still looking for a better solution if it exists.

  • Try v360 filter instead, with all correct parameters it is doable.
    – user564335
    Dec 25 '20 at 12:47
  • @PaulB.Mahol: thanks, I was actually just playing with v360's options to convert from 'flat' to 'fisheye' formats. This works but I cannot find an adequate way to control the amount of distortion beyond a narrow range... if I cannot figure it out I'll update the question.
    – CugelTC
    Dec 25 '20 at 14:24
  • You can use hacky workaround like oversampling, upsample input to 2x/4x/8x width/height, filter with lenscorrection and then downsample to 0.5x/0.25x/0x125 width/height, Use scale filter for this.
    – user564335
    Dec 25 '20 at 14:52
  • 2
    Added bilinear interpolation to lenscorrection filter.
    – user564335
    Jan 25 '21 at 0:03
  • @PaulB.Mahol: thanks! Tested and answered.
    – CugelTC
    Jan 28 '21 at 18:50

Fixed by Paul B. Mahol's Jan 25 addition. It's now possible to specify bilinear interpolation for lenscorrection, which nicely solves the moire issue. For instance: lenscorrection=k1=.1:k2=.1:i=bilinear

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.