Convolution with Fourier Transform: Bokeh!

I’ve managed to work out how to convolve with fft in G’MIC command line. Basic command (with Windows line breaks):

gmic image.png w2:=int(w/2) h2:=int(h/2) +adjust_colors 0,50 fft[-1] ^
 shape.png resize[-1] [0],[0],1,[-1],0,0,0.5,0.5 shift[-1] $w2,$h2,0,0,2 fft[-1] ^
 mul_complex[1,2] [3,4] ifft[1,2] remove[2,3,4] apply_gamma[-1] 2 normalize[-1] 0,255 ^ 
 blur[0] 5,0 blend screen

Brief explanation:

  • Open main image (image.png)
  • Get half of width and height values
  • Increase contrast (adjust_colors or threshold) to isolate bright sections of image
  • Fourier transform this image, will produce real and imaginary value layers (a+ib)
  • Open shape image or use gmic’s shapes at an appropriate size (e.g. shape_heart or shape_polygon)
  • Pad or crop this to match main image’s dimension (weird results if different dimensions)
  • Shift/offset this at half image size so the shape will be at the corners, otherwise result will be shifted
  • Fourier transfrom this image, will produce real and imaginary value layers (c+id)
  • Complex multiply the layers. Mathematically it would be (a+ib)(c+id) = (ac-bd)+i(ad+bc)
  • Inverse fourier transform multiplied image
  • Remove extra images
  • Increase gamma to enhance the effect
  • Normalize to display
  • Blur main image
  • Blend with screen (or lighten) mode

Result:

Playing with the command:

It is quite fast too. With a 2048x1356 main image and 216x216 shape (inset top left), it took 2.3 seconds on my PC (here reduced to 600x400):
db3

Looking forward to see if there’s any tweaks or improvent that can be made to this script.

Notes:

  1. Thanks due to Fred’s ImageMagick Scripts (https://www.fmwconcepts.com/imagemagick/bokeh). I tried to convert the script, but couldn’t do it on my Windows PC without compiling IM with FFTW. Then tried so many blending methods in GIMP using Fourier Transfrom in G’MIC Plugin, but it of course works in a different domain, plus there is no way to multiply layers as complex numbers. Almost went to Python. However, I tried with gmic_cli, and here it is. This does mean the command above could be scripted into a filter.
  2. Other bokeh methods: Bokeh in G’MIC Plugin, but it is at random locations, not centered on the highlights. GIMP’s Lens Blur is quite good, but you can only get circular highlights.
  3. Images from Wikimedia Commons: Christmas_lights_Franklin_Avenue_Millbrook,_NY.JPG and City_Lights_(248468305).jpeg.
2 Likes

Hello @scribbleed ,

Would it be equivalent to use command convolve_fft ?

Oh my, maybe that underscore is why it never came up in my searches :sweat_smile:. At least I learnt how to use gmic_cli and the other functions. :joy:

Played with convolve_fft but a direct application is not quite photographic. It looks like the equivalent to mine is:

gmic image.png +adjust_colors 0,50 shape.png resize[-1] [0],[0],1,[-1],0,0,0.5,0.5 +convolve_fft[1] [2] remove[1,2] apply_gamma[-1] 2 normalize[-1] 0,255 blur[0] 3,0 blend screen output fin.png   

Still needs an initial contrast, a resize if the shape is a different dimension, then gamma after fft, normalization (before blending), and blur+blend to get a photographic look.
fin
Thanks @David_Tschumperle :heart:

Hi, I liked your gradient mask version so i tried to modify your command a little to replicate it:

gmic sp tiger,2048 sharpen 500 +adjust_colors 0,50 shape_polygon 30,6 r. [0],[0],1,[-1],0,0,0.5,0.5 +convolve_fft. [2] remove[1,2] apply_gamma. 2 n. 0,255 b. 3,0 1000,1000,1,1 gaussian. 250,250 r. [0],[0] n. 0,255 negate. a[-1,-2] c +blend screen,1

I used some shortcuts :

  • command. means command[-1] (.. and ... being [-2] and [-3]
  • sp tiger,2048 for sample (spawns a 2048px tiger in your living room)
  • r. for resize[-1]
  • b. for blur (i modified your b[0] to b[-1] since tiger looked a bit too blurry to me)
  • n. for normalize
  • 1000,1000,1,1 (spawns a 1000x1000 image with only 1 channel)
  • gaussian. 250,250 (draws a gaussian blob in the image previously created)
  • a[-1,-2] c for append[-1,-2] c (appends the gaussian image as a 4th channel, which is alpha here)


Let’s hope it works out ok…

I will bookmark this to refactor Splinter Blur at some point. Thank you.

Looks a bit like a Lensbaby lens

One tweak: Should you want to do the “Fake depth of field” within gmic, without resorting to an external paint program, then Jerome Boulanger’s mapblur is your friend. It adjusts blurring dynamically in a particular image locale by way of a mask. Its two immediate predecessor images are (1) the image to be blurred, with all other effects already applied, and (2) the blurring mask. The blurring mask is a gray scale, (one channel) image that has the same width and height as the target image. In this mask, black suppresses all blurring, white permits maximum blurring. blurmask sets up a Gaussian blur style mask. This can be replace by any other generator that makes some arbitrary shaped region.

$ gmic  -m blurmask.gmic Christmas_lights.jpg +blurmask. 44.5%,61.6%,100,10 +mapblur , o. christmas_lights_blurmask.jpg


mask setup for a Gaussian mask centered over the tree:

blurmask : -check ispercentage(${1=50%})" && "\
                  ispercentage(${2=50%})" && "\
                  isnum(${3=50})" && "\
                  isnum(${4=100})

   tx,ty,gr,intensity=${1-4}
   foreach {
      dcx,dcy:=[w*$tx,h*$ty]
      -input 100%,100%,100%,1
      -name. blurmask
      -gaussian[blurmask] $gr,$gr,0
      -oneminus[blurmask]    
      -shift[blurmask] {$dcx-w/2},{$dcy-h/2},0,0,2
      -mul[blurmask] $intensity
      -keep[blurmask]
   }

Have fun!

2 Likes