Firefly Remover script [call for firefly example images]

firefly avoidance:
Prevention is better than post processing with a script like this, know your cycles settings.

  • don’t have an emitter emit pure white (1.0, 1.0, 1.0, 1.0)
  • avoid using any value at 100% (1.0 out of 1.0 or 255 of 255 etc…)
  • if you can clamp, clamp.
  • light your scene in a realistic way, read up on studio / set lighting techniques.
  • read the tool tips in the render panel, they will tell you a lot about the parameters themselves
  • using a complex material node will slow down processing. Unless it is deliberate - simplify.
  • understand every part of your node setup, if you can eliminate a node without noticing. do.

firefly calibration:
If you have firefly infested images you would like to donate, I am accepting image examples for calibration. Images don’t need to be big - or even full originals -, but they do need to be at least 9px by 9px with the firefly in the center so i can sample the nearest neighbours. Preferably not jpeg/jpg. png/tiff/tga are fine and welcome.

script in progress:
download link on github

The speed of the script is a function of how many ‘fireflies’ it finds.

In strict mode, if a pixel has a bounding pixel that is beyond a strength of (rgba= .97, .97, .97, 1.0) then the pixel is rejected and not considered to be a firefly. With strict mode set to False, any number of bounding pixels may be bright.

The method as it stands is naive, the more examples you can send me - the better the algorithm can be trained.

Usage

  • Around the last line the script looks for ‘pixeltest4’ , replace that with your image name.
  • Hit run script
  • Click the image in the image editor so it updates.

Status

  • bugfixed, but i welcome examples of failure!
  • added filenotfound handler, will prompt in the console / terminal for user input ( if interactive )
  • added a switch to disable interactive mode for batch processing
  • added a strict mode to reject pixels with bright neighbours as fireflies
  • set default to strict mode, interactive, non-debug

Future

  • could be a bit smarter about colour mixing, take into account the most common colour
  • i’m itching to refactor and do things much simpler.

Examples

  • The first image is described here as a bug report, if for whatever reason you have a similar issue and don’t want to rerender - this script will fix your image.
    http://i.imgur.com/F6vHL.png

This is with strict mode set to False, it removes even touching bright spots.
http://i.imgur.com/j16fx.png
With strict mode on, bright pixels that touch other bright pixels are not considered fireflies
http://i.imgur.com/wMunz.png

That´s seems interesting to me, and seems very well coded too, i´ll give it a try ASAP :wink:

Small heads up, I’m done with the functionality. It seems pretty stable. Massive code changes since the initial upload. It’s now a little cryptic to read. Some functions I wrote towards the end of the cycle might have made a whole blanket of previously coded functions redundant.

If I’ve learnt anything from this, it is do the code you least look forward to first.

I just tried it and it works on the bug-report example, but not on my test render. Does it work on just pure white fireflies? Some of mine seem to be tinted somewhat. Anyway, good job on the script.

if you care to crop portions of the image with the fireflies and upload it to http://www.pasteall.org/pic , in a losless format or gif, then i could do some analyses on it. The approach to finding fireflies at the moment is a little simplistic, but easily modified. The more examples the better.

The best way to avoid fireflies is more samples and more render time.

I often figured out it doesn’t work always that way, I mean, few times fireflies appear when image is already quite clean.

Eg i had a render, bit noisy but without fireflies at 100 samples, i tried waiting for 150/200 samples to clean up more, and guess what…fireflies appeared AFTER those 100 samples. Even if the render was almost fully converged.

In that case guys, the more examples I get of fireflies out in the wild, the better I can analyse and engineer a script that will deal with them. I’m not looking for entire images, just the parts that contain fireflies.

In my cases it often helps to set the Clamp Value of Cycles to 0.99 (or lower).

Kind regards
Alain

Kai Kostack has done some impressive node work, to remove fireflies.

Try this, a bit compressed due to JPEG format unfortunately, but still an interesting situation imho. There is one on the sofa, and a few on the floor.

https://dl.dropbox.com/u/58007699/Blog%20images/Chester%20mG_fireflies.jpg

@aermartin - that’s impressive

Very impressive !
Did he post is composite setup

@marcoG_ita
Always when I see such a low rate of fireflys I always wish over my monitor because I think it’s on my dusty monitor :smiley:

Kind regards
Alain

Andrew Price has an image of Kai’s Node Setup in his Twitter (i think)

Edit: Link found

The bidirectional blurring looks impressive and really squashes a lot of noise.

I’m looking for uncompressed renders, even cropped 9 by 9 grids as a .tga with the firefly in the centre would be useful. But looking at the compressed sofa image spits out this data:

from this it might be reasonable to sum the components and mark a pixel as a firefly if it exceeds some value, compared to its surrounding pixels



424 706 -> [1.0, 0.9411765336990356, 0.8784314393997192, 1.0] -> 3.819607973098755
178 864 -> [1.0, 0.9686275124549866, 0.9568628072738647, 1.0] -> 3.9254903197288513
67 68 -> [1.0, 0.960784375667572, 0.9294118285179138, 1.0] -> 3.890196204185486
58 110 -> [1.0, 0.9647059440612793, 0.9411765336990356, 1.0] -> 3.905882477760315
16 123 -> [1.0, 0.9764706492424011, 0.9490196704864502, 1.0] -> 3.9254903197288513
21 169 -> [1.0, 0.9843137860298157, 0.960784375667572, 1.0] -> 3.9450981616973877
81 218 -> [1.0, 0.9725490808486938, 0.9411765336990356, 1.0] -> 3.9137256145477295
49 422 -> [1.0, 0.9764706492424011, 0.9411765336990356, 1.0] -> 3.9176471829414368
56 603 -> [1.0, 0.9529412388801575, 0.9372549653053284, 1.0] -> 3.890196204185486
29 637 -> [1.0, 0.960784375667572, 0.9294118285179138, 1.0] -> 3.890196204185486
60 643 -> [1.0, 0.988235354423523, 0.9529412388801575, 1.0] -> 3.9411765933036804
31 686 -> [1.0, 0.9725490808486938, 0.9372549653053284, 1.0] -> 3.909804046154022
6 720 -> [1.0, 0.9764706492424011, 0.9450981020927429, 1.0] -> 3.921568751335144
28 764 -> [0.7725490927696228, 0.7176470756530762, 0.6823529601097107, 1.0] -> 3.1725491285324097

I will spend very little time on this.


# this would work for 95% of this image
if (any(rgba) == 1.0) and (sum(rgba) > 3.8):

https://gist.github.com/3313628 (w/ syntax highlighting)


import bpy

D = bpy.data
img = D.images['Chester mG_fireflies.tga']
pxs_slow = pixels = img.pixels

#recast, faster
pxs = [i for i in pxs_slow]

w = width = img.size[0]
h = height = img.size[1]

num_pixels = len(pxs)

#equivalent statements
#gl = grouped_list = [pxs[i:i+4] for i in range(0, num_pixels, 4)]
gl = grouped_list = [pxs[i:i+4] for i in range(num_pixels)[::4]]


def idx_to_co(idx, width):
    r = int(idx / width)
    c = idx % width
    return r, c


def co_to_idx(r, c, width):
    return r * width + c


def rgba_from_index(idx, pxs):
    start_raw_index = idx * 4
    return pxs[start_raw_index:start_raw_index+4]


def is_firefly(rgba):
    if (any(rgba) == 1.0) and (sum(rgba) > 3.8):
        return True


""" found coordinates to look at """
pixels_of_interest = [
    [424,706], [178,864], [67,68], [58,110],
    [16,123], [21,169], [81,218], [49,422], 
    [56,603], [29,637], [60,643], [31,686], 
    [6, 720], [28,764]]
    

print('-----------------')
for r,c in pixels_of_interest:
    idx = co_to_idx(r, c, w)
    rgba = rgba_from_index(idx, pxs)
    print(r,c, '-->', rgba,'-->', is_firefly(rgba))

but this is an outlier:
http://i.imgur.com/53UfM.png

Here is an interesting paper about resolving a coarse grained render:
http://groups.csail.mit.edu/graphics/ilfr/

I tried your script, but with images I had close to my hands the script didn’t work so well.
First image finished with almost untouched fireflies and melted bigger white arreas
Second image had zero changes after your script.

Sadly have to say that simple node setup worked better on those images.
Good luck, and thanks for work :slight_smile:

http://blender.howto.cz/blender-links/test-Fireflies.zip

Great job, and LOL yeh the code you hate get it done.

Thanks for the .zip. more examples means better statistics and lower threshold for me to establish the characteristics of a firefly. The output from the node setup is great, maybe i shouldn’t bother with this silly script.

Few days ago I downloaded some build from graphicall.org r49461 (or something like that) and regular rendering (F12) looks now without fireflies and noise just clean, rendered in tiles very fast.
Integrator panel is gone and to setup number of samples is under Sampling panel now.
I see I missed some news here . . .

Here you are:

http://dl.dropbox.com/u/14100104/pmc_caustic.png

Cheers, mib.

Cool, thanks for that one!

I’ll still explain how the script operates, but in images! Here is the core idea of firefly identification:

  • a pixel is surrounded by other pixels
  • pixels that have obviously different colour values than surrounding pixels might be fireflies.
  • some fireflies are easier to detect than others,
  • first try an absolute check   
    (very bright?, any blown out values?)  
    
  • then try a relative brightness check   
    (check the surrounding pixels, assign a difference value and establish a threshold of when to act)  
    
  • each firefly goes onto a coordinate list.
  • each entry in the list becomes an average (or some clever function) of its surrounding pixels.

finding the pixels isn’t difficult, think of the black area in the following animated GIF as the edge of a massive image, but i’ve abstracted the image size away.

  • if a pixel is on a corner, then i can sample 3 pixels.
  • if a pixel is on an edge, then i can sample 5 pixels.
  • if a pixel is not on a corner, or an edge, then i can sample from all surrounding pixels.
    http://i.imgur.com/KcZy2.gif