均值、中值以及Motion滤波器

均值、中值与Motion Filter


问题描述:

使用三种滤波器( 7 × 7 7\times7 7×7)大小,来对fate.jpeg进行图像处理。

代码如下(示例):

// 均值与中值滤波器
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <math.h>

cv::Mat mean_filter(cv::Mat img, int kernel_size)
{
    int row = img.rows;
    int col = img.cols;
    int channel = img.channels();

    // 准备输出
    cv::Mat new_image = cv::Mat::zeros(row, col, CV_8UC3);

    int pad = floor(kernel_size / 2);
    int count = 0;
    double val = 0;

    float kernel[kernel_size * kernel_size];

    for (int i = 0; i < kernel_size; i++)
    {
       kernel[i] = 0;
    }

    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            for (int c = 0; c < channel; c++)
            {
                val = 0;
                for (int di = -pad; di < pad + 1; di++)
                {
                    for (int dj = -pad; dj < pad + 1; dj++)
                    {
                        if ((i + di) >= 0 && (j + dj) >= 0)
                        {
                            val += (int)img.at<cv::Vec3b>(i + di, j + dj)[c];
                        }
                    }
                }
                // 求均值
                val /= (kernel_size * kernel_size);
                new_image.at<cv::Vec3b>(i, j)[c] = (uchar)val;
            }
        }
    }

    return new_image;
}

cv::Mat median_filter(cv::Mat img, int kernel_size)
{
    int row = img.rows;
    int col = img.cols;
    int channel = img.channels();

    cv::Mat new_image = cv::Mat::zeros(row, col, CV_8UC3);

    int pad = floor(kernel_size / 2);
    int count = 0;
    int kernel[kernel_size * kernel_size];
    for (int i = 0; i < kernel_size * kernel_size; i++)
    {
        kernel[i] = 0;
    }


    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            for (int c = 0; c < channel; c++)
            {
                count = 0;
                for (int di = -pad; di < pad + 1; di++)
                {
                    for (int dj = -pad; dj < pad + 1; dj++)
                    {
                        if (((i + di) >= 0) && ((j + dj) >= 0))
                        {
                            kernel[count++] = (int)img.at<cv::Vec3b>(i + di, j + dj)[c];
                        }
                    }
                }
                // 排序方面定位中值
                std::sort(kernel, kernel + kernel_size * kernel_size);
                new_image.at<cv::Vec3b>(i, j)[c] = (uchar)kernel[int(floor(count / 2)) + 1];
            }
        }
    }

    return new_image;
}

int main(){
    // read image
    cv::Mat img = cv::imread("../fate.jpeg", cv::IMREAD_COLOR);

    // median_filter
//    cv::Mat new_image = median_filter(img, 7);
    cv::Mat new_image = mean_filter(img, 7);

    cv::imwrite("../1-10/fate3.jpeg", new_image);
    cv::imshow("vvv", new_image);
    cv::waitKey(0);
    cv::destroyAllWindows();

    return 0;
}

// motion_filter
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <math.h>

cv::Mat motion_filter(cv::Mat img, int kernel_size)
{
    int row = img.rows;
    int col = img.cols;
    int channel = img.channels();

    cv::Mat new_image = cv::Mat::zeros(row, col, CV_8UC3);

    int pad = floor(kernel_size / 2);
    double kernel[kernel_size][kernel_size];

    for (int i = 0; i < kernel_size; i++)
    {
        for (int j = 0; j < kernel_size; j++)
        {
            if (i == j)
            {
                kernel[i][j] = 1. / kernel_size;
            }
            else
            {
                kernel[i][j] = 0;
            }
        }
    }

    double val = 0;
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            for (int c = 0; c < channel; c++)
            {
                val = 0;
                for (int di = -pad; di < pad + 1; di++)
                {
                    for (int dj = -pad; dj < pad + 1; dj++)
                    {
                        if (((di + i) >= 0) && ((di + i) < row) && ((dj + j) >= 0) && ((dj + j) < col))
                        {
                            val += (double)img.at<cv::Vec3b>(i + di, j + dj)[c] * kernel[pad + di][pad + dj];
                        }
                    }
                }
                new_image.at<cv::Vec3b>(i, j)[c] = (uchar)val;
            }
        }
    }

    return new_image;
}


int main(){
    // read image
    cv::Mat img = cv::imread("../fate.jpeg", cv::IMREAD_COLOR);

    // motion_filter
    cv::Mat new_image = motion_filter(img, 7);

    cv::imwrite("../1-10/fate1.jpeg", new_image);
    cv::imshow("vvv", new_image);
    cv::waitKey(0);
    cv::destroyAllWindows();

    return 0;
}

输入图像 (fate.jpeg)中值滤波图像 (fate2.jpeg)均值滤波图像 (fate2.jpeg)motion滤波图像 (fate3.jpeg)
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

三种滤波器

中值滤波器是一种可以使图像平滑的滤波器。这种滤波器用滤波器范围内像素点的中值进行滤波(在这里采用了Zero Padding)。
均值滤波器则使用滤波器范围内像素点的平均值进行滤波。

Motion Filter取对角线方向的像素的平均值,像下式这样定义:
[ 1 3 0 0 0 1 3 0 0 0 1 3 ] \left[ \begin{matrix} \frac{1}{3}&0&0\\ 0&\frac{1}{3}&0\\ 0 & 0& \frac{1}{3} \end{matrix} \right] 310003100031

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值