OpenCV learning: basic image manipulation (5): Smooth and Blur

Common filters

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, that is, the current pixel (x, y) to be processed, select a template, which is composed of several neighboring pixels, and find the value of all pixels in the template The average value, and then assign the average value to the current pixel (x, y), which can be expressed by the following formula:

f(x,y) = \frac {1}{m\times n}\sum_{i \in [-n,n] }\sum_{j \in [-m,m]}f(i,j)

Features: Mean filtering itself has inherent defects, that is, it can't protect the image details well . It also destroys the details of the image while denoising the image, so that the image becomes blurred and the noise cannot be removed well.

Median filter

Median filtering is a non-linear signal processing technology that can effectively suppress noise based on ranking statistical theory. The basic principle of median filtering is to use the value of a point in a digital image or digital sequence with the value of each point in a neighborhood of that point. Instead of the median value, the surrounding pixel values ​​are close to the true value, thereby eliminating isolated noise points.

f(x,y) = med(f(x-m,y-n),...,f(x,y),...,f(x+m,y+n))

Features: Median filtering has a good filtering effect on impulse noise, especially while filtering noise, it can protect the edge of the signal and prevent it from being blurred. These excellent characteristics are not available in linear filtering methods.

Gaussian filtering

Two-dimensional Gaussian distribution

Gaussian filtering is a linear smoothing filter, which is suitable for eliminating Gaussian noise and is widely used in the noise reduction process of image processing. In layman's terms, Gaussian filtering is the process of weighted averaging the entire image. The value of each pixel is obtained by weighted averaging of itself and other pixel values ​​in the neighborhood. The weighted weight comes from the two-dimensional Gaussian distribution generated according to the input parameters.

Features: Most of the image noise is Gaussian noise, so Gaussian filters are also widely used. Gaussian filtering is a linear smoothing filter, which is suitable for eliminating Gaussian noise and is widely used in image denoising.

Bilateral filtering

Bilateral filter is a non-linear filtering method, which combines the spatial proximity of the image and the similarity of the pixel value. It also considers the spatial information and gray-scale similarity to achieve edge preservation and denoising. purpose.

Spatial domain S

Pixel range domain (range domain R)

In general, when the pixel difference is greater than the threshold (that is, there is an edge), the filtering is divided into two parts, without affecting the edge to perform Gaussian filtering. Structured as the following formula:

Features: Bilateral filter, as its name implies, has one more Gaussian variance than Gaussian filter \delta_d. It is a Gaussian filter function based on spatial distribution. So near the edge, pixels farther away will not affect the pixel value on the edge too much. Ensure the preservation of pixel values ​​near the edge. However, because too much high-frequency information is stored, the bilateral filter cannot cleanly filter out the high-frequency noise in the color image, and can only filter the low-frequency information well. Bilateral filtering is often used in applications such as beautiful dermabrasion.

API introduction

  • Mean filtering
  • blur(src, dst, Size(5, 5));
    //源图片,生成图片,卷积核大小
    //卷积核大小长选用正方形的奇数边长,也可选用奇数长和宽的矩形,但不常用可根据实际情况选定
  • Median filter
  • medianBlur(src, dst, ksize / 2 * 2 + 1);
    //源图片,生成图片,卷积核大小(默认为方形)
  • Gaussian filtering
  • GaussianBlur(src, dst, Size(wkernelSize / 2 * 2 + 1, hkernelSize / 2 * 2 + 1), wsigma, hsigma);
    //源图片,生成图片,核大小(长、宽),长上分布的标准差,宽上分布的标准差
    //同样可以根据需要改变卷积核的长宽,及对应维度上的分布
    
  • Bilateral filtering
  • bilateralFilter(src, dst, kernelSize / 2 * 2 + 1, sigmaColor, sigmaSpace);
    //源图片,生成图片,卷积核大小,高斯分布标准差,保护边缘阈值

    The lower the protection edge threshold is set, the more details are retained, and the larger the setting, the higher the blur degree.

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);
}

Guess you like

Origin blog.csdn.net/fan1102958151/article/details/106980216