中值濾波
一、原理
(1)目的:去除圖像上的尖銳噪聲,平滑圖像。
(2)原理:中值濾波屬於非線性濾波,是基於排序統計理論的一種能有效抑制噪聲的非線性信號處理技術,中值濾波的基本原理是把數字圖像或數字序列中一點的值用該點的一個鄰域中各點值的中值代替,讓周圍的像素值接近的真實值,從而消除孤立的噪聲點。其中,圖1中mid表示矩陣中的中值,median表示獲取中值的函數名,中括號的內容是待選取中值的參數。
圖1 核心步驟,求中值
二、步驟
(1)判斷卷積核大小是否為奇數
(2)邊界復制填充
(3)跳過邊界,對中間區域濾波
(4)通過排序獲得中值
(5)將中值寫入目標圖像
(6)顯示圖像
三、偽代碼
輸入:原圖src,卷積核大小n(取中值的范圍)
輸出:結果圖dst
Void MedianFilter(Mat src,Mat& dst, int n)
{
If(卷積核n為偶數)
報異常,退出
邊緣處理
for(循環處理像素點){
if(判斷圖像通道數){
根據通道數,以n個像素為單位存入一個大小為n的數組
求數組的中值
將中值賦值到輸出圖片中
}
}
}
三、特點
優點:中值濾波法對消除椒鹽噪聲非常有效;
缺點:條紋中心分析方法中作用不大,效率不如均值濾波;
四、源碼
// 中值濾波
void MedianFilter(cv::Mat &srcImg, cv::Mat& dstImg, int n)
{
// 判斷原圖像是否為空
if (srcImg.empty()) {
return;
}
// 判斷核的大小是否為奇數
CV_Assert(n % 2 == 1);
// 清空目標圖像,對原圖像進行邊界填充
Mat tmp;
dstImg = dstImg.zeros(srcImg.size(), srcImg.type());
int *kernel = new int[n*n];
copyMakeBorder(srcImg, tmp, n / 2, n / 2, n / 2, n / 2, BORDER_REPLICATE);
for (int i = n / 2; i < srcImg.rows + n / 2; i++) //對填充后的圖像從有圖像區域開始濾波
{
for (int j = n / 2; j < srcImg.cols + n / 2; j++)
{
for (int c = 0; c < 3; c++)
{
// 將核大小的圖像填入數組
for (int m = 0; m < n*n; m++) {
if (tmp.channels() == 1) {
kernel[m] = tmp.ptr<uchar>(i - n / 2 + m / n, j - n / 2 + m % n)[c];
}
else if (tmp.channels() == 3) {
kernel[m] = tmp.ptr<Vec3b>(i - n / 2 + m / n, j - n / 2 + m % n)->val[c];
}
else
{
delete[]kernel;
return;
}
}
// 排序
Sort(kernel, n*n);
// 將中值寫入目標圖像
if (tmp.channels() == 1) {
dstImg.ptr<uchar>(i - n / 2, j - n / 2)[c] = kernel[(n*n) / 2];
}
else if (tmp.channels() == 3) {
dstImg.ptr<Vec3b>(i - n / 2, j - n / 2)->val[c] = kernel[(n*n) / 2];
}
}
}
}
delete[]kernel;
}
五、結果圖
卷積核為3*3
卷積核為5*5