Essentially, we created a matrix(equal in dimensions to that of the image) of random pixel values.
The numpy function empty_like() creates an empty matrix with the same dimensions as the matrix passed through, the image of the puppy in this case.
To create our noise filter we used cv2.
randn() to fill the empty matrix dst with random values within a normal distribution, where the mean is 0 and the standard deviation is 20 for each of the 3 color channels.
Once this matrix is filled, it produces this image:This is our filter.
From here, applying the filter to the image will require the openCV function addWeighted().
The two images can just be added together (img + noise), but this can produce some unwanted results.
The out-of-place looking blue and purple pixels in the image below are a result of the value constraints of RGB colors, specifically 0 to 255.
For this reason, we use the addWeighted() function and cut the pixel values in half, to prevent overflow of the pixel values, then add some brightness back into the image with the Gamma parameter (50 in this case).
Gaussian BlurringNow that we have some noise, let’s add some blurring to the image to see if it can smooth some of it out.
In essence, the Gaussian blurring algorithm will scan over each pixel of the image, and recalculate the pixel value based on the pixel values that surround it.
The area that is scanned around each pixel is called the kernel.
A larger kernel scans a larger amount of pixels that surround the center pixel.
Gaussian blurring doesn’t weigh each pixel equally, however.
The closer a pixel is to the center, the greater it affects the weighted average used to calculate the new center pixel value.
The image below demonstrates this function.
This method assumes pixels closest to the center pixel will be closest to the true value of that pixel, so they will influence the averaged value of the center pixel greater than pixels further away.
The size of the sigma of the function dictates how wide the curve should be inside the kernel, in the same way that that sigma, or standard deviation, of a Normal Distribution curve will dictate the width of the curve.
Since we are essentially operating in 3-D space here, the sigma here works both in the X and Y directions, so sigma-X and sigma-Y may have different values.
The openCV GaussianBlur() function takes in 3 parameters here: the original image, the kernel size, and the sigma for X and Y.
The kernel is the matrix that the algorithm uses to scan over the image, and in this case the kernel is 5×5, where the center pixel is the pixel that will be changed with respect to the surrounding 24.
The sigma dictates the width of the curve in the X and Y directions.
If one value is provided to the function, it will serve as sigma for both X and Y, but separate values may be passed as well (resulting in 4 arguments).
It is also important to note that if the sigma is 0, it will be auto-calculated from the kernel size.
Now, let’s see what the image actually looks like after all this kernel-sigma-nonsense!Kernel size=5Let’s change the kernel size and see what happens:Left: k=5.
Right: k=9.
As you can see, increasing the kernel size smooths out the image a little more, but the change is not drastic.
Let’s try an even larger kernel:Left: k=5.
Right: k=15.
With the kernel at 15×15 we see the remnants of the noise essentially eliminated, but we also lose a little bit of detail.
When implementing Gaussian blurring on your own images, it will take a bit of tweaking to find the right kernel size, especially when something like an edge detection algorithm is implemented.
Increasing the sigma will also have a similar effect on an image, but is largely dependent on the kernel size.
When in doubt, the sigma may be left at 0, but it doesn’t hurt to play around with the numbers a little.
TL;DRIncrease kernel size (GaussianBlur(pup_noise, (15, 15), 0)) to increase blurring effect; decrease it to decrease blur.
The sigma argument auto-calculates if it is set to 0.
If it’s not 0, increasing the sigma will increase blurring.
.. More details