C++實(shí)現(xiàn)中值濾波的示例代碼
為了加深對(duì)中值濾波算法的理解以及方便以后更好的復(fù)習(xí),我將該算法的一些重點(diǎn)細(xì)節(jié)和實(shí)現(xiàn)過(guò)程踩過(guò)的坑記錄下來(lái)。
中值濾波器是一種非線性濾波器,或者叫統(tǒng)計(jì)排序?yàn)V波器。
適用對(duì)象:帶椒鹽噪聲的圖像
由于椒鹽噪聲像素值與原圖像素值沒(méi)有關(guān)聯(lián),隨機(jī)性較大,因此使用中值濾波可有效濾掉噪聲。
中值濾波需要對(duì)像素值進(jìn)行排序,因此首先寫(xiě)一個(gè)冒泡排序算法。
冒泡排序?qū)崿F(xiàn):
為提高效率加入標(biāo)志位flag,當(dāng)?shù)趇次尋找最大值時(shí),如果相鄰兩個(gè)數(shù)均未發(fā)生互換,此時(shí)flag位為false,即說(shuō)明此時(shí)數(shù)組已經(jīng)按照遞增排列,可提前終止。此處應(yīng)該注意flag=false所在位置,因?yàn)樾枰WC第i次尋找最大值過(guò)程中,遍歷到所有未參與排列的數(shù)據(jù),所以flag=false應(yīng)該放在循環(huán)條件for(int j=0; j<len-1-i; j++)的外部。
void bubble(std::vector<int> &arr, int len)
{
bool flag = true;
for (int i = 0; i < len-1; i++)
{
while (flag)
{
flag = false;
for (int j = 0; j < len - i - 1; j++)
{
if (arr[j + 1] < arr[j])
{
flag = true; //只要發(fā)生一次交換就繼續(xù)判斷
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
}
}
中值濾波的實(shí)現(xiàn):
需要注意的主要問(wèn)題:
為了能夠遍歷到原圖的邊界,需要對(duì)原圖進(jìn)行邊界擴(kuò)充,擴(kuò)充長(zhǎng)度為(窗口的長(zhǎng)度-1)/ 2。
注意利用窗口對(duì)擴(kuò)充后的圖像遍歷時(shí),起始的位置不是0,而是擴(kuò)充的長(zhǎng)度,因?yàn)檫@時(shí)對(duì)應(yīng)的才是原圖的第一個(gè)像素點(diǎn),同理結(jié)束的位置也是原圖的最后一個(gè)像素點(diǎn)。
另外為了方便將窗口內(nèi)對(duì)應(yīng)的像素存到容器中,可以寫(xiě)兩個(gè)循環(huán),循環(huán)長(zhǎng)度為窗口的長(zhǎng)度與寬度,依次將像素值存入容器中。
最后對(duì)容器內(nèi)的像素按照遞增排列后,取中值賦給目標(biāo)矩陣相應(yīng)的位置,而此時(shí)的位置也應(yīng)該用i-h,對(duì)應(yīng)擴(kuò)充前的位置。
經(jīng)實(shí)踐證明我寫(xiě)的這兩個(gè)算法可有效使用。
void medianFilter(cv::Mat& src, cv::Mat& dst, cv::Size width)
{
//判斷窗口是否為奇數(shù)
if (width.width % 2 == 0 || width.height % 2 == 0)
{
std::cout << "輸入窗口大小應(yīng)該為奇數(shù),請(qǐng)重新輸入" << endl;
exit(-1);
}
else
{
//計(jì)算邊界擴(kuò)充長(zhǎng)度
int h = (width.height - 1) / 2;
int w = (width.width - 1) / 2;
//對(duì)原圖邊界擴(kuò)充
cv::Mat src_border;
cv::copyMakeBorder(src, src_border, h, h, w, w, cv::BORDER_REFLECT_101);
for (int i = h; i < src.rows + h; i++)
{
for (int j = w; j < src.cols + w; j++)
{
//定義容器存放窗口對(duì)應(yīng)的像素
std::vector <int> v;
for (int ii = i - h; ii <= i + h; ii++)
{
for (int jj = j - w; jj <= j + w; jj++)
{
v.push_back(src_border.at<uchar>(ii, jj));
}
}
//對(duì)容器內(nèi)存放的像素排序
int len = width.area();
bubble(v, len);
//將中值賦給目標(biāo)圖像對(duì)應(yīng)位置
dst.at<uchar>(i-h, j-w) = v[(len - 1) / 2];
}
}
}
}
到此這篇關(guān)于C++實(shí)現(xiàn)中值濾波的示例代碼的文章就介紹到這了,更多相關(guān)C++ 中值濾波內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之單鏈表與雙鏈表的增刪改查操作實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)中單鏈表與雙鏈表的增刪改查操作的實(shí)現(xiàn),相信大家如果搞懂了本文內(nèi)容,應(yīng)對(duì)復(fù)雜的鏈表類(lèi)的題也就能慢慢鉆研了2022-07-07
C語(yǔ)言?huà)呃自敿?xì)代碼分步實(shí)現(xiàn)流程
掃雷是電腦上很經(jīng)典的游戲,特意去網(wǎng)上玩了一會(huì),幾次調(diào)試之后,發(fā)現(xiàn)這個(gè)比三子棋要復(fù)雜一些,尤其是空白展開(kāi)算法上和堵截玩家有的一拼,與實(shí)際游戲差別較大,不能使用光標(biāo),下面來(lái)詳解每一步分析2022-02-02
C++編程中將引用類(lèi)型作為函數(shù)參數(shù)的方法指南
這篇文章主要介紹了C++編程中將引用類(lèi)型作為函數(shù)參數(shù)的方法指南,是C++入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09

