均值、中值与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⎦⎤