opencv-11-中值滤波及自适应中值滤波

开始之前

在上一篇我们实现了读取噪声图像, 然后 进行三种形式的均值滤波得到结果, 由于我们自己写的均值滤波未作边缘处理, 所以效果有一定的下降, 但是总体来说, 我们得到的结果能够说明我们的算法执行之后得到的图像噪声更低, 图像更清晰. 但是也会造成图像的模糊, 导致部分细节丢失. 在这一章中,我们介绍一下中值滤波及其实现

摘要

首先介绍了中值滤波的原理, 给出其实现思路,并根据思路实现了 C++ 的代码, 然后 同样测试 opencv 自带的中值滤波, 同样的测试图像, 得到对比结果, 分析代码的实现过程, .

正文

中值滤波原理

中值滤波(Media Filter)就是对于图像的每一个点计算其邻域窗口的像素序列中值, 可以表示为:
g ( x , y ) = m e i d a ( i , j ) ∈ S f ( i , j ) g(x,y) = meida_{(i,j) \in S}f(i,j) g(x,y)=meida(i,j)Sf(i,j)
核心就是将相应窗口内的像素值进行排列, 我们之前也说过, 我们选择的窗口为奇数尺寸, 所以我们能够保证窗口内的像素个数也是奇数个, 这样我们可以保证取得唯一的中值, 相应的设置为该点的目标值就行了.

C++ 实现中值滤波

我们来实现一下, 这方面还是能够找到不少结果的, 感觉这个博主写的还是很不错的,有兴趣的可以看下数字图像处理------中值滤波,还有图像处理之中值滤波介绍及C实现, 或者 中值滤波器(Median filter)特性及其实现, 这里我就不再造轮子了, 我们来看下 C++的实现
, 主要参考 第一篇文章, 可以看下效果

这里有一点点需要讨论的, 对于彩色图像的三个通道怎么处理, 自己的思路就是分成三个通道进行处理, 然后分别得到三个图之后进行合并三个通道, 得到结果图像. 查了下 目测大家都是这么做的, 可以看OpenCV 彩色图像的自适应中值滤波 C++ 和 彩色图像空间滤波(MATLAB) 这两篇文章, 思路都是一样的, 我们来实现一下.

//中值滤波:C++ 代码实现 // 处理单通道图像 // 参考 https://www.cnblogs.com/ranjiewen/p/5699395.html
cv::Mat medianFilterGray(const cv::Mat &src, int ksize = 3)
{
   
    cv::Mat dst = src.clone();
    //0. 准备:获取图片的宽,高和像素信息,
    const int  num = ksize * ksize;
    std::vector<uchar> pixel(num);

    //相对于中心点,3*3领域中的点需要偏移的位置
    int delta[3 * 3][2] = {
   
        {
    -1, -1 }, {
    -1, 0 }, {
    -1, 1 }, {
    0, -1 }, {
    0, 0 }, {
    0, 1 }, {
    1, -1 }, {
    1, 0 }, {
   1, 1}
    };
    //1. 中值滤波,没有考虑边缘
    for (int i = 1; i < src.rows - 1; ++i)
    {
   
        for (int j = 1; j < src.cols - 1; ++j)
        {
   
            //1.1 提取领域值 // 使用数组 这样处理 8邻域值 不适合更大窗口
            for (int k = 0; k < num; ++k)
            {
   
                pixel[k] = src.at<uchar>(i+delta[k][0], j+ delta[k][1]);
            }
            //1.2 排序  // 使用自带的库及排序即可
            std::sort(pixel.begin(), pixel.end());
            //1.3 获取该中心点的值
            dst.at<uchar>(i, j) = pixel[num / 2];
        }
    }
    return dst;
}

思路还是那个思路, 不过在写的过程中, 我在想, 能不能直接处理彩色的图像呢, 对于彩色图像最麻烦的地方就是排序了, 我们没办法考虑颜色的高低值, 所以 那我们自定义一个比较函数应该就行了吧. 我们使用三个颜色的和值 做比较
这里使用了C++ 的sort 自定义函数的方法, 这边采用的比较函数的方式, 还有别的方式实现两个元素的比较, 可以参考c++中vector自定义排序的问题

// 自定义两个像素的比较函数,  // 使用和值 排序
bool comp(const cv::Vec3b &p1, const cv::Vec3b &p2)
{
   
    return (p1[0] + p1[1] + p1[2]) < (p2[0] + p2[1] 

你可能感兴趣的:(opencv教程,计算机视觉,opencv,算法,c++,qt5)