opencv——均值/中值濾波器去噪


實驗內容及實驗原理:

1.用均值濾波器(即鄰域平均法)去除圖像中的噪聲;

2.用中值濾波器去除圖像中的噪聲

3.比較兩種方法的處理結果

實驗步驟:

用原始圖像lena.bmp或cameraman.bmp加產生的3%椒鹽噪聲圖像合成一幅有噪聲的圖像並顯示;

1.用均值濾波器去除圖像中的噪聲(選3x3窗口):以當前像素點為中心,求窗口內所有灰度值的和,以其平均值作為中心像素新的灰度值

2. 用中值濾波器去除圖像中的噪聲(選3x3窗口做中值濾波);以當前像素點為中心,求窗口中所有像素點的灰度值的中值,以中值作為中心像素點的值

3.將兩種處理方法的結果與原圖比較,注意兩種處理方法對邊緣的影響。

添加椒鹽噪聲

以3%的幾率產生隨機為0/255的灰度值覆蓋原來的灰度值

   for (int i = 0; i <src->height; i++){
        for (int j = 0; j <src->width; j++){
            CvScalar s = cvGet2D(src, i,j);
            srand(seed++);
            if (rand() % 100 <3){//3%的幾率覆蓋
                srand(seed++);
                s.val[0]= rand() % 2 * 255;//隨機是0還是255
            }
            cvSet2D(dst,i, j, s);
        }
    }

添加后:

均值濾波

計算當前像素周圍的九個像素點的灰度值和,以其平均值作為當前像素的灰度值。如果是邊緣的像素點就求有限的幾個像素灰度值的平均值

for (int i = 0;i < dst->height; i++){
     for (int j = 0; j < dst->width; j++){
         CvScalar s =cvGet2D(dst, i, j);
         double sum =0;//存放窗口中所有像素點灰度值的和
         int num =0;//記錄窗口中像素的個數,因為邊界上可能不是9個像素
         //求3x3的和
         for (int k = -1; k <= 1; k++)
              for (int m = -1; m <= 1; m++)
                   if (i + k>= 0 && i + k <= 255 && j + m >= 0 && j + m<= 255){
                       CvScalar temp =cvGet2D(dst, i+k, j+m);
                       sum += temp.val[0];
                       num++;
                   }
         s.val[0] = sum/num;
         cvSet2D(dst_sp, i, j, s);
     }
}


中值濾波

獲取當前像素位置周圍的九個像素灰度值,排序選擇中間值作為新的灰度值。如果是邊界的像素點就只選擇有限的幾個灰度值的中值

for (int i = 0;i < dst->height; i++){
     for (int j = 0; j < dst->width; j++){
         CvScalar s =cvGet2D(dst, i, j);
         double val[9]= {0},mid=0;//分別為存放窗口中所有灰度值的數組和中值
         int num =0;//記錄實際窗口中有幾個像素點
         //遍歷當前像素點為中心的3X3窗口
         for (int k = -1; k <= 1; k++)
              for (int m = -1; m <= 1; m++)
                   if (i + k>= 0 && i + k <= 255 && j + m >= 0 && j + m<= 255){//在圖像上,沒有超出邊界
                       CvScalar temp =cvGet2D(dst, i + k, j + m);
                       val[num++]= temp.val[0];
                   }
         //冒泡排序,從大到小
         for (int k = 0; k < 9; k++){
              for (int m = 0; m < 8-k; m++){
                   if (val[m]< val[m + 1]){
                       double temp =val[m];
                       val[m] = val[m + 1];
                       val[m + 1] = temp;
                   }
              }
         }
         s.val[0] =  val[num/2];//求中值
         cvSet2D(dst_sp2, i, j, s);
     }
}

源碼:

// opencv1.cpp: 定義控制台應用程序的入口點。
//

#include "stdafx.h"
#include<iostream>  
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <cv.h>
#include <cxcore.h>
#include <cvaux.h>
#include <stdlib.h>
#include <imgproc.hpp>
#include <time.h>

using namespace cv;

int main()
{
	IplImage *src;
	src = cvLoadImage("lena.bmp", 1);//原圖
	IplImage *dst = cvCreateImage(cvSize(src->width, src->height), IPL_DEPTH_8U, 1);


	std::cout << "添加椒鹽噪聲" << std::endl;
	int seed = 1;
	for (int i = 0; i < src->height; i++)
	{
		for (int j = 0; j < src->width; j++)
		{
			CvScalar s = cvGet2D(src, i, j);
			srand(seed++);
			if (rand() % 100 < 3)
			{
				srand(seed++);
				s.val[0] = rand() % 2 * 255;
			}
			cvSet2D(dst, i, j, s);
		}
	}
	cvNamedWindow("Image1", 1);//創建窗口
	cvShowImage("Image1", dst);//顯示圖像

	IplImage *dst_sp = cvCreateImage(cvSize(dst->width, dst->height), IPL_DEPTH_8U, 1);
	std::cout << "均值濾波" << std::endl;
	for (int i = 0; i < dst->height; i++)
	{
		for (int j = 0; j < dst->width; j++)
		{
			CvScalar s = cvGet2D(dst, i, j);
			double sum = 0;
			int num = 0;
			//求3x3的和
			for (int k = -1; k <= 1; k++)
				for (int m = -1; m <= 1; m++)
					if (i + k >= 0 && i + k <= 255 && j + m >= 0 && j + m <= 255)
					{
						CvScalar temp = cvGet2D(dst, i+k, j+m);
						sum += temp.val[0];
						num++;
					}

			s.val[0] = sum/num;
			cvSet2D(dst_sp, i, j, s);
		}
	}
	cvNamedWindow("Image2", 1);//創建窗口
	cvShowImage("Image2", dst_sp);//顯示圖像

	IplImage *dst_sp2 = cvCreateImage(cvSize(dst->width, dst->height), IPL_DEPTH_8U, 1);
	std::cout << "中值濾波" << std::endl;
	for (int i = 0; i < dst->height; i++)
	{
		for (int j = 0; j < dst->width; j++)
		{
			CvScalar s = cvGet2D(dst, i, j);
			double val[9] = {0},mid=0;
			int num = 0;
			for (int k = -1; k <= 1; k++)
				for (int m = -1; m <= 1; m++)
					if (i + k >= 0 && i + k <= 255 && j + m >= 0 && j + m <= 255)
					{
						CvScalar temp = cvGet2D(dst, i + k, j + m);
						val[num++]= temp.val[0];
					}
			//排序,從大到小
			for (int k = 0; k < 9; k++)
			{
				for (int m = 0; m < 8-k; m++)
				{
					if (val[m] < val[m + 1])
					{
						double temp = val[m];
						val[m] = val[m + 1];
						val[m + 1] = temp;
					}
				}
			}
			s.val[0] =  val[num/2];
			cvSet2D(dst_sp2, i, j, s);
		}
	}
	cvNamedWindow("Image3", 1);//創建窗口
	cvShowImage("Image3", dst_sp2);//顯示圖像
	cvWaitKey(0); //等待按鍵
	cvReleaseImage(&dst_sp2); //釋放圖像
	cvReleaseImage(&dst_sp); //釋放圖像

	cvReleaseImage(&dst); //釋放圖像
}

原圖:(原來是bmp格式的,但是不能上傳,改成png格式了,分辨率都是256X256的)



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM