图像处理为什么要去噪

2019-04-25 19:40:03 lyd1995 阅读数 1613

一、实验内容及原理

1、均值滤波

具体内容:利用 OpenCV 对灰度图像像素进行操作,分别利用算术均值滤波器、几何均值滤波器、谐波和逆谐波均值滤波器进行图像去噪。模板大小为 5*5。 (注:请分别为图像添加高斯噪声、胡椒噪声、盐噪声和椒盐噪声,并观察 滤波效果)

(1)算术均值滤波器

f^(x,y)=1mng(s,t)\hat {f}(x,y)=\frac {1}{mn}\sum g(s,t)

(2)几何均值滤波器

f^(x,y)=[g(s,t)]1mn\hat {f}(x,y)=[\prod g(s,t)]^{\frac {1}{mn}}

注:这个累乘很容易会超过int或者long的表示范围,建议每n个灰度一起乘,再开根号

(3)谐波均值滤波器

f^(x,y)=mn1g(s,t)\hat {f}(x,y)=\frac {mn}{\frac {1}{\sum g(s,t)}}

(4)逆谐波均值滤波器

f^(x,y)=g(s,t)Q+1g(s,t)Q\hat {f}(x,y)=\frac {\sum g(s,t)^{Q+1}}{\sum g(s,t)^Q}

2、中值滤波

具体内容:利用 OpenCV 对灰度图像像素进行操作,分别利用555*5999*9 尺寸的模板对图像进行中值滤波。(注:请分别为图像添加胡椒噪声、盐噪声和 椒盐噪声,并观察滤波效果)

3、自适应均值滤波。

具体内容:利用 OpenCV 对灰度图像像素进行操作,设计自适应局部降 低噪声滤波器去噪算法。模板大小 7*7(对比该算法的效果和均值滤波器的效果)

f^(x,y)=g(s,t)ση2σL2[g(s,t)mL]\hat {f}(x,y)=g(s,t)-\frac {\sigma_\eta^2}{\sigma_L^2}[g(s,t)-m_L]

4、自适应中值滤波

具体内容:利用 OpenCV 对灰度图像像素进行操作,设计自适应中值滤波算 法对椒盐图像进行去噪。模板大小 7*7(对比中值滤波器的效果)
在这里插入图片描述
在这里插入图片描述

5、彩色图像均值滤波

具体内容:利用 OpenCV 对彩色图像 RGB 三个通道的像素进行操作,利用算 术均值滤波器和几何均值滤波器进行彩色图像去噪。模板大小为 5*5

二、实验代码

实验环境:
(1)OpenCV3.4.3
(2)Ubuntu16.04
(3)VS Code
(4)C++

#include <iostream>
#include <opencv2/opencv.hpp>
#include <string>
#include <vector>
#include <math.h>
#include <cmath>
#include <algorithm>

class Exp4{
public:
    // 1 初始化:彩色图片、灰度图片、加噪图片
    Exp4(std::vector<std::string> path){
        noise_name.push_back("高斯噪声");
        noise_name.push_back("胡椒噪声");
        noise_name.push_back("盐噪声");
        noise_name.push_back("椒盐噪声");

        filter_name.push_back("算术均值滤波");
        filter_name.push_back("几何均值滤波");
        filter_name.push_back("谐波均值滤波");
        filter_name.push_back("逆谐波均值滤波");
        filter_name.push_back("中值滤波");
        filter_name.push_back("自适应均值滤波");
        filter_name.push_back("自适应中值滤波");

        pic_color.push_back("灰度");
        pic_color.push_back("彩色");
        for(int i = 0; i < path.size(); i++){
            // 读取彩色图片、灰度图片
            original_color_image.push_back(cv::imread(path[i]));
            original_gray_image.push_back(color2Gray(original_color_image[i]));

            // 彩色图片加噪
            noise_color_image.push_back(addNoise(original_color_image[i], 0, 0));
            noise_color_image.push_back(addNoise(original_color_image[i], 1, 0));
            noise_color_image.push_back(addNoise(original_color_image[i], 2, 0));
            noise_color_image.push_back(addNoise(original_color_image[i], 3, 0));

            // 灰度图片加噪
            noise_gray_image.push_back(addNoise(original_gray_image[i], 0));
            noise_gray_image.push_back(addNoise(original_gray_image[i], 1));
            noise_gray_image.push_back(addNoise(original_gray_image[i], 2));
            noise_gray_image.push_back(addNoise(original_gray_image[i], 3));
        }
    }
    // 1.1 彩色图像转灰度图像
    cv::Mat color2Gray(cv::Mat src_image){
        //创建与原图同类型和同大小的矩阵
	    cv::Mat gray_image(src_image.rows, src_image.cols, CV_8UC1);
        if(src_image.channels()!=1){
            for(int i = 0; i < src_image.rows; i++)
                for(int j = 0; j < src_image.cols; j++)
                    gray_image.at<uchar>(i, j) = (src_image.at<cv::Vec3b>(i, j)[0] + src_image.at<cv::Vec3b>(i, j)[1] + src_image.at<cv::Vec3b>(i, j)[2]) / 3;
        }
        else
            gray_image = src_image.clone();
        return gray_image;
    }
    // 2 灰度图像滤波
    void grayFiltering(int id, int select, int filter_size=5, double Q=1){
        int size = filter_size;
        if(select == 6 || select == 5)
            size = 7;
        int m = size/2;
        int n=size*size;
        cv::Mat image = cv::Mat::zeros(noise_gray_image[id].size(), noise_gray_image[id].type());

        for(int i=m; i < noise_gray_image[id].rows - m; i++)
            for(int j=m; j < noise_gray_image[id].cols - m; j++){ 
                cv::Mat sub_matrix = noise_gray_image[id](cv::Rect(j - m, i - m, size, size));
                if(select == 0)
                    image.at<uchar>(i,j) = arithmeticMeanValueConvolution(sub_matrix);
                else if(select == 1)
                    image.at<uchar>(i,j) = geometryMeanValueConvolution(sub_matrix);
                else if(select == 2)
                    image.at<uchar>(i,j) = harmonicMeanValueConvolution(sub_matrix);
                else if(select == 3)
                    image.at<uchar>(i,j) = inverseHarmonicMeanValueConvolution(sub_matrix);
                else if(select == 4)
                    image.at<uchar>(i,j) = middleValueConvolution(sub_matrix);
                else if(select == 5)
                    image.at<uchar>(i,j) = selfAdaptionMeanValueConvolution(sub_matrix, image.at<uchar>(i,j));
                else if(select == 6)
                    image.at<uchar>(i,j) = selfAdaptionMiddleValueConvolution(sub_matrix);
            }
        noise_gray_image_process.push_back(image);
    }

    // 2.1 算术均值
    int arithmeticMeanValueConvolution(cv::Mat& image_block, int size=5){
        cv::Mat c_template(size, size, CV_8UC1, 1);
        int n=size*size;
        return c_template.dot(image_block) / n + 0.5;
    }

    // 2.2 几何平均
    int geometryMeanValueConvolution(cv::Mat& image_block, int size=5){
        std::vector<double> product(5,1);
        double n = 1.0 / double(size * size);
        for(int k1 = 0; k1 < size; k1++){
            double temp=1;
            for(int k2 = 0; k2 < size; k2++){
                temp = temp * ((image_block.at<uchar>(k1,k2) > 0) ? double(image_block.at<uchar>(k1,k2)) : 1.0);
                product[k1] = pow(temp, n);
            }
        }
        return int(product[0] * product[1] * product[2] * product[3] * product[4]);
    }

    // 2.3 谐波均值
    int harmonicMeanValueConvolution(cv::Mat& image_block, int size=5){
        std::vector<double> product(5,1);
        double sum=0;
        double n = double(size * size);
        for(int k1 = 0; k1 < size; k1++){
            for(int k2 = 0; k2 < size; k2++){
                double temp;
                if(image_block.at<uchar>(k1,k2))
                    temp = 1.0 / double(image_block.at<uchar>(k1,k2));
                else
                    temp=0;
                sum += temp;
            }
        }
        return int(n / sum);
    }

    // 2.4 逆谐波均值
    int inverseHarmonicMeanValueConvolution(cv::Mat& image_block, int size=5, double Q=1){
        double sum1=0, sum2=0;
        for(int k1 = 0; k1 < size; k1++){
            for(int k2 = 0; k2 < size; k2++){
                sum1 += pow(double(image_block.at<uchar>(k1, k2)), Q);
                sum2 += pow(double(image_block.at<uchar>(k1, k2)), Q+1);
            }
        }
        return int(sum2 / sum1);
    }

    // 3.1 中值滤波
    int middleValueConvolution(cv::Mat& image_block, int size=5){
        int min = 0, k = 0, pos = size*size/2;
        std::vector<int> nums;
        for(int k1 = 0; k1 < size; k1++)
            for(int k2 = 0; k2 < size; k2++)
                nums.push_back(image_block.at<uchar>(k1,k2));
        int middle = findMiddleNum(nums, 0, size*size - 1, pos);
        return middle;
    }

    // 3.2.1 快速查找中位数
    int findMiddleNum(std::vector<int>& nums, int begin, int end, int n){
        int i = partition(nums, begin, end);
        if(i == n)
            return nums[i];
        else if(i > n)
            return findMiddleNum(nums, begin, i-1, n);
        else
            return findMiddleNum(nums, i+1, end, n);
    }

    // 3.2.2 交换
    void exchange(std::vector<int>& nums, int a,int b){
        int c = nums[a];
        nums[a] = nums[b];
        nums[b] = c;
        return;
    }

    // 3.2.2 快速查找中位数
    int partition(std::vector<int>& nums, int begin, int end){
        int i = begin, j = end + 1;
        int x = nums[begin];
        while (true) {
            while (nums[++i] < x) {// 向右扫描
                if (i == end)
                    break;
            }
            while (nums[--j] > x) {// 向左扫描
                if (j == begin)
                    break;
            }
            if (i >= j) // 指针相遇,切分位置确定
                break;
            exchange(nums, i, j);// 交换左右逆序元素
        }
        // 运行到最后:i指向从左往右第一个大于x的元素,j指向从右往左第一个小于x的元素。
        exchange(nums, begin, j);// 将切分元素放在切分位置
        return j;
    }

    // 4、自适应均值滤波
    int selfAdaptionMeanValueConvolution(cv::Mat& image_block, int value, int size=7, int sigma_n=3000){
        int center = size/2;
        int mean = computerMeanValue(image_block);
        int sigma = computerVariance(image_block, mean);
        //std::cout<<sigma<<"\n";
        double rate = double(sigma_n)/double(sigma);
        if(rate > 1.0)
            rate = 1;
        int ans = value - rate * (value - mean);
        return ans;
    }

    // 4.1 计算图像块的平均值
    int computerMeanValue(cv::Mat& image_block, int size=7){
        int sum = 0,n = size*size;
        for(int k1 = 0; k1 < size; k1++)
            for(int k2 = 0; k2 < size; k2++)
                sum += image_block.at<uchar>(k1,k2);
        return (sum / n);
    }

    // 4.2 计算图像块的方差
    int computerVariance(cv::Mat& image_block, int mean, int size=7){
        int sum = 0,n = size*size;
        for(int k1 = 0; k1 < size; k1++)
            for(int k2 = 0; k2 < size; k2++)
                sum += pow((image_block.at<uchar>(k1,k2) - mean), 2);
        return (sum / n);
    }

    // 5、自适应中值滤波
    int selfAdaptionMiddleValueConvolution(cv::Mat& image_, int size=3, int sizemax=7){
        int center = sizemax/2;
        int zxy = image_.at<uchar>(center, center);
        int m = size/2;
        cv::Mat image_block = image_(cv::Rect(center - m, center - m, size, size)).clone();
        std::vector<int> nums;
        for(int k1 = 0; k1 < size; k1++)
            for(int k2 = 0; k2 < size; k2++)
                nums.push_back(image_block.at<uchar>(k1,k2));

        sort(nums.begin(), nums.end());
        int zmin = nums[0], zmax = nums[nums.size()-1], zmid = nums[(size*size)/2];
        int A1 = (zmid - zmin), A2 = (zmid - zmax);
        if(A1 > 0 && A2 < 0){
            int B1 = (zxy - zmin), B2 = (zxy - zmax);
            if(B1 > 0 && B2 < 0)
                return zxy;
            else
                return zmid; 
        }
        else{
            if(size < sizemax)
                return selfAdaptionMiddleValueConvolution(image_,  size+2);
            else
                return zmid;
        }      
    }

     // 6、彩色图像滤波器
    void colorFiltering(int id, int select, int filter_size=5, int Q=1){
        int size = filter_size;
        if(select == 6)
            size = 7;
        int m = size/2;
        int n=size*size;
        cv::Mat image = cv::Mat::zeros(noise_color_image[id].rows, noise_color_image[id].cols, noise_color_image[id].type()); 
        std::vector<cv::Mat> channels;
        cv::split(noise_color_image[id], channels);

        for(int i=m; i < noise_color_image[id].rows - m; i++)
            for(int j=m; j < noise_color_image[id].cols - m; j++)
                for(int k=0;k < 3;k++){
                    cv::Mat sub_matrix = channels.at(k)(cv::Rect(j - m, i - m, size, size));
                    if(select == 0)
                        image.at<cv::Vec3b>(i,j)[k] = arithmeticMeanValueConvolution(sub_matrix, size);
                    else if(select == 1)
                        image.at<cv::Vec3b>(i,j)[k] = geometryMeanValueConvolution(sub_matrix, size);
                    else if(select == 2)
                        image.at<cv::Vec3b>(i,j)[k] = harmonicMeanValueConvolution(sub_matrix, size);
                    else if(select == 3)
                        image.at<cv::Vec3b>(i,j)[k] = inverseHarmonicMeanValueConvolution(sub_matrix, size, Q);
                    else if(select == 4)
                        image.at<cv::Vec3b>(i,j)[k] = middleValueConvolution(sub_matrix, size);
                    else if(select == 5)
                        image.at<cv::Vec3b>(i,j)[k] = selfAdaptionMeanValueConvolution(sub_matrix, image.at<cv::Vec3b>(i,j)[k]);
                    else if(select == 6)
                        image.at<cv::Vec3b>(i,j)[k] = selfAdaptionMiddleValueConvolution(sub_matrix);
                }
        noise_color_image_process.push_back(image);
    }

    // 7、运行代码
    void test_gray_filter(int num){
        int id = num;
        for(int i = 0; i < noise_name.size(); i++){
            grayFiltering(i, id);
            std::cout<< pic_color[0] << "-----" <<noise_name[i]<<"-----"<<filter_name[id]<<": 运行完毕!!!!  \n";
        }

        cv::imshow(filter_name[id] + "----准备就绪,可以开始!", original_color_image[0]);
        cv::waitKey(0);

        // 3 显示灰度滤波结果
        for(int i = 0; i < noise_name.size(); i++){
            cv::imshow(noise_name[i], noise_gray_image[i]);
            cv::waitKey(0);
            cv::imshow(noise_name[i] + "-----" + filter_name[id] + "-----" + pic_color[0], noise_gray_image_process[id * 4 + i]);
            cv::waitKey(0);
        }
        std::cout<<"\n \n";
        cv::destroyAllWindows();
    }

    void test_color_filter(int num){
        int id = num;
        for(int i = 0; i < noise_name.size(); i++){
            colorFiltering(i, id);
            std::cout<< pic_color[1] << "-----" <<noise_name[i]<<"-----"<<filter_name[id]<<": 运行完毕!!!!  \n";
        }

        cv::imshow(filter_name[id] + "----准备就绪,可以开始!", original_color_image[0]);
        cv::waitKey(0);

        // 3 显示灰度滤波结果
        for(int i = 0; i < noise_name.size(); i++){
            cv::imshow(noise_name[i], noise_color_image[i]);
            cv::waitKey(0);
            cv::imshow(noise_name[i] + "-----" + filter_name[id] + "-----" + pic_color[0], noise_color_image_process[id * 4 + i]);
            cv::waitKey(0);
        }
        std::cout<<"\n \n";
        cv::destroyAllWindows();
    }
private:
    std::vector<std::string> noise_name;
    std::vector<std::string> filter_name;
    std::vector<std::string> pic_color;

    std::vector<cv::Mat> original_color_image;
    std::vector<cv::Mat> original_gray_image;

    std::vector<cv::Mat>  noise_color_image;
    std::vector<cv::Mat>  noise_gray_image;

    std::vector<cv::Mat>  noise_color_image_process;
    std::vector<cv::Mat>  noise_gray_image_process;

    /************************** 添加噪声***************************************/

    cv::Mat addNoise(cv::Mat src_image, int select=0, int gray=1, double SNR=0.99, double mean=0.0, double sigma=10.0, int k=2){
        cv::Mat outImage;
        cv::Mat image;
        if(gray){
            image = color2Gray(src_image);
            if(select==0)
                outImage = addGaussNoise(image, mean, sigma, k);
            else if(select==1)
                outImage = addPepperSaltNoise(image, SNR, select - 1);
            else if(select==2)
                outImage = addPepperSaltNoise(image, SNR, select - 1);
            else if(select==3)
                outImage = addPepperSaltNoise(image, SNR, select - 1);
        }
        else{
            std::vector<cv::Mat> channels, ch;
            cv::Mat image = src_image.clone();
            cv::split(src_image, channels);
            cv::split(image, ch);
            for(int k=0; k < 3; k++){
                if(select==0)
                    ch.at(k) = addGaussNoise(channels.at(k), mean, sigma, k);
                else if(select==1)
                    ch.at(k) = addPepperSaltNoise(channels.at(k), SNR, select - 1);
                else if(select==2)
                    ch.at(k) = addPepperSaltNoise(channels.at(k), SNR, select - 1);
                else if(select==3)
                    ch.at(k) = addPepperSaltNoise(channels.at(k), SNR, select - 1);
            }
            cv::merge(ch, outImage);
        }
        return outImage;
    }

    // 1、添加高斯噪声
    cv::Mat addGaussNoise(cv::Mat src_image, double mean=0.0, double sigma=100.0, int k=2, int gray=1){
        cv::Mat outImage;
        cv::Mat image = src_image.clone();
        //cv::Mat image = color2Gray(src_image);
        outImage.create(image.rows,image.cols,image.type());
        int PixcelMax = 255, PixcelMin = 0;
        for(int x=0;x<image.rows;x++){
            for(int y=0;y<image.cols;y++){
                double temp = image.at<uchar>(x, y) + k * generateGaussianNoise(mean,sigma);
                if(temp>PixcelMax)
                    temp=PixcelMax;
                else if(temp<PixcelMin)
                    temp=PixcelMin;
                outImage.at<uchar>(x, y) = temp;
            }
        }
        return outImage;
    }

    // 1.1、生成高斯噪声(其实就是服从高斯分布的随机数)
    double generateGaussianNoise(double mean, double sigma){
        static double V1, V2, S;
        static int phase = 0;
        double X;
        double U1,U2;
        if ( phase == 0 ) {
            do {
                U1 = (double)rand() / RAND_MAX;
                U2 = (double)rand() / RAND_MAX;

                V1 = 2 * U1 - 1;
                V2 = 2 * U2 - 1;
                S = V1 * V1 + V2 * V2;
            } while(S >= 1 || S == 0);

            X = V1 * sqrt(-2 * log(S) / S);
        } 
        else{
            X = V2 * sqrt(-2 * log(S) / S);
        }
        phase = 1 - phase;
        return mean + sigma * X;
    }

    // 2、添加椒盐噪声(根据图像的信噪比,添加椒盐噪声)根据选择,可以添加:盐噪声(又称白噪声,白色点255)、胡椒噪声(黑色点)、椒盐噪声。
    cv::Mat addPepperSaltNoise(cv::Mat src_image, double SNR=0.9, int select=0, int gray=1){
        cv::Mat outImage;
        cv::Mat image = src_image.clone();
        //outImage.create(image.rows,image.cols,image.type());
        int SP = image.rows * image.cols;
        int NP = SP*(1-SNR);
        outImage = image.clone();
        // 噪声点的总个数 与 信噪比有关
        for(int i=0; i<NP; i++) {
            // 随机选取图像上的点
            int x = (int)(double(rand())*1.0/RAND_MAX* (double)image.rows);
            int y = (int)(double(rand())*1.0/RAND_MAX* (double)image.cols);
            // 峰值(255)和零值(0)出现的概率相同
            if(select==0)
               outImage.at<uchar>(x,y) = 0;
            else if(select==1)
                outImage.at<uchar>(x,y) = 255;
            else{
                int r = rand()%2;
                outImage.at<uchar>(x,y) = (r > 0) ? 255 : 0;
            }
        }
        return outImage;
    }
};

int main(){
    std::vector<std::string> path;
    path.push_back("/home/lyd/image_process/pic/lena.jpg");
    Exp4 a(path);
    //a.run();
    for(int i=0; i < 7; i++)
        a.test_gray_filter(i);
    for(int i=0; i < 7; i++)
        a.test_color_filter(i);
    return 1;
}

三、实验结果

四类噪声下的灰度图像:
在这里插入图片描述
1、 均值滤波

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2、 中值滤波
在这里插入图片描述
3、 自适应均值滤波
在这里插入图片描述
4、 自适应中值滤波
在这里插入图片描述

5、 彩色图像均值滤波
在这里插入图片描述
在这里插入图片描述

2017-12-16 17:36:21 u012123989 阅读数 19860

python数字图像处理-图像噪声与去噪算法

figure_1.png

图像噪声

椒盐噪声

概述: 椒盐噪声(salt & pepper noise)是数字图像的一个常见噪声,所谓椒盐,椒就是黑,盐就是白,椒盐噪声就是在图像上随机出现黑色白色的像素。椒盐噪声是一种因为信号脉冲强度引起的噪声,产生该噪声的算法也比较简单。

给一副数字图像加上椒盐噪声的步骤如下:

  1. 指定信噪比 SNR (其取值范围在[0, 1]之间)
  2. 计算总像素数目 SP, 得到要加噪的像素数目 NP = SP * (1-SNR)
  3. 随机获取要加噪的每个像素位置P(i, j)
  4. 指定像素值为255或者0。
  5. 重复3,4两个步骤完成所有像素的NP个像素
  6. 输出加噪以后的图像

高斯噪声

概述: 加性高斯白噪声(Additive white Gaussian noise,AWGN)在通信领域中指的是一种功率谱函数是常数(即白噪声), 且幅度服从高斯分布的噪声信号. 这类噪声通常来自感光元件, 且无法避免.

去噪算法

中值滤波

概述: 中值滤波是一种非线性空间滤波器, 它的响应基于图像滤波器包围的图像区域中像素的统计排序, 然后由统计排序结果的值代替中心像素的值. 中值滤波器将其像素邻域内的灰度中值代替代替该像素的值. 中值滤波器的使用非常普遍, 这是因为对于一定类型的随机噪声, 它提供了一种优秀的去噪能力, 比小尺寸的均值滤波器模糊程度明显要低. 中值滤波器对处理脉冲噪声(也称椒盐噪声)非常有效, 因为该噪声是以黑白点叠加在图像上面的.

与中值滤波相似的还有最大值滤波器和最小值滤波器.

均值滤波

概述: 均值滤波器的输出是包含在滤波掩模领域内像素的简单平均值. 均值滤波器最常用的目的就是减噪. 然而, 图像边缘也是由图像灰度尖锐变化带来的特性, 所以均值滤波还是存在不希望的边缘模糊负面效应.

均值滤波还有一个重要应用, 为了对感兴趣的图像得出一个粗略描述而模糊一幅图像. 这样, 那些较小物体的强度与背景揉合在一起了, 较大物体变得像斑点而易于检测.掩模的大小由即将融入背景中的物体尺寸决定.

代码

https://github.com/wangshub/python-image-process

2020-02-17 14:40:30 ab136681 阅读数 192

频率域去噪

为了节约读者时间,首先说明这一篇不会有任何代码只有个人的心得体会理由如下:

  1. 代码过于简单,像书上这样的例子这样的
  2. 自己并没有这类周期噪声的例子,也不想去手动去添加,因为这样的还原效果太好。像自欺欺人

频率域去噪的假设
所有的噪声都有一种模式,或者说一种规律。这样也就知道了为什么会分带阻,陷波了。当然这里的最佳陷波则是对噪声规律的一种最佳近似。

频率域去噪的原理
这里就需要解释傅立叶变换或者是其他正交基对应的变换了,因为在空间域下对于噪声的认识不清晰,但是通过变换后在频率域下噪声的规律易于发现。

带阻滤波器

如果你看过上面的说明,则很清楚可以认识这是处理类似圆圈这样的噪声,顾名思义就是噪声的模式像一条圆圈丝带

带通滤波器

这个没什么好说的只是为了提取噪声图像的即只保留噪声频率,对应于空间域即提取噪声图像

陷波滤波器

噪声模式为某区域(太难形容),然后处理这些区域所对应的频率

最佳陷波滤波器

即添加一个系数w,使得 f = g - wn 最小,其中:
f 为还原图
g 为待处理图
w 为系数
n 为噪声模式

即wn等价于找一个最佳效果的噪声模式使得最终处理的效果最好,读者如果这里不明白,可以结合后面的维纳滤波和最小二乘滤波看。

上一篇:数字图像处理python实现-图像去噪之空间域自适应滤波

2019-03-03 15:42:00 weixin_34301307 阅读数 322

图像去噪定义

图像去噪是指减少数字图像中噪声的过程称为图像去噪。现实中的数字图像在数字化和传输过程中常受到成像设备与外部环境噪声干扰等影响,称为含噪图像或噪声图像。

噪声分类

按照噪声组成来分

   f(x,y)表示给定原始图象,g(x,y)表示图象信号,n(x,y)表示噪声。

(1)加性噪声,此类噪声与输入图象信号无关,含噪图象可表示为f(x,y)=g(x,y)+n(x,y),信道噪声及光导摄像管的摄像机扫描图象时产生的噪声就属这类噪声;典型的加性噪声有高斯噪声,

(2)乘性噪声,此类噪声与图象信号有关,含噪图象可表示为f(x,y)=g(x,y)+n(x,y)g(x,y),飞点扫描器扫描图象时的噪声,电视图象中的相关噪声,胶片中的颗粒噪声就属于此类噪声;

(3)量化噪声,此类噪声与输入图象信号无关,是量化过程存在量化误差,再反映到接收端而产生。

按照噪声密度分布:

(1)高斯噪声:指噪声服从高斯分布,即某个强度的噪声点个数最多,离这个强度越远噪声点个数越少,且这个规律服从高斯分布。高斯噪声是一种加性噪声,即噪声直接加到原图像上,因此可以用线性滤波器滤除。

(2)椒盐噪声(脉冲噪声):类似把椒盐撒在图像上,因此得名,是一种在图像上出现很多白点或黑点的噪声,如电视里的雪花噪声等。椒盐噪声可以认为是一种逻辑噪声,用线性滤波器滤除的结果不好,一般采用中值滤波器滤波可以得到较好的结果。

(3)均匀噪声:是指功率谱密度(信号功率在频域的分布状况)在整个频域内是常数的噪声。 所有频率具有相同能量密度的随机噪声称为白噪声。

(4)瑞利噪声:噪声分布为瑞利分布。

(5)指数噪声:噪声分布为指数分布。

(6)伽马噪声:噪声分布为瑞利分布。

(以下是对图像加入高斯,椒盐等噪声的python代码) 

 1 # -*- coding: utf-8 -*-
 2 """
 3 Created on Sat Mar  2 14:00:30 2019
 4 
 5 @author: Administrator
 6 """
 7 
 8 '''
 9 图像添加噪声,去除噪声
10 '''
11 import matplotlib.pyplot as plt 
12 import numpy as np
13 from skimage.util import random_noise
14 from PIL import Image 
15 
16 img = plt.imread('F:/python编程/自己的博客园代码/picture_process/example.jpg')
17 
18 fig = plt.figure(figsize = (8.0,6.0))
19 ax1 = fig.add_subplot(2,3,1)
20 ##  show the original picture
21 ax1.imshow(img)
22 plt.title('original_picture')
23 
24 ## gray_picture
25 gravity= np.array([0.299,0.587,0.114])
26 #red*0.299+green*0.587+blue*0.114
27 img_gravity=np.dot(img,gravity)
28 ax2 = fig.add_subplot(2,3,2)
29 ##  show the gray_picture
30 ax2.imshow(img_gravity,cmap='gray')
31 plt.title('gray_picture')
32 
33 
34 img_gaussian =  random_noise(img, mode='gaussian', seed=100, clip=True)
35 ax3 = fig.add_subplot(2,3,3)
36 ax3.imshow(img_gaussian)
37 plt.title('add_gaussian')
38 
39 
40 img_salt =  random_noise(img, mode='salt', seed=100, clip=True)
41 ax4 = fig.add_subplot(2,3,4)
42 ax4.imshow(img_salt)
43 plt.title('add_salt')
44 
45 
46 img_pepper =  random_noise(img, mode='pepper', seed=100, clip=True)
47 ax4 = fig.add_subplot(2,3,5)
48 ax4.imshow(img_pepper)
49 plt.title('add_pepper')
50 
51 
52 img_sp =  random_noise(img, mode='s&p', seed=100, clip=True)
53 ax4 = fig.add_subplot(2,3,6)
54 ax4.imshow(img_sp)
55 plt.title('add_sp')
View Code

去噪方法

中值滤波:

  中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值。

高斯滤波:

  高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。

均值滤波:

  均值滤波也称为线性滤波,其采用的主要方法为邻域平均法。线性滤波的基本原理是用均值代替原图像中的各个像素值,即对待处理的当前像素点(x,y),选择一个模板,该模板由其近邻的若干像素组成,求模板中所有像素的均值,再把该均值赋予当前像素点(x,y),作为处理后图像在该点上的灰度g(x,y),即g(x,y)=1/m ∑f(x,y) m为该模板中包含当前像素在内的像素总个数。

维纳滤波:

  维纳滤波(wiener filtering) 一种基于最小均方误差准则、对平稳过程的最优估计器。这种滤波器的输出与期望输出之间的均方误差为最小,因此,它是一个最佳滤波系统。它可用于提取被平稳噪声所污染的信号。

傅里叶滤波简称fft,是通过对图片信号在频域里进行滤波,从而达到去噪效果。

 (以下是几种滤波方法(不一定全)在python代码中的应用)

 1 # -*- coding: utf-8 -*-
 2 """
 3 Created on Sat Mar  2 21:17:58 2019
 4 
 5 @author: Administrator
 6 """
 7 
 8 '''
 9 图像去除噪声
10 '''
11 import matplotlib.pyplot as plt 
12 import numpy as np
13 from skimage.util import random_noise
14 from PIL import Image 
15 import cv2
16 
17 img = plt.imread('F:/python编程/自己的博客园代码/picture_process/gaussian_picture.jpg')
18 fig = plt.figure(figsize=(8.0,6.0))
19 ax1 = fig.add_subplot(2,3,1)
20 ax1.imshow(img)
21 plt.title('blur_picture')
22 
23 ###  中值滤波
24 median_filter_img = cv2.medianBlur(img, 3)
25 ax2 = fig.add_subplot(2,3,2)
26 ax2.imshow(median_filter_img)
27 plt.title('median_filter')
28 
29 #### 高斯滤波
30 Gaussian_filter_img = cv2.GaussianBlur(img, (3,3), 0)
31 ax2 = fig.add_subplot(2,3,3)
32 ax2.imshow(Gaussian_filter_img)
33 plt.title('Gaussian_filter')
34 
35 #### 均值滤波
36 mean_vaule_filter = cv2.blur(img, (5,5))
37 ax2 = fig.add_subplot(2,3,4)
38 ax2.imshow(mean_vaule_filter)
39 plt.title('mean_vaule_filter')
40 
41 #### 双边滤波
42 #9 邻域直径,两个 75 分别是空间高斯函数标准差,灰度值相似性高斯函数标准差
43 blur = cv2.bilateralFilter(img,9,75,75)
44 ax2 = fig.add_subplot(2,3,5)
45 ax2.imshow(blur)
46 plt.title('bilatral-filter')
View Code

效果图

 

posted on 2019-03-03 15:42 E-Dreamer 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/E-Dreamer-Blogs/p/10458846.html

2017-08-24 16:12:58 second24 阅读数 18474

常见的噪声种类

数字图像在获取、传输的过程中都可能会受到噪声的污染,常见的噪声主要有高斯噪声和椒盐噪声。其中,高斯噪声主要是由摄像机传感器元器件内部产生的,椒盐噪声主要是由图像切割所产生的黑白相间的亮暗点噪声,“椒”表示黑色噪声,“盐”表示白色噪声。

f=imread('3.jpg');
g=imnoise(f,'salt & pepper',0.06);
h=imnoise(f,'gaussian',0.05,0.05);
subplot(1, 3, 1), imshow(f), title('原图');
subplot(1, 3, 2), imshow(g), title('椒盐');
subplot(1, 3, 3), imshow(h), title('高斯');

这里写图片描述

去噪方法

空域

空域图像去噪用的有均值滤波算法和中值滤波算法,主要是对图像像素做邻域的运算来达到去噪结果。

g1 = imfilter(g, fspecial('average'));
g2 = medfilt2(g, [5 5]);
subplot(2, 2, 3), imshow(g1), title('均值滤波');
subplot(2, 2, 4), imshow(g2), title('中值滤波');

这里写图片描述

形态学去噪

数学形态学图像处理通过采用具有一定形态的结构元素去度量和提取图像中的对应形状,借助于集合理论来达到对图像进行分析和识别的目标,该算法具有以下特征。

1、图像信息的保持

在图像形态学处理中,可以通过已有目标的几何特征信息来选择基于形态学的形态滤波器,这样在进行处理时既可以有效地进行滤波,又可以保持图像中的原有信息。

2、图像边缘的提取

基于数学形态学的理论进行处理,可以在一定程度上避免噪声的干扰,相对于微分算子的技术而言具有较高的稳定性。形态学技术提取的边缘也比较光滑,更能体现细节信息。

3、图像骨架的提取

基于数学形态学进行骨架提取,可以充分利用集合运算的优点,避免出现大量的断点,骨架也较为连续。

4、图像处理的效率

基于数学形态学进行图像处理,可以方便地应用并行处理的技术来进行集合运算,具有效率高、易于硬件实现的特点。

权重自适应的多结构形态学去噪

在数学形态学图像去噪的过程中,通过适当地选取结构元素的形状和维数可以提高滤波去噪的效果。在多结构元素的级联过程中,需要考虑到结构元素的形状和维数。数字图像在进行数学形态滤波去噪时,根据噪声特点可以尝试采用维数由小到大的结构元素来进行处理,进而达到滤除不同噪声的目的。采用数学形态学的多结构元素,可以更多地保持数字图像的几何特征。因此,选择构建串联滤波器来进行图像滤波,就是将同一形状的结构元素按维数从小到大的顺序来对图像进行滤波。

>> i=imread('food.jpg');
>> i=rgb2gray(i);
>> %添加噪声
>> ig=imnoise(i,'poisson');
>> %获取算子
>> s=GetStrelList();
>> %串联去噪
>> edit erodeList
>> e=erodeList(ig,s);
>> edit getRateList
>> %计算权重
>> f=getRateList(ig,e);
>> edit getRemoveResult
>> %并联
>> igo=getRemoveResult(f,e);
>> %显示结果
>> subplot(1,2,1),imshow(f);
>> subplot(1,2,1),imshow(i);
>> title('原图像');
>> subplot(1,2,2),imshow(ig),title('噪声图像');
>> figure;
>> subplot(2,2,1),imshow(e.eroded_co12);title('串联1处理结果');
>> subplot(2,2,2),imshow(e.eroded_co22);title('串联2处理结果');
>> subplot(2,2,3),imshow(e.eroded_co32);title('串联3处理结果');
>> subplot(2,2,4),imshow(e.eroded_co42);title('串联4处理结果');
>> figure;
>> subplot(1,2,1),imshow(ig),title('噪声图像');
>> subplot(1,2,2),imshow(igo),title('并联去噪图像');

这里写图片描述

这里写图片描述

这里写图片描述