In the previous part I created a negative scanner and created batch processing to turn it into good looking pictures.
In this part I will continue to develop dust and scratches process.
Dust and scratches are unavoidable when you are scanning negatives. The expensive professional scanners will create a dust mask by using infrared sensor – but that is not available in most consumer grade scanners or the one we build from macro bellows. To deal with the dust we will have to do it the software way.
Unless the scanner has a special hardware that scans for dust (usually using infrared sensor) every scanning software has to basically guess the dust extraction by estimating what is undesirable part and what is not. This has its plethora of issues – most notably parts of the image like hair are very much similar to scratches. A fine foliage in the background can look like dust etc… This all minimizes the effectiveness of any such post processing. While the actual process is very effective, we have to tone it down quite a bit to avoid mushing up other features.
The baby way of removing dust and scratches is to use simple filter such as median or some of those one click dust & scratch filters. This will remove any of the sharp spikes such as dust, but also uncontrollably blur any other fine texture.
The proper way is to first create a mask that would have only the dust and scratches in it then go from there.
There is many ways how to approach this. The simplest way would be to look for intensity spikes.
One way to achieve this is to actually blur the image slightly – which naturally hides such spikes, then compare the blurred image with the original to see what was removed – which would be the dust.
Here is a simple version of this. First we will desaturate the image as we are interested in the intensity. Next is a strong Noise Reduction – since scanned film has a lot of grain we don’t want to be the grain part of our dust estimation and the Noise reduction will take care of it. Next is a fork – the bottom part will go through a slight Gaussian blur (0.9 – 1.0), then we will compare it it with the original denoised image. We will use Subtract blending layer – which simply means give us the sharp image minus the blurred image – this gives us the difference between the sharp and slightly blurred picture – where the spikes of intensity will be affected most and so produce the higher difference.
That would be barely visible – so we need to use clip block to stretch the intensity until the difference peaks become visible. The clip has start clipping at zero and the clipping width very low, like 30-40. This means stretch the image intensity 0-30 into 0-256. That is basically it as a dust mask.
You can see on the flow above that I follow it with another blur and another clip. This is a preparation for further steps. By bluring it and then clipping the mask again we are expanding the area of those tiny dust white blobs so they would in fact overlap the actual dust.
In the next step we need to replace the dust mask with surrounding pixels.
On the flow above that is the top fork. We simply denoise the image and use Median (also blur can be used) which smooths out any spikes. The alpha block combine the top and bottom fork where we use the previously created mask as the alpha channel for our Median smoothed image.
So we get a transparent overlay where the intensity spikes are with the surrounding colors.
All we need to do now is to put that overlay on top of our input image. That is very easy, in Photo reactor we use Normal Blending block which simply layer our newly created blob overlay with the original image.
This is basically the whole, simple dust and scratches removal base from we can expand much more further.
One thing we would notice right away is that while we are removing the scratches they are still visible. After examining the image the reason become obvious: the whole image has grain, but the patches are just too smooth.
One trick to fix this seems a bit counterproductive but it works. We will add noise to our smoothed image. In this case I use Perlin noise where we can adjust the size and Soft light overlay.
When everything is setup right (especially the Clipping Width in the Clip blocks is crucial to pinpoint the dust but avoid any texture grain) you will not be able to spot where the scratches and dust were on the final image.
To download the finished flow:
Did we just create a million dollar Dust and Scratch algorithm? Well, at this moment it is time to go back and remember the first paragraph when I mentioned hair and foliage.
As soon as we try it on few different images, our million dollar algorithm idea crumbles down, like every other algorithm that tries to extract dust. Yes, our process works amazingly with some images but as expected fails with hair or any sharp fine texture that has light thin lines in it.
Looking at the mask on the Clip block we can see why. The hair tricks our subtract dust detection method.
No matter of tweaking will completely eliminate that – we can either remove the dust and scratches which will also mush the hair or we can settle on some middle compromise and tweak it such way so the hair won’t be much affected but also the scratches and dust removal will be less effective.
After some tweaking I came up with the best compromise using this algorithm. The dust is partially eliminated and the hair is less affected.
In future installments we will try to enhance the algorithm.