高斯平滑滤波的实现与图像内存之间值的复制
2017-08-03 15:23
337 查看
以另外一个滤波器而言----均值滤波器, 就是说某像素的颜色, 由以其为中心的九宫格的像素平均值来决定. 在这个基础上又发展成了带权的“平均”滤波器, 这里的高斯平滑或者说滤波器就是这样一种带权(通常我们认为距离要代替的点像素的作用大一些)的“平均”滤波器. 那么这些权重如何分布呢? 我们先来看几个经典的模板例子:
尝试了使用这些滤波器对我们原来的图进行操作, 得到了这样的一组结果:
原图:
3x3 高斯滤波处理后:
5x5 高斯处理后:
单纯从效果来看, 两个模板都起到了平滑的作用, 只是程度有深浅的区分. 那么从理论上来说为什么能起到平滑的作用呢? 很显然, 像素的颜色不仅由自身决定了, 同时有其周围的像素加权决定, 客观上减小了和周围像素的差异.同时这些权重的设定满足了越近权重越大的规律. 从理论来讲, 这些权重的分布满足了著名的所谓高斯分布:
这就是1维的计算公式:
这就是2维的计算公式:
x, y表示的就是当前点到对应点的距离, 而那些具体的模板就是由这里公式中的一些特例计算而来. 需要说明的是不只有这么一些特例, 从wikipedia可以方便地找到那些复杂的模板比如像:
This is a sample matrix, produced by sampling the Gaussian filter kernel (with σ = 0.84089642) at the midpoints of each pixel and then normalising. Note that the center element (at [4, 4]) has the largest value, decreasing symmetrically as distance from the
center increases.
是不是看到就头大了?不过没关系, 对于一般的应用来说, 前面的例子已经可以完成任务了. 代码的话我们还是给一份5x5的example:
[html] view
plain copy
print?
void gaussianFilter2 (unsigned char* corrupted, unsigned char* smooth, int width, int height)
{
int templates[25] = { 1, 4, 7, 4, 1,
4, 16, 26, 16, 4,
7, 26, 41, 26, 7,
4, 16, 26, 16, 4,
1, 4, 7, 4, 1 }; //滤波器模板
memcpy ( smooth, corrupted, width*height*sizeof(unsigned char) ); //复制像素
for (int j=2;j<height-2;j++) //边缘不处理
{
for (int i=2;i<width-2;i++)
{
int sum = 0;
int index = 0;
for ( int m=j-2; m<j+3; m++)
{
for (int n=i-2; n<i+3; n++)
{
sum += corrupted [ m*width + n] * templates[index++] ;
}
}
sum /= 273;
if (sum > 255)
sum = 255;
smooth [ j*width+i ] = sum;
}
}
}
今天也尝试了图像复原算法的研究,其实图像复原算法与傅里叶变换与滤波的关系很大。下面为一部分代码
# include <opencv2/core/core.hpp>
# include <opencv2/highgui/highgui.hpp>
# include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void gaussianFilter2 (unsigned char* corrupted, unsigned char* smooth, int width, int height)
{
int templates[25] = { 1, 4, 7, 4, 1,
4, 16, 26, 16, 4,
7, 26, 41, 26, 7,
4, 16, 26, 16, 4,
1, 4, 7, 4, 1 }; //滤波器模板
//定义卷积核算子
cv::Mat kernal = (cv::Mat_<float>(3,3)<< 1,1,1,
1,1,1,
1,1,1);
memcpy ( smooth, corrupted, width*height*sizeof(unsigned char) ); //复制像素
for (int j=2;j<height-2;j++) //边缘不处理
{
for (int i=2;i<width-2;i++)
{
int sum = 0;
int index = 0;
for ( int m=j-2; m<j+3; m++)
{
for (int n=i-2; n<i+3; n++)
{
sum += corrupted [ m*width + n] * templates[index++] ;
}
}
sum /= 273;
if (sum > 255)
sum = 255;
smooth [ j*width+i ] = sum;
}
}
}
cv::Mat DFT(cv::Mat srcImage)
{
cv::Mat srcGray;
cvtColor(srcImage,srcGray,CV_RGB2GRAY);
// 将输入图像延扩到最佳的尺寸
int nRows = getOptimalDFTSize(srcImage.rows);
int nCols = getOptimalDFTSize(srcImage.cols);
cv::Mat resultImage;
// 把灰度图像放在左上角,在右边和下边扩展图像,
// 添加的像素初始化为0
copyMakeBorder(srcGray, resultImage, 0,
nRows - srcGray.rows,
0, nCols - srcGray.cols,
BORDER_CONSTANT, Scalar::all(0));
// 为傅立叶变换的结果(实部和虚部)分配存储空间
cv::Mat planes[] = { cv::Mat_<float>(resultImage),
cv::Mat::zeros(resultImage.size(), CV_32F)};
Mat completeI;
// 为延扩后的图像增添一个初始化为0的通道
merge(planes,2,completeI);
// 进行离散傅立叶变换
dft(completeI,completeI);
// 将复数转换为幅度
split(completeI,planes);
magnitude(planes[0],planes[1],planes[0]);
cv::Mat dftResultImage = planes[0];
// 对数尺度(logarithmic scale)缩放
dftResultImage += 1;
log(dftResultImage,dftResultImage);
// 剪切和重分布幅度图象限
dftResultImage= dftResultImage(Rect(0,
0,srcGray.cols,srcGray.rows));
// 归一化图像
/*normalize(dftResultImage,dftResultImage,
0,1,CV_MINMAX);*/
int cx = dftResultImage.cols/2;
int cy = dftResultImage.rows/2;
Mat tmp;
// Top-Left - 为每一个象限创建ROI
Mat q0(dftResultImage,Rect(0,0,cx,cy));
// Top-Right
Mat q1(dftResultImage,Rect(cx,0,cx,cy));
// Bottom-Left
Mat q2(dftResultImage,Rect(0,cy,cx,cy));
// Bottom-Right
Mat q3(dftResultImage,Rect(cx,cy,cx,cy));
// 交换象限 (Top-Left with Bottom-Right)
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
// 交换象限 (Top-Right with Bottom-Left)
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
return dftResultImage;
}
int main()
{
cv::Mat srcImage = imread("3.jpg");
Mat dstImage = Mat(srcImage.size(),srcImage.type(),Scalar::all(0));
uchar *dataSrc = srcImage.data;
uchar *dataDst = dstImage.data;
int nRows = srcImage.rows;
int nCols = srcImage.cols;
/*gaussianFilter2(dataSrc,dataDst,nCols,nRows);*/
memcpy(dataDst,dataSrc,sizeof(uchar)*nCols*nRows * 3); 此处为3通道图像
namedWindow("2",0);
imshow("2",dstImage);
waitKey(0);
}
尝试了使用这些滤波器对我们原来的图进行操作, 得到了这样的一组结果:
原图:
3x3 高斯滤波处理后:
5x5 高斯处理后:
单纯从效果来看, 两个模板都起到了平滑的作用, 只是程度有深浅的区分. 那么从理论上来说为什么能起到平滑的作用呢? 很显然, 像素的颜色不仅由自身决定了, 同时有其周围的像素加权决定, 客观上减小了和周围像素的差异.同时这些权重的设定满足了越近权重越大的规律. 从理论来讲, 这些权重的分布满足了著名的所谓高斯分布:
这就是1维的计算公式:
这就是2维的计算公式:
x, y表示的就是当前点到对应点的距离, 而那些具体的模板就是由这里公式中的一些特例计算而来. 需要说明的是不只有这么一些特例, 从wikipedia可以方便地找到那些复杂的模板比如像:
Sample Gaussian matrix
This is a sample matrix, produced by sampling the Gaussian filter kernel (with σ = 0.84089642) at the midpoints of each pixel and then normalising. Note that the center element (at [4, 4]) has the largest value, decreasing symmetrically as distance from thecenter increases.
0.00000067 | 0.00002292 | 0.00019117 | 0.00038771 | 0.00019117 | 0.00002292 | 0.00000067 |
0.00002292 | 0.00078633 | 0.00655965 | 0.01330373 | 0.00655965 | 0.00078633 | 0.00002292 |
0.00019117 | 0.00655965 | 0.05472157 | 0.11098164 | 0.05472157 | 0.00655965 | 0.00019117 |
0.00038771 | 0.01330373 | 0.11098164 | 0.22508352 | 0.11098164 | 0.01330373 | 0.00038771 |
0.00019117 | 0.00655965 | 0.05472157 | 0.11098164 | 0.05472157 | 0.00655965 | 0.00019117 |
0.00002292 | 0.00078633 | 0.00655965 | 0.01330373 | 0.00655965 | 0.00078633 | 0.00002292 |
0.00000067 | 0.00002292 | 0.00019117 | 0.00038771 | 0.00019117 | 0.00002292 | 0.00000067 |
[html] view
plain copy
print?
void gaussianFilter2 (unsigned char* corrupted, unsigned char* smooth, int width, int height)
{
int templates[25] = { 1, 4, 7, 4, 1,
4, 16, 26, 16, 4,
7, 26, 41, 26, 7,
4, 16, 26, 16, 4,
1, 4, 7, 4, 1 }; //滤波器模板
memcpy ( smooth, corrupted, width*height*sizeof(unsigned char) ); //复制像素
for (int j=2;j<height-2;j++) //边缘不处理
{
for (int i=2;i<width-2;i++)
{
int sum = 0;
int index = 0;
for ( int m=j-2; m<j+3; m++)
{
for (int n=i-2; n<i+3; n++)
{
sum += corrupted [ m*width + n] * templates[index++] ;
}
}
sum /= 273;
if (sum > 255)
sum = 255;
smooth [ j*width+i ] = sum;
}
}
}
今天也尝试了图像复原算法的研究,其实图像复原算法与傅里叶变换与滤波的关系很大。下面为一部分代码
# include <opencv2/core/core.hpp>
# include <opencv2/highgui/highgui.hpp>
# include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void gaussianFilter2 (unsigned char* corrupted, unsigned char* smooth, int width, int height)
{
int templates[25] = { 1, 4, 7, 4, 1,
4, 16, 26, 16, 4,
7, 26, 41, 26, 7,
4, 16, 26, 16, 4,
1, 4, 7, 4, 1 }; //滤波器模板
//定义卷积核算子
cv::Mat kernal = (cv::Mat_<float>(3,3)<< 1,1,1,
1,1,1,
1,1,1);
memcpy ( smooth, corrupted, width*height*sizeof(unsigned char) ); //复制像素
for (int j=2;j<height-2;j++) //边缘不处理
{
for (int i=2;i<width-2;i++)
{
int sum = 0;
int index = 0;
for ( int m=j-2; m<j+3; m++)
{
for (int n=i-2; n<i+3; n++)
{
sum += corrupted [ m*width + n] * templates[index++] ;
}
}
sum /= 273;
if (sum > 255)
sum = 255;
smooth [ j*width+i ] = sum;
}
}
}
cv::Mat DFT(cv::Mat srcImage)
{
cv::Mat srcGray;
cvtColor(srcImage,srcGray,CV_RGB2GRAY);
// 将输入图像延扩到最佳的尺寸
int nRows = getOptimalDFTSize(srcImage.rows);
int nCols = getOptimalDFTSize(srcImage.cols);
cv::Mat resultImage;
// 把灰度图像放在左上角,在右边和下边扩展图像,
// 添加的像素初始化为0
copyMakeBorder(srcGray, resultImage, 0,
nRows - srcGray.rows,
0, nCols - srcGray.cols,
BORDER_CONSTANT, Scalar::all(0));
// 为傅立叶变换的结果(实部和虚部)分配存储空间
cv::Mat planes[] = { cv::Mat_<float>(resultImage),
cv::Mat::zeros(resultImage.size(), CV_32F)};
Mat completeI;
// 为延扩后的图像增添一个初始化为0的通道
merge(planes,2,completeI);
// 进行离散傅立叶变换
dft(completeI,completeI);
// 将复数转换为幅度
split(completeI,planes);
magnitude(planes[0],planes[1],planes[0]);
cv::Mat dftResultImage = planes[0];
// 对数尺度(logarithmic scale)缩放
dftResultImage += 1;
log(dftResultImage,dftResultImage);
// 剪切和重分布幅度图象限
dftResultImage= dftResultImage(Rect(0,
0,srcGray.cols,srcGray.rows));
// 归一化图像
/*normalize(dftResultImage,dftResultImage,
0,1,CV_MINMAX);*/
int cx = dftResultImage.cols/2;
int cy = dftResultImage.rows/2;
Mat tmp;
// Top-Left - 为每一个象限创建ROI
Mat q0(dftResultImage,Rect(0,0,cx,cy));
// Top-Right
Mat q1(dftResultImage,Rect(cx,0,cx,cy));
// Bottom-Left
Mat q2(dftResultImage,Rect(0,cy,cx,cy));
// Bottom-Right
Mat q3(dftResultImage,Rect(cx,cy,cx,cy));
// 交换象限 (Top-Left with Bottom-Right)
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
// 交换象限 (Top-Right with Bottom-Left)
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
return dftResultImage;
}
int main()
{
cv::Mat srcImage = imread("3.jpg");
Mat dstImage = Mat(srcImage.size(),srcImage.type(),Scalar::all(0));
uchar *dataSrc = srcImage.data;
uchar *dataDst = dstImage.data;
int nRows = srcImage.rows;
int nCols = srcImage.cols;
/*gaussianFilter2(dataSrc,dataDst,nCols,nRows);*/
memcpy(dataDst,dataSrc,sizeof(uchar)*nCols*nRows * 3); 此处为3通道图像
namedWindow("2",0);
imshow("2",dstImage);
waitKey(0);
}
相关文章推荐
- c#实现图像图像卷积与滤波——高斯平滑
- 数字图像处理,高斯平滑滤波的C++实现
- 高斯图像滤波原理及其编程离散化实现方法
- matlab实现图像滤波——高斯滤波
- 【Matlab学习笔记】【图像滤波去噪】高斯平滑滤波
- 高斯图像滤波原理及其编程离散化实现方法
- 高斯图像滤波原理及其编程离散化实现方法
- 转载:图像高斯平滑滤波分析——如何求高斯滤波模板
- opencv for python (13) 图像卷积及图像平滑(平均、高斯模糊、中值模糊、双边滤波)
- matlab 图像高斯平滑滤波处理(转载)
- 高斯图像滤波原理及其编程离散化实现方法
- 高斯图像滤波原理及其编程离散化实现方法
- 高斯图像滤波原理及其编程离散化实现方法
- 高斯图像滤波原理及其编程离散化实现方法
- 高斯图像滤波原理及其编程离散化实现方法
- 图像的高斯平滑C++实现
- 图像高斯平滑滤波分析(转)
- 高斯图像滤波原理及其编程离散化实现方法
- 高斯图像滤波原理及其编程离散化实现方法
- OpenCV 之三----高斯模板对图像平滑滤波