OpenCV learning: basic image manipulation: Smooth and Blur

Posted by madspoihur on Sat, 27 Jun 2020 09:54:11 +0200

Common filter

Mean filtering

Mean filtering is also called linear filtering, and its main method is neighborhood averaging. The basic principle of linear filtering is to replace each pixel value in the original image with the mean value, i.e. the current pixel point (x, y) to be processed, select a template, which is composed of several neighboring pixels, calculate the mean value of all pixels in the template, and then assign the mean value to the current pixel point (x, y), which can be expressed by the following formula:

Features: mean filtering itself has its inherent defects, that is, it can not protect image details well, while image denoising, it also destroys the details of the image, so that the image becomes fuzzy and can not remove noise points well.

median filtering

Median filter is a kind of nonlinear signal processing technology which can effectively suppress noise based on sorting statistics theory. The basic principle of median filter is to replace the value of a point in a digital image or digital sequence with the median value of each point in a neighborhood of the point, so that the surrounding pixel value is close to the real value, so as to eliminate isolated noise points.

Features: median filter has a good filtering effect on impulse noise, especially when filtering noise, it can protect the edge of signal from being blurred. These excellent characteristics are not possessed by linear filtering method.

Gauss filter

Two dimensional Gaussian distribution

Gaussian filter is a kind of linear smoothing filter, which is suitable for eliminating Gaussian noise and widely used in image processing. Generally speaking, Gaussian filtering is the process of weighted average of the whole image. The value of each pixel is obtained by weighted average of itself and other pixel values in the neighborhood. The weighted weight comes from the binary Gaussian distribution generated according to the input parameters.

Features: most of the image noise is Gaussian noise, so Gaussian filter is widely used. Gaussian filter is a kind of linear smoothing filter, which is suitable for eliminating Gaussian noise and widely used in image denoising.

Bilateral filtering

Bilateral filter is a non-linear filtering method, which combines the spatial proximity of image and the similarity of pixel value. At the same time, considering the spatial information and gray similarity, the purpose of edge preserving denoising is achieved.

spatial domain S

range domain R

In general, when the pixel difference is greater than the threshold value (i.e. there are edges), the filtering is divided into two parts, without affecting the edges to carry out Gaussian filtering respectively. Constructed as follows:

Features: as the name implies, the bilateral filter has one more Gaussian variance than the Gaussian filter, which is a Gaussian filtering function based on spatial distribution, so the pixels far away from the edge will not affect the pixel value on the edge, so it can ensure the preservation of the pixel value near the edge. However, due to the storage of too much high-frequency information, for the high-frequency noise in the color image, the double-sided filter can not filter out cleanly, only can filter the low-frequency information better. Bilateral filtering is often used in applications such as beautiful skin grinding.

API introduction

  • Mean filtering
  • blur(src, dst, Size(5, 5));
    //Source image, generated image, convolution kernel size
    //The size and length of convolution kernel can be chosen from the odd side length of square or the odd length and width of rectangle, but it is not often chosen according to the actual situation
  • median filtering
  • medianBlur(src, dst, ksize / 2 * 2 + 1);
    //Source image, generated image, convolution kernel size (default is square)
  • Gauss filter
  • GaussianBlur(src, dst, Size(wkernelSize / 2 * 2 + 1, hkernelSize / 2 * 2 + 1), wsigma, hsigma);
    //Source image, generated image, core size (length, width), standard deviation of distribution over length, standard deviation of distribution over width
    //The length and width of convolution kernel and the distribution of corresponding dimensions can also be changed as required
    
  • Bilateral filtering
  • bilateralFilter(src, dst, kernelSize / 2 * 2 + 1, sigmaColor, sigmaSpace);
    //Source image, generated image, convolution kernel size, standard deviation of Gaussian distribution, protection edge threshold

    The lower the threshold value of protection edge is, the more details are retained, and the greater the difference is, the higher the degree of ambiguity is.

Code practice

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;

typedef struct _imgPair {
	Mat* src;
	Mat* dst;
	void* Param;
	string winName;
}ImgPair;

typedef struct _gaussianParam {
	int kernelSize;
	int sigma;
}GaussianParam;

typedef struct _bilateralParam {
	int kernelSize;
	int sigmaColor;
	int sigmaSpace;
}BilateralParam;

void on_gaussiankernelBar(int ksize, void* userdata)
{
	ImgPair* pImgPair = (ImgPair*)userdata;
	GaussianParam* gPair = (GaussianParam*)(pImgPair->Param);
	gPair->kernelSize = ksize;

	GaussianBlur(*(pImgPair->src), *(pImgPair->dst), Size(gPair->kernelSize / 2 * 2 + 1, gPair->kernelSize / 2 * 2 + 1), gPair->sigma, gPair->sigma);
	imshow(pImgPair->winName, *(pImgPair->dst));
}


void on_gaussianSigmaBar(int sigma, void* userdata)
{
	ImgPair* pImgPair = (ImgPair*)userdata;
	GaussianParam* gPair = (GaussianParam*)(pImgPair->Param);
	gPair->sigma = double(sigma);

	GaussianBlur(*(pImgPair->src), *(pImgPair->dst), Size(gPair->kernelSize / 2 * 2 + 1, gPair->kernelSize / 2 * 2 + 1), gPair->sigma, gPair->sigma);
	imshow(pImgPair->winName, *(pImgPair->dst));
}




void on_medianSigmaBar(int ksize, void* userdata)
{
	ImgPair* pImgPair = (ImgPair*)userdata;

	medianBlur(*(pImgPair->src), *(pImgPair->dst), ksize / 2 * 2 + 1);
	imshow(pImgPair->winName, *(pImgPair->dst));

}


void on_bilateralDBar(int ksize, void* userdata)
{
	ImgPair* pImgPair = (ImgPair*)userdata;
	BilateralParam* param = (BilateralParam*)(pImgPair->Param);
	bilateralFilter(*(pImgPair->src), *(pImgPair->dst), ksize / 2 * 2 + 1, param->sigmaColor, param->sigmaSpace);
	param->kernelSize = ksize;
	imshow(pImgPair->winName, *(pImgPair->dst));

}



void on_bilateralSigmaSpaceBar(int sigmaSpace, void* userdata)
{
	ImgPair* pImgPair = (ImgPair*)userdata;
	BilateralParam* param = (BilateralParam*)(pImgPair->Param);
	bilateralFilter(*(pImgPair->src), *(pImgPair->dst), param->kernelSize / 2 * 2 + 1, param->sigmaColor, sigmaSpace);
	param->sigmaSpace = sigmaSpace;
	imshow(pImgPair->winName, *(pImgPair->dst));
}

void on_bilateralSigmaColorBar(int sigmaColor, void* userdata)
{
	ImgPair* pImgPair = (ImgPair*)userdata;
	BilateralParam* param = (BilateralParam*)(pImgPair->Param);
	bilateralFilter(*(pImgPair->src), *(pImgPair->dst), param->kernelSize / 2 * 2 + 1, sigmaColor, param->sigmaSpace);
	param->sigmaColor = sigmaColor;
	imshow(pImgPair->winName, *(pImgPair->dst));
}


int main()
{
	Mat src = imread("4.jpg");

	namedWindow("src");
	imshow("src", src);


	/*-------GaussianBlur-----------*/
	Mat GaussianBlurImg;
	namedWindow("GaussianBlurImg");
	GaussianParam gaussianParam = { 5, 1.0 };
	GaussianBlur(src, GaussianBlurImg, Size(5, 5), 1, 1);
	GaussianParam gparam = { 5, 1.0 };
	ImgPair  gaussianPair = { &src, &GaussianBlurImg, &gparam,  "GaussianBlurImg" };

	imshow("GaussianBlurImg", GaussianBlurImg);
	createTrackbar("kernelsize", "GaussianBlurImg", &(gparam.kernelSize), 30, on_gaussiankernelBar, &gaussianPair);
	createTrackbar("sigma", "GaussianBlurImg", &(gparam.kernelSize), 10, on_gaussianSigmaBar, &gaussianPair);

	/*-------medianBlur-----------*/
	Mat MedianBlurImg;
	int kernelSize = 5;
	ImgPair  medianPair = { &src, &MedianBlurImg, nullptr,  "MedianBlurImg" };
	medianBlur(src, MedianBlurImg, 5);
	imshow("MedianBlurImg", MedianBlurImg);
	createTrackbar("kernelsize", "MedianBlurImg", &(kernelSize), 30, on_medianSigmaBar, &medianPair);


	/*---Bilateral-----------------*/
	Mat BilateralFilterImg;
	bilateralFilter(src, BilateralFilterImg, 5, 2, 2);
	BilateralParam bparam = { 5,1,1 };
	ImgPair  bilateralPair = { &src, &BilateralFilterImg, &bparam,  "BilateralFilterImg" };
	imshow("BilateralFilterImg", BilateralFilterImg);
	createTrackbar("kernelsize", "BilateralFilterImg", &(bparam.kernelSize), 30, on_bilateralDBar, &bilateralPair);
	createTrackbar("sigmaspace", "BilateralFilterImg", &(bparam.sigmaSpace), 30, on_bilateralSigmaSpaceBar, &bilateralPair);
	createTrackbar("sigmacolor", "BilateralFilterImg", &(bparam.sigmaColor), 30, on_bilateralSigmaColorBar, &bilateralPair);
	waitKey(0);
}