一般的なフィルター
平均フィルタリング
平均フィルタリングは線形フィルタリングとも呼ばれ、その主な方法は近傍平均です。線形フィルタリングの基本原理は、元の画像の各ピクセル値を平均値、つまり処理する現在のピクセル(x、y)に置き換え、いくつかの隣接するピクセルで構成されるテンプレートを選択し、テンプレート内のすべてのピクセルの値を見つけることです。次に、平均値を現在のピクセル(x、y)に割り当てます。これは、次の式で表すことができます。
特徴:平均フィルタリング自体に固有の欠陥があります。つまり、画像の詳細を適切に保護できません。また、画像のノイズを除去しながら画像の詳細を破壊するため、画像がぼやけ、ノイズポイントを適切に除去できません。
メディアンフィルター
メディアンフィルタリングは、ランキング統計理論に基づいてノイズを効果的に抑制することができる非線形信号処理技術です。メディアンフィルタリングの基本原理は、デジタル画像またはデジタルシーケンス内のポイントの値を、そのポイントの近傍にある各ポイントの値とともに使用することです。中央値の代わりに、周囲のピクセル値が真の値に近いため、孤立したノイズポイントが排除されます。
特徴:メディアンフィルタリングは、インパルスノイズに対して優れたフィルタリング効果を発揮します。特にノイズをフィルタリングする場合は、信号のエッジを保護し、ぼやけを防ぐことができます。これらの優れた特性は、線形フィルタリング方法では利用できません。
ガウスフィルタリング
二次元ガウス分布
ガウスフィルタリングは線形平滑化フィルタであり、ガウスノイズの除去に適しており、画像処理のノイズ低減プロセスで広く使用されています。素人の言葉で言えば、ガウスフィルタリングは画像全体の加重平均プロセスです。各ピクセルの値は、それ自体と近隣の他のピクセル値の加重平均によって取得されます。加重加重は、入力パラメータに従って生成された2次元ガウス分布から取得されます。
特徴:画像ノイズのほとんどはガウスノイズであるため、ガウスフィルターも広く使用されています。ガウスフィルタリングは線形平滑化フィルタであり、ガウスノイズの除去に適しており、画像のノイズ除去に広く使用されています。
バイラテラルフィルタリング
バイラテラルフィルターは、画像の空間的近接性とピクセル値の類似性を組み合わせた非線形フィルタリング方法です。また、空間情報とグレースケールの類似性を考慮して、エッジの保存とノイズ除去を実現します。目的。
空間ドメインS
ピクセル範囲ドメイン(範囲ドメインR)
一般に、ピクセルの差がしきい値よりも大きい場合(つまり、エッジがある場合)、ガウスフィルタリングを実行するためにエッジに影響を与えることなく、フィルタリングは2つの部分に分割されます。次の式のように構成されています。
特徴:バイラテラルフィルターは、その名前が示すように、ガウスフィルターよりもガウス分散が1つ多くなります。これは、空間分布に基づくガウスフィルター関数です。したがって、エッジに近い場合、遠いピクセルはエッジのピクセル値にあまり影響しません。エッジ近くのピクセル値が確実に保持されるようにします。ただし、保存する高周波情報が多すぎるため、バイラテラルフィルターではカラー画像の高周波ノイズをきれいに除去できず、低周波情報しかうまくフィルタリングできません。バイラテラルフィルタリングは、美しいダーマブレーションなどのアプリケーションでよく使用されます。
APIの紹介
- 平均フィルタリング
-
blur(src, dst, Size(5, 5)); //源图片,生成图片,卷积核大小 //卷积核大小长选用正方形的奇数边长,也可选用奇数长和宽的矩形,但不常用可根据实际情况选定
- メディアンフィルター
-
medianBlur(src, dst, ksize / 2 * 2 + 1); //源图片,生成图片,卷积核大小(默认为方形)
- ガウスフィルタリング
-
GaussianBlur(src, dst, Size(wkernelSize / 2 * 2 + 1, hkernelSize / 2 * 2 + 1), wsigma, hsigma); //源图片,生成图片,核大小(长、宽),长上分布的标准差,宽上分布的标准差 //同样可以根据需要改变卷积核的长宽,及对应维度上的分布
- バイラテラルフィルタリング
-
bilateralFilter(src, dst, kernelSize / 2 * 2 + 1, sigmaColor, sigmaSpace); //源图片,生成图片,卷积核大小,高斯分布标准差,保护边缘阈值
保護エッジのしきい値を低く設定すると、より多くの詳細が保持され、設定を大きくすると、ぼかしの度合いが高くなります。
コードの練習
#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);
}