# Gaussian blur
Gaussian Blur (Gaussian Blur), also known as Gaussian smoothing, is a processing effect widely used in image processing software such as Adobe Photoshop, GIMP and Paint.NET to reduce image noise and detail level. The blur creates an image that looks like it is being viewed through a translucent screen, which is very different from the out-of-focus effect of a lens in bokeh or in normal lighting shadows. Gaussian smoothing is also used in the pre-processing phase of computer vision algorithms to enhance images at different scale sizes. From a mathematical point of view, the gaussian blur process of an image is the convolution of the image with normal distribution. Since normal distribution is also known as Gaussian distribution, this technique is called Gaussian blur. Convolving the image with the circular box blur will produce a more accurate out-of-focus image. Since the Fourier transform of gaussian function is another Gaussian function, Gaussian blur is a low pass filter for image.
Gaussian blur uses gaussian density function of normal distribution to calculate the transformation of each pixel in the image.
According to the one-dimensional Gaussian function, the two-dimensional Gaussian function can be derived:
Where r is the fuzzy radius, r^2 = x^2 + y^2, and σ is the standard deviation of the normal distribution. In two dimensions, the contour lines of the surface generated by this formula are concentric circles normally distributed from the center. The convolution matrix composed of pixels with non-zero distribution is transformed with the original image. The value of each pixel is a weighted average of the values of its neighbors. The value of the original pixel has the largest Gaussian distribution value, so it has the largest weight. As the distance between adjacent pixels from the original pixel gets further and further, its weight gets smaller and smaller. In this way, the edge effect is preserved better than other equalized fuzzy filters.
In fact, gaussian blur is very easy to implement on iOS. The CoreImage API has been available since iOS 5.0, and a number of filter implementations are available in the CoreImage. Framework library.
+ (UIImage *)coreBlurImage:(UIImage *)image withBlurNumber:(CGFloat)blur
{
CIContext *context = [CIContext contextWithOptions:nil];
CIImage *inputImage= [CIImage imageWithCGImage:image.CGImage];
/ / set the filter
CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
[filter setValue:inputImage forKey:kCIInputImageKey]; [filter setValue:@(blur) forKey: @"inputRadius"];
// Blur the image
CIImage *result=[filter valueForKey:kCIOutputImageKey];
CGImageRef outImage=[context createCGImage:result fromRect:[result extent]];
UIImage *blurImage=[UIImage imageWithCGImage:outImage];
CGImageRelease(outImage);
return blurImage;
}Copy the code
Gaussian blur can also be implemented on Android using the native API—–RenderScript, but requires Android API 17 or above, which is Android version 4.2.
/** * Gaussian blur algorithm with RenderScript *@param bitmap
* @return* /
public Bitmap blur(Bitmap bitmap){
//Let's create an empty bitmap with the same size of the bitmap we want to blur
Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
//Instantiate a new Renderscript
RenderScript rs = RenderScript.create(getApplicationContext());
//Create an Intrinsic Blur Script using the Renderscript
ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
//Create the Allocations (in/out) with the Renderscript and the in/out bitmaps
Allocation allIn = Allocation.createFromBitmap(rs, bitmap);
Allocation allOut = Allocation.createFromBitmap(rs, outBitmap);
//Set the radius of the blur: 0 < radius <= 25
blurScript.setRadius(20.0 f);
//Perform the Renderscript
blurScript.setInput(allIn);
blurScript.forEach(allOut);
//Copy the final bitmap created by the out Allocation to the outBitmap
allOut.copyTo(outBitmap);
//recycle the original bitmap
bitmap.recycle();
//After finishing everything, we destroy the Renderscript.
rs.destroy();
return outBitmap;
}Copy the code
The image framework we developed, CV4J, also provides a filter to achieve Gaussian blur.
GaussianBlurFilter filter = new GaussianBlurFilter();
filter.setSigma(10);
RxImageData.bitmap(bitmap).addFilter(filter).into(image2);Copy the code
As you can see, the Gaussian blur implemented by CV4J is the same as that implemented by RenderScript.
The GaussianBlurFilter code is as follows:
public class GaussianBlurFilter implements CommonFilter {
private float[] kernel;
private double sigma = 2;
ExecutorService mExecutor;
CompletionService<Void> service;
public GaussianBlurFilter(a) {
kernel = new float[0];
}
public void setSigma(double a) {
this.sigma = a;
}
@Override
public ImageProcessor filter(final ImageProcessor src){
final int width = src.getWidth();
final int height = src.getHeight();
final int size = width*height;
int dims = src.getChannels();
makeGaussianKernel(sigma, 0.002, (int)Math.min(width, height));
mExecutor = TaskUtils.newFixedThreadPool("cv4j",dims);
service = new ExecutorCompletionService<>(mExecutor);
// save result
for(int i=0; i<dims; i++) {
final int temp = i;
service.submit(new Callable<Void>() {
public Void call(a) throws Exception {
byte[] inPixels = src.toByte(temp);
byte[] temp = new byte[size];
blur(inPixels, temp, width, height); // H Gaussian
blur(temp, inPixels, height, width); // V Gaussain
return null; }}); }for (int i = 0; i < dims; i++) {
try {
service.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mExecutor.shutdown();
return src;
}
/**
* <p> here is 1D Gaussian , </p>
*
* @param inPixels
* @param outPixels
* @param width
* @param height
*/
private void blur(byte[] inPixels, byte[] outPixels, int width, int height)
{
int subCol = 0;
int index = 0, index2 = 0;
float sum = 0;
int k = kernel.length-1;
for(int row=0; row<height; row++) {
int c = 0;
index = row;
for(int col=0; col<width; col++) {
sum = 0;
for(int m = -k; m< kernel.length; m++) {
subCol = col + m;
if(subCol < 0 || subCol >= width) {
subCol = 0;
}
index2 = row * width + subCol;
c = inPixels[index2] & 0xff;
sum += c * kernel[Math.abs(m)];
}
outPixels[index] = (byte)Tools.clamp(sum); index += height; }}}public void makeGaussianKernel(final double sigma, final double accuracy, int maxRadius) {
int kRadius = (int)Math.ceil(sigma*Math.sqrt(-2*Math.log(accuracy)))+1;
if (maxRadius < 50) maxRadius = 50; // too small maxRadius would result in inaccurate sum.
if (kRadius > maxRadius) kRadius = maxRadius;
kernel = new float[kRadius];
for (int i=0; i<kRadius; i++) // Gaussian function
kernel[i] = (float)(Math.exp(-0.5*i*i/sigma/sigma));
double sum; // sum over all kernel elements for normalization
if (kRadius < maxRadius) {
sum = kernel[0];
for (int i=1; i<kRadius; i++)
sum += 2*kernel[i];
} else
sum = sigma * Math.sqrt(2*Math.PI);
for (int i=0; i<kRadius; i++) {
double v = (kernel[i]/sum);
kernel[i] = (float)v;
}
return; }}Copy the code
Two-dimensional convolution is often encountered in image processing. Most of the discrete forms of two-dimensional convolution are used in image processing.
The following are the various convolution effects implemented by CV4J.
Cv4j currently supports the following spatial convolution filters
filter | The name of the | role |
---|---|---|
ConvolutionHVFilter | convolution | Blur or reduce noise |
MinMaxFilter | Maximum and minimum filtering | To the noise |
SAPNoiseFilter | Salt and pepper noise | Increase the noise |
SharpFilter | sharpen | To enhance |
MedimaFilter | Median filtering | To the noise |
LaplasFilter | Laplace | To extract the edge |
FindEdgeFilter | Looking for the edge | Gradient extraction |
SobelFilter | The gradient | Obtain the gradient extraction of x and y directions |
VarianceFilter | Variance filter | High-pass filter |
MaerOperatorFilter | Omar operation | High-pass filter |
USMFilter | USM | To enhance |
Cv4j is an image processing library developed by Hyperyfish and me. It is still in its early version.
Functions realized so far:
This week, we made major changes to CV4J, optimizing the overall architecture. Spatial convolution (image enhancement, sharpening, blurring, etc.) is also added. Next, we will do analysis of binary images (corrosion, expansion, open and close operation, contour extraction, etc.)