Skip to content

How imfuse works

Martin Viereck edited this page Jan 18, 2023 · 34 revisions

How imfuse works

imfuse generates an overall sharp image from a stack of source images, where each source images is only partially sharp in focus.

  • This page describes the general workflow of imfuse.
  • The magic is all about generating masks that describe the desired areas of each single image that should contribute to the overall sharp result.
  • Make sure the source images are aligned and maybe cropped first.
  • Check out the examples.

Preparation

Aligning

For best results the stackshot source images need to be aligned.

  • You can use tool stackalign to create a new folder with aligned source images.
  • imfuse has an option --align. However, I recommend to rather use stackalign so you can use the aligned images later again.
  • This needs tool PetteriAimonen/focus-stack.
  • Another aligning tool is align_image_stack from panorama / hugin tools.

Cropping

It can take a lot of time to find the best option set. To speed this up, I recommend to work with a cropped part of the source images first.

  • First run with option --background=enfuse to estimate which parts of the image might be difficult.
  • Use tool stackprepare with option --crop or --shave to get a chosen part of the aligned source images.
  • Run imfuse with the cropped images and several option sets until you find one that suits well. Than run with same option set on the full-sized aligned source images.

Cache, preview and file name

I almost always run imfuse with options -CVWXL.

  • Option -C, --cache stores the generated mask files in cache folder ~/.cache/imfuse.
    • In case you change options to optimize the results, imfuse will re-use the cache files whenever possible. This makes it faster.
      • imfuse applies the options in several steps.
        • If you change an option of one step, the affected step and all following steps will have to run.
        • Changing an option in a late step (like the --final* options) is cheap and fast.
        • Changing --background in step 1 is cheap, too, because it does not affect mask generation.
    • The default file format to store in cache is mpc, that is optimized for fast writing and reading by ImageMagick. However, it needs a lot of disk space. In case you run out of disk space, use slower but smaller compressed tif with option --maskformat=tif.
    • For best performance the cache should be on an SSD hard drive.
    • imfuse --rmcache cleans the imfuse cache. It can grow really big. The current cache size is shown after each run of imfuse.
  • Option -V will show you intermediate results in image viewer geeqie. However, this will slow down imfuse.
  • Option -W will show the result image in image viewer feh.
  • Option -X additionally stores the final mask and a depth map. They are shown in feh, too, and help to analyze the result.
  • The file name of imfuse by default consists of two numbers, the first one a shorted md5sum of the source images, the second one a shortened md5sum from the given options. This gives a unique file name and sorts images of same source together.
    • The options are stored as exif meta data in the image and can be seen with exiftool -ImageDescription IMAGENAME.
    • With option -L, --longname the options are added to the file name.

Step 1: Background

You can create a background image on which the result image will be painted on.

  • Some backgrounds of interest: enfuse, wave, overlay.
  • Example: --bg=enfuse.
  • You can as well use the background option only without all other steps.
  • The background will be visible in the result only if the result is partially (semi-)transparent.
    • This can happen e.g. with options --cutalpha, finalalpha, --finalthreshold.

Step 2: Basic mask generation

imfuse provides a lot of options to generate masks from the source images.

  • The order of the mask generating options does not matter.
  • Most mask generating options detect contrast edges in the source images. The idea is that only areas in focus will show sharp edges.
    • Most used by myself: --statistic, --blur with two sigma arguments, --morphology, --wavelet.
    • Some mask generators accept arguments for radius, sigma or percent.
      • Think of radius and sigma as of brush sizes.
      • Low values for radius or sigma show more detail and cause noise.
      • High values for radius or sigma show more contrast, less noise and less detail.
      • Examples: --statistic=r4, --blur=s0.75,S1.2
  • Some mask generating options provide color space channels or image comparisons.
    • Often useful example: --darkness=w10

Step 3: Mask merging

The masks generated in step 2 are merged together into one mask.

  • The masks contribute to the merged mask according to their weight given mit argument w.
    • If argument w is not given, the weights will be calculated automatically to give each mask the same weight.
  • The merged mask can be adjusted with the --mask* options.
    • The --mask* options in general serve to connect the detected contrast edges to also get unsharp areas in between that are likely in focus, too. I call those areas gaps.
    • The order of the --mask* option matters. Each one will process the result of the previous one.
    • The --mask* options have default values that might be entirely useless depending on the overall setup. Try different values for the arguments.
    • Option --masklevel is enabled by default and always executed at last to stretch the masks to a 0..100% spectrum again. This helps in step 4 to have full range percent values.
    • Examples:
      • Reduce noise and close gaps with --maskwave=p100.
      • Close gaps with --maskmorph=close,r2,R2.
      • Enhance contrast and close gaps with --maskblur. However, this can strengthen noise, too. Maybe rather use --cutblur later.

Step 4: Generating the overall sharp image

Each source image will be compared with its according mask to decide which parts of it will contribute to the overall sharp result image.

  • There might be foreground objects that are superseded by strong background objects.
    • Use option --cutless to preserve foreground objects.
      • --cutless takes a percent value that you will need to adjust in most cases.
      • If the foreground objects are not complete, use a lower percent value for --cutless.
      • If undesired unsharp areas appear due to --cutless, use a higher percent value for --cutless.
  • The masks might have major gaps where no sharp edge was found. Also it might look rough.
    • Use option --cutwave to soften the cut. This also closes some gaps. The percent argument adjusts the overall softness.
    • --cutblur softens the cut in another way than --cutwave and can also close some gaps.
  • Further --cut* options are available. The order matters. Always use --cutless first if it is needed.
    • A quite useful one is --cutalpha that makes the cuts semitransparent according to the mask.
      • Use --cutbg before --cutalpha to fill the background.
    • Scissors: Options --cutmorph=dilate, --cutthreshold and --cutmax can serve as scissors to cut of borders or parts of the cut mask. However, none of them works really great.

Step 5: Post processing the overall sharp image

This step mostly serves to change the background to a nice bokeh.

  • The --final* options base on a final mask that is generated as a maximum of all single masks.
  • Some --final* options create transparency.
    • The result image might be already partially transparent.
    • You can turn off transparency with --finalalpha=off.
    • Transparent results can be painted on a background of step 1.
  • You can make the result transparent according to the final mask.
    • --finalalpha will make weak areas very transparent, but strong areas less transparent.
      • --cutalpha might give better results than --finalalpha.
  • You can cut off weak areas with --finalthreshold. The cut off areas will be transparent.
    • Adjust the percent argument until all and only weak areas are cut off.
    • Add a sigma argument for a soft cut border.
      • The result of --finalthreshold can be painted on a background image of step 1.
  • You can blur the background with --finalblur.
    • Use a percent value to tell how much of weak area should be blurred.
      • Find out a useful percent value with --finalthreshold and drop --finalthreshold afterwards. --finalthreshold helps here to see which areas will be blurred.
    • Set a sigma argument for strength of blur.
    • Different and less invasive is --finalblur2 that blurs low contrast areas more than strong contrast areas.

Examples

The wiki contains some example stacks and results for different option sets. You might try out the shown option sets and adjust them to your own stackshot.

  • Option --cutless needs to be adjusted for most stacks.
  • The radius of --cutmorph often needs to be adjusted.
  • Options --darkness --saturation sometimes need an adjusted weight.

This option sets proved to work well for several macro stackshots:

  • --fft --darkness=w10 \
    --maskfft \
    --cutwave --cutbg --cutalpha=p-25,P150
    
  • --blur=s0.3,S0.6 --blur=s1,S2 --blur=s2,S3 --saturation=w25,level \
    --maskwave=p5 --maskstat=r6,Mean --masklevel=t5 \
    --cutless=p20 --cutwave=p75 --cutmorph=r3,R1,Erode
    

In some cases it makes sense to add --finalblur or --finalblur2. Sometimes --darkness is better than --saturation.