Some content is organized from:

Http://blog.csdn.net/jianxiong8814/article/details/1562728

Http://www.cnblogs.com/pegasus/archive/2011/05/20/2052031.html

Http://blog.sina.com.cn/s/blog_640577ed0100yz8v.html

Http://blog.csdn.net/pearl333/article/details/8696307

Http://www.cnblogs.com/tornadomeet/tag/opencv/

Filter

Filtering is generally described by convolution or correlation, while linear filtering is generally described by convolution. They are very similar, but they are still different. Let's take a look at their specific differences based on the related and convolution calculation processes:

Convolution calculation steps:

1) the convolution core rotates 180 degrees clockwise around its core elements.

2) Move the central element of the convolution kernel so that it is located at the top of the pixels to be processed in the input image

3) In the rotated convolution kernel, multiply the pixel values of the input image as weights.

4) The sum of the result in step 3 is the output pixel corresponding to the input pixel.

Related calculation steps:

1) Move the central element of the correlation core so that it is located at the top of the pixels to be processed in the input image

2) use the pixel value of the input image as the weight and multiply it by the correlation kernel.

3) Add the results obtained in the preceding steps as output.

We can see that their main difference is that the convolution kernel must be rotated first during convolution calculation. The related cores do not need to be rotated during calculation.

For example, magic (3) = [8 1 6; 3 5 7; 4 9 2], after rotating 180 degrees, it becomes [2 9 4; 7 5 3; 6 1 8].

Gaussian filter

Gaussian filter is a linear smoothing filter that is suitable for eliminating Gaussian noise and is widely used in image processing noise reduction. In layman's terms, Gaussian filtering is a process of weighted average for the entire image. The value of each pixel is obtained by the weighted average of its own and other pixel values in the neighborhood.

The specific operation of Gaussian filter is to use a template (or convolution or mask) to scan each pixel in the image, use the weighted average gray value of pixels in the neighborhood determined by the template to replace the value of the central pixel in the template.

If a 3 × 3 Template is used, the formula G (x, y) = {f (x-1, Y-1) + f (x-1, Y + 1) is calculated as follows) + f (x + 1, Y-1) + f (x + 1, Y + 1) + [F (x-1, Y) + f (x, Y-1) + f (x + 1, Y) + f (x, y + 1)] * 2 + f (x, y) * 4}/16;

F (x, y) is the gray value of the (x, y) Point in the image, and g (x, y) is the value of the vertex after Gaussian filtering.

1. Gaussian distribution:

One-dimensional Gaussian distribution:

Two-dimensional Gaussian distribution:

2. Gaussian Kernel

In theory, Gaussian distribution has non-negative values in all the defined fields, which requires an infinitely large convolution kernel. In fact, you only need to take the value within 3 times the standard deviation around the mean, and remove the other part directly. For example, an integer Gaussian Kernel with a standard deviation of 1.0.

3. Application:

The degree to which the image is smoothed after Gaussian filtering depends on the standard deviation. Its output is the weighted average of the pixels in the field, and the pixel weight closer to the center is higher. Therefore, compared with mean filter, the smoothing effect is softer and the edge is better preserved.

Gaussian filter is used as a smoothing filter because it is a low-pass filter (passing the signal components below a certain frequency, and greatly suppressing the signal components above this frequency)

4. features:

1): the convolution between a Gaussian function and another Gaussian function is still a Gaussian function. The square of the standard deviation of a * B = C is the sum of the squares of the standard deviations of A and B, that is to say, the Gaussian function after convolution is wider, and the blur effect is more obvious (intuitively, the image will become more and more blurred after continuous Gaussian Fuzzy Operations ).

Two-dimensional Gaussian function convolution can be performed in two steps. First, the image and one-dimensional Gaussian function are convolution, and then the convolution result is perpendicular to the same dimension Gaussian function convolution. therefore, the calculation amount of two-dimensional Gaussian filter increases linearly with the width of the filter template instead of the square.

2): the Fourier transformation of the Gaussian function is still a Gaussian function. If the original Gaussian function is wider (the larger the standard deviation), the Gaussian function after the transformation will be narrower (the smaller the standard deviation ), that is to say, the wider the Gaussian function, the more obvious the effect of low-pass (high-impedance) filtering, the more unclear (more fuzzy) The details of the processed image ).

To perform Gaussian blur on a digital image, you must use a convolution that conforms to the Gaussian function distribution to check the digital image for convolution.

The size of the convolution kernel, the size of the final proportional coefficient to be determined.

The larger σ, the wider the Gaussian filter band and the better the smoothness.

A 5x5 Gaussian convolution kernel with a standard deviation of 1.4:

2 4 5 4 2

4 9 12 9 4

5 12 15 12 5

4 9 12 9 4

2 4 5 4 2

Last multiplied by the ratio of 1/115

Use Gaussian filter in opencv

The composite function is prototype:

void cvSmooth(const CvArr* src, CvArr* dst,intsmoothtype=CV_GAUSSIAN,int param1=3, int param2=0,double param3=0, doubleparam4=0 );

The first three parameters of the function are easy to understand. The last four parameters are analyzed below.

1) if param1 and param2 are specified, they represent the columns of the kernel function, that is, the width and height of the filter window;

2) param3: sigma value of Gaussian convolution

3) If you want to use an asymmetric Gaussian Kernel, param4 is introduced. The last two parameters represent the horizontal kernel and the vertical kernel dimension respectively;

4) if param3 is not given, the first two parameters param1 and param2 calculate Sigma. Here, it is based on the characteristics of Gaussian distribution (the probability of numerical values distributed in (μ-3 σ, μ + 3 σ) is 0.9974). If the kernel matrix is larger, the corresponding Sigma is larger. On the contrary, if Sigma is larger, the coverage of the core matrix is larger. Go to opencv and use the following formula for calculation (based on its source code ).

5) according to this formula, if param1 and param2 are 0 (or not given), then the size of the filter window is determined by Sigma represented by the last two parameters.

The separate Gaussian filter function is declared

void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT ) ;

Function: Perform Gaussian filter on the input image SRC and then output it using DST.

Parameters: SRC and DST are of course input and output images.

Ksize is the template size of Gaussian filter.

Sigmax and sigmay are the filter coefficients of Gaussian filter on the horizontal line and vertical line, respectively.

Bordertype is an edge extension point interpolation type.

The next step is to enter the gaussianblur function and trace its function code. After analysis, many other functions are called within the function. The called function hierarchy is shown in:

Here we do not need to go deep into the bottom layer for source code analysis. We only need to analyze the createseparablelinearfilter and getgaussiankernel functions.

From the hierarchical structure of function calls, we can see that to analyze the gaussianblur function, you must first analyze the called internal functions.

Therefore, the getgaussiankernel function is analyzed first.

Function: returns an array of ksize * 1. The array elements meet the Gaussian formula:

Only the alpha coefficient and Sigma parameter are unknown. The Sigma method is as follows:

If the input Sigma is not positive, the formula is: Sigma = 0.3 * (ksize-1) * 0.5-1) + 0.8.

If the input Sigma is positive, this input parameter Sigma is used.

At last, Alpha is the Normalization Coefficient, that is, the sum of the number of ksize calculated must be 1. Therefore, we only need to calculate the number of ksize, calculate the sum, and calculate the sum.

The source code and comments are as follows:

CV: mat CV: getgaussiankernel (int n, double Sigma, int ktype) {const int small_gaussian_size = 7; static const float interval [] [small_gaussian_size] ={{ 1.f }, {0.25f, 0.5f, 0.25f}, {0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f}, {0.03125f, medium, medium, 0.28125f, medium, 0.03375f, 0.03125f }}; const float * fixed_kernel = n % 2 = 1 & n <= small_gaussian_size & Sigma <= 0? Small_gaussian_tab [n> 1]: 0; cv_assert (ktype = cv_32f | ktype = cv_64f ); // ensure that the core element is a 32-bit floating point or 64-bit floating point mat kernel (n, 1, ktype); // create an array kernel of N * 1, a mat matrix includes a matrix header and a pointer to a matrix element float * cf = (float *) kernel. data; // defines the pointer. Cf points to the single-precision floating point data of the kernel double * Cd = (double *) kernel. data; // define the pointer CD pointing to kernerl Double Precision Floating Point Data double sigmax = Sigma> 0? Sigma: (n-1) * 0.5-1) * 0.3 + 0.8; // when Sigma is less than 0, Sigma is obtained using the formula (only related to N) double scale2x =-0.5/(sigmax * sigmax); // use double sum = 0; int I; for (I = 0; I <N; I ++) {Double X = I-(n-1) * 0.5; // if you calculate your own core, you can use the formula exp (scale2x * x * X) for calculation, otherwise, we will use the fixed coefficient core double T = fixed_kernel? (Double) fixed_kernel [I]: STD: exp (scale2x * x * X); If (ktype = cv_32f) {CF [I] = (float) T; // sum + = CF [I] In the CF array when the precision requirement is set; // used for normalization} else {CD [I] = T; // sum + = CD [I];} sum = 1. /SUM; // sum of the elements in the normalized kernel: 1for (I = 0; I <n; I ++) {If (ktype = cv_32f) cf [I] = (float) (CF [I] * sum); // The normalized Single-precision kernel element elsecd [I] * = sum; // normalized dual-precision kernel element} return kernel; // returns an array of N * 1. Its elements are either single-precision or double-precision and conform to Gaussian distribution}

The following analysis function is createseparablelinearfilter.

Function: create an image filter engine class, which mainly processes the original and target image data formats and the synthesis of filter cores.

The source code and comments are as follows:

CV: PTR <CV: filterengine> CV: creategaussianfilter (INT type, size ksize, double sigma1, double sigma2, int bordertype) {int depth = cv_mat_depth (type ); // obtain the depth of the array element if (sigma2 <= 0) sigma2 = sigma1; // when the 3rd parameters are not correct, take the value of the same as that of the second parameter // automatic detection of kernel size from sigmaif (ksize. width <= 0 & sigma1> 0) // when the width of the filter core is not correct, the width of the filter core must be re-calculated by ksize. width = cvround (sigma1 * (depth = cv_8u? 3: 4) * 2 + 1) | 1; if (ksize. height <= 0 & sigma2> 0) ksize. Height = cvround (sigma2 * (depth = cv_8u? 3: 4) * 2 + 1) | 1; cv_assert (ksize. width> 0 & ksize. width % 2 = 1 & ksize. height> 0 & ksize. height % 2 = 1); // ensure that the kernel width and core height are positive and odd sigma1 = STD: max (sigma1, 0 .); // The minimum sigma value is 0sigma2 = STD: max (sigma2, 0 .); mat kx = getgaussiankernel (ksize. width, sigma1, STD: max (depth, cv_32f); // obtain the one-dimensional Gaussian Kernel mat Ky in the X direction; If (ksize. height = ksize. width & STD: ABS (sigma1-sigma2) <dbl_epsilon) Ky = kx; // If the width and height of the core are equal and the Sigma difference is small, the Gaussian Kernel in the Y direction is the same as that in the X direction, reducing the calculation workload. elseky = getgaussiankernel (ksize. height, sigma2, STD: max (depth, cv_32f); // otherwise, return createseparablelinearfilter (type, type, kx, Ky, point (-1,-1), 0, bordertype); // returns a 2-dimensional image filter engine}

Finally, let's look at the real Gaussian filter function gaussianblur: function: filter the input image _ SRC to get the output image _ DST. The size of the filter core is ksize. The filter parameters are calculated by sigma1 and sigma2, the extended edge mode is bordertype. its source code and comments are as follows:

Void CV: gaussianblur (inputarray _ SRC, outputarray _ DST, size ksize, double sigma1, double sigma2, int bordertype) {mat src = _ SRC. getmat (); // create a matrix SRC using _ SRC's matrix header information _ DST. create (SRC. size (), SRC. type (); // construct a target matrix with the same size as the input matrix mat DST = _ DST. getmat (); // create a target matrix if (ksize. width = 1 & ksize. height = 1) {SRC. copyto (DST); // if the size of the filter core is 1, the filter core does not need to be filtered at all. The output matrix is exactly the same as the input matrix return;} If (bordertype! = Border_constant) // when the edge extension is not a constant extension {If (SRC. rows = 1) ksize. height = 1; // If the input matrix is a row vector, the height of the filter core is 1if (SRC. cols = 1) ksize. width = 1; // If the input matrix is a column vector, the width of the filter core is forced to 1} PTR <filterengine> F = creategaussianfilter (SRC. type (), ksize, sigma1, sigma2, bordertype); F-> apply (SRC, DST); // call the engine function, filter the input matrix SRC Gaussian into the output matrix DST}

Implemented Gaussian filter

The source code and comments are as follows:

# Include "highgui. H "# include" CV. H "# pragma comment (linker,"/subsystem: Windows/entry: maincrtstartup ") void gaussianfilter (uchar * data, int width, int height) {int I, j, index, SUM; int templates [9] = {1, 2, 1, 2, 4, 2, 1, 2, 1 }; // template value sum = height * width * sizeof (uchar); // size of memory occupied by the image uchar * tmpdata = (uchar *) malloc (SUM ); memcpy (char *) tmpdata, (char *) data, sum); for (I = 1; I