数字图像处理(八)KNN滤波器

题目:使用K近邻平滑滤波器对图像进行滤波。
采用国际标准测试图像Lena。

上节我们介绍了均值滤波器,均值滤波器会使图像变得模糊,边缘特征减少。为了解决图像模糊问题,一个自然的想法就是,在进行平滑处理时,首先判别当前像素是否在边界上的点,如果是,则不进行平滑处理;如果不是,则进行平滑处理。
KNN算法原理:如果待处理像素为非噪声点,则通过选择像素值与之相近的邻点,可以保证在进行平滑处理时,基本上是同一个区域的像素值的计算,这样就可以保证图像的清晰度(边界保持)。如果待处理像素是噪声点,则因为噪声本身具有孤立点的特点,因此,与邻点进行平滑处理,可以对其进行抑制。

具体方法如下:

  1. f ( x , y ) f(x,y) f(x,y)为当前待处理像素,以其为中心,构造一个 N × N N\times N N×N的模板( N N N为奇数,一般取3,5,或7);
  2. 在模板中的 N × N N\times N N×N个像素中,选择出K个像素值与 f ( x , y ) f(x,y) f(x,y)相近的像素(一般当 N = 3 N=3 N=3时,取 K = 5 K=5 K=5;当 N = 5 N=5 N=5时,取 K = 9 K=9 K=9;当 N = 7 N=7 N=7时,取 K = 25 K=25 K=25),这 K K K个像素不包含 f ( x , y ) f(x,y ) f(x,y)本身;
  3. 将这 K K K个像素的均值(中值)替代原像素值 f ( x , y ) f(x,y) f(x,y)
    C++代码:
//定义结构体,保存相邻像素点的信息
struct subValue
{
    
    
    int value;
    cv::Point f;
};
//冒泡排序
vector<struct subValue> sortStruct(vector<struct subValue>a)
{
    
    
    struct subValue b;
    for (int i = 0; i < a.size() - 1; i++)
    {
    
    
        for (int j = 0; j < a.size() - 1 - i; j++)
        {
    
    
            if (a[j].value > a[j + 1].value)
            {
    
    
                b = a[j];
                a[j] = a[j + 1];
                a[j + 1] = b;
            }
        }
    }
    return a;
}
int main()
{
    
    
    cv::Mat image = cv::imread("knn.png");
    cv::Mat src(image.size(), CV_8UC1);
    cv::cvtColor(image, src, CV_BGR2GRAY);

    cv::Mat dst = src.clone();
    int N = 3, K = 5;

    for (int row = 1; row < src.rows - 1; ++row)
    {
    
    
        for (int col = 1; col < src.cols - 1; ++col)
        {
    
    
            double v = 0.0;
            vector<struct subValue>c;
            struct subValue b;
            for (int dy = -1; dy < N - 1; ++dy)
            {
    
    
                for (int dx = -1; dx < N - 1; ++dx)
                {
    
    
                    if (!(dx == 0 && dy == 0))
                    {
    
    
                        b.value = abs(src.at<uchar>(row + dy, col + dx) - src.at<uchar>(row, col));
                        b.f.x = dx;
                        b.f.y = dy;
                        c.push_back(b);
                    }
                }
            }
            //进行排序
            vector<struct subValue> sortValue = sortStruct(c);
            //取中值
           // v = src.at<uchar>(row + sortValue[2].f.y, col + sortValue[2].f.x);
           // dst.at<uchar>(row, col) = uchar(v);
           //取均值
            for (int i = 0; i < K;++i)
            {
    
    
                v += src.at<uchar>(row + sortValue[i].f.y, col + sortValue[i].f.x);
            }
            dst.at<uchar>(row, col) = uchar(v/K);
           
        }
    }
    cv::imshow("input", src);
    cv::imshow("output", dst);
    cv::waitKey(0);
    return 0;
}

参考书籍:数字图像处理基础.朱虹

猜你喜欢

转载自blog.csdn.net/qq_41596730/article/details/126999048