文章目录
一、实验目的:
掌握利用模板对图像进行空域滤波操作,熟练掌握常用空域模板的使用。 1、掌握图像平滑的空域方法,熟练掌握均值模板和高斯模板平滑图像 2、掌握图像锐化的空域方法,熟练掌握 Laplacian、Robert、Sobel 模板锐化
图像 3、掌握利用高提升滤波算法对图像进行增强
二、实验内容:
1、利用均值模板平滑灰度图像。
具体内容:利用 OpenCV 对图像像素进行操作,分别利用 3*3、5*5 和 9*9尺寸的均值模板平滑灰度图像
2、利用高斯模板平滑灰度图像。
具体内容:利用 OpenCV 对图像像素进行操作,分别利用 3*3、5*5 和 9*9尺寸的高斯模板平滑灰度图像
3、利用 Laplacian、Robert、Sobel 模板锐化灰度图像。
具体内容:利用 OpenCV 对图像像素进行操作,分别利用 Laplacian、Robert、Sobel 模板锐化灰度图像
4、利用高提升滤波算法增强灰度图像。
具体内容:利用 OpenCV 对图像像素进行操作,设计高提升滤波算法增强图像
5、利用均值模板平滑彩色图像。
具体内容:利用 OpenCV 分别对图像像素的 RGB 三个通道进行操作,利用 3*3、5*5 和 9*9 尺寸的均值模板平滑彩色图像
6、利用高斯模板平滑彩色图像。
具体内容:利用 OpenCV 分别对图像像素的 RGB 三个通道进行操作,分别利用 3*3、5*5 和 9*9 尺寸的高斯模板平滑彩色图像
7、利用 Laplacian、Robert、Sobel 模板锐化彩色图像。
具体内容:利用 OpenCV 分别对图像像素的 RGB 三个通道进行操作,分别利用 Laplacian、Robert、Sobel 模板锐化彩色图像
三.实验过程
对实验内容进行分析,实验利用均值和高斯模版时只是模版内容不同,但通过模版样式平滑图片的过程相同。
所以首先写出一个通用的滤波器。这个滤波器可以处理灰度和彩色的传入图像。
//利用模版进行平滑处理
Mat Filter(const Mat &src,Mat &dst,int ksize,double **templateMatrix){
assert(src.channels()||src.channels()==3);
//建立滤波器模版
cout <<ksize<<"*"<<ksize<<"模版为:"<<endl;
for(int i=0;i<ksize;i++){
for (int j=0; j<ksize; j++) {
cout<<templateMatrix[i][j]<<"";
}
cout<<endl;
}
int border=ksize/2;
//边界处理,这里直接调用函数进行
copyMakeBorder(src, dst, border, border, border, border, BorderTypes::BORDER_REFLECT);
int channels=src.channels();
int cols=dst.cols-border;
int rows=dst.rows-border;
//开始利用模版进行平滑处理
for(int i=border;i<rows;i++){
for(int j=border;j<cols;j++){
double sum[3]={
0};
for (int k=-border;k<=border;k++){
for(int m=-border;m<=border;m++){
//灰度
if(channels==1){
sum[0] += (double)templateMatrix[k + border][m + border] * src.at<uchar>(i + k, j + m);
}
//彩色
else if (channels == 3)
{
Vec3b rgb = src.at<Vec3b>(i + k,j + m);
auto tmp = templateMatrix[border + k][border + m];
sum[0] += tmp*rgb[0];
sum[1] += tmp*rgb[1];
sum[2] += tmp*rgb[2];
}
}
}
//限定像素值在0-255之间
for (int i = 0; i < channels; i++) {
if (sum[i] < 0)
sum[i] = 0;
else if (sum[i] > 255)
sum[i] = 255;
}
if (channels == 1) {
dst.at<uchar>(i, j) = static_cast<uchar>(sum[0]);
}
else if (channels == 3) {
Vec3b rgb;
rgb[0] = static_cast<uchar>(sum[0]);
rgb[1] = static_cast<uchar>(sum[1]);
rgb[2] = static_cast<uchar>(sum[2]);
dst.at<Vec3b>(i, j) = rgb;
}
}
}
return dst;
}
实验
(1)实验1、利用均值模板平滑灰度图像 实验5、利用均值模板平滑彩色图像。
两个实验用的均值处理的模版相同。
//实验一:
void MeanFilter(const Mat &src,Mat &dst,int ksize){
//建立一个二维数组
double **templateMatrix=new double *[ksize];
for(int i=0;i<ksize;i++){
templateMatrix[i]=new double [ksize];
}
int tmp=ksize*ksize;
int origin=ksize/2;
for(int i=0;i<ksize;i++){
for(int j=0;j<ksize;j++){
//每个位置上直接算出来平均值
templateMatrix[i][j]=1.0/tmp;
}
}
dst=Filter(src,dst,ksize,templateMatrix);
imshow("lab1", dst);
waitKey(1000);
}
处理结果:
实验1:利用均值模板平滑灰度图像。
实验五:利用均值模板平滑彩色图像。
(2)实验2、利用高斯模板平滑灰度图像。实验6、利用高斯模板平滑彩色图像。
高斯公式:
//实验二:利用高斯模板平滑灰度图像。
void GaussianFilter(const Mat &src,Mat &dst,int ksize,double sigma){
const static double pi=3.1415926;
//根据窗口大小和sigma生成高斯滤波模版,并申请一个二维数组,存放生成的高斯模版矩阵
double **templateMatrix=new double *[ksize];
for(int i=0;i<ksize;i++)
templateMatrix[i]=new double[ksize];
int origin=ksize/2; //以模版中心为原点
double x2,y2;
double sum=0;
for(int i=0;i<ksize;i++){
x2=pow(i-origin, 2);
for(int j=0;j<ksize;j++){
y2=pow(double(j-origin), 2);
//高斯函数前的常数可以不用计算,会在归一化的过程中消去
double g=exp(-(x2+y2)/(2*sigma*sigma));
sum+=g;
templateMatrix[i][j]=g;
}
}
double k=1/sum;
for(int i=0;i<ksize;i++){
for(int j=0;j<ksize;j++){
templateMatrix[i][j]*=k;
}
}
dst=Filter(src,dst,ksize,templateMatrix);
imshow("lab2", dst);
waitKey(1000);
}
实验结果:
实验2、利用高斯模板平滑灰度图像。
实验6、利用高斯模板平滑彩色图像。
(3)实验3、利用 Laplacian模板锐化灰度图像。实验 7、利用 Laplacian、模板锐化彩色图像。
这三个锐化模板与之前的平滑模板不同,会出现超过[0,255]范围的结果。对于结算得到的边缘图像,需要标定一下。
首先利用Laplacian:
拉普拉斯经过公式变换后得到几个模版:
灰度图像下算法过程:
//实验三:使用拉普拉斯进行锐化
int FilterProcessing(Mat src, Mat dst, Mat filter,double ProcessingMethod(Mat filterArea, Mat filter))
{
Mat src_padding=src.clone();
Mat filterArea;
int padding = (filter.rows - 1) / 2;
//padding the border
copyMakeBorder(src, src_padding, padding, padding, padding, padding, BORDER_REPLICATE);
if (dst.type() == CV_8U)
{
for (int y = padding; y < src_padding.rows - padding; y++)
{
for (int x = padding; x < src_padding.cols - padding; x++)
{
filterArea = src_padding(Range(y - padding, y + padding + 1), Range(x - padding, x + padding + 1));
dst.at<uchar>(y - padding, x - padding) = cvRound(ProcessingMethod(filterArea, filter));
}
}
}
else if (dst.type() == CV_64F)
{
for (int y = padding; y < src_padding.rows - padding; y++)
{
for (int x = padding; x < src_padding.cols - padding; x++)
{
filterArea = src_padding(Range(y - padding, y + padding + 1), Range(x - padding, x + padding + 1));
dst.at<double>(y - padding, x - padding) = ProcessingMethod(filterArea, filter);
}
}
}
else
{
cout << "type error" << endl;
}
return 0;
}
double LinearFilterCalc(Mat filterArea, Mat linearFilter)
{
double result = 0;
for (int y = 0; y < filterArea.rows; y++)
{
for (int x = 0; x < filterArea.cols; x++)
{
result += (double(filterArea.at<uchar>(y, x)))*(linearFilter.at<double>(y, x));
}
}
return result;
}
int LaplacianFilterProcessing(Mat src, Mat dst, Mat laplacianFilter, Mat laplacianFilterImg, double c)
{
FilterProcessing(src, laplacianFilterImg, laplacianFilter, LinearFilterCalc);
//计算并标定锐化结果,直接saturate_cast<uchar>
for (int y = 0; y < src.rows; y++)
{
for (int x = 0; x < src.cols; x++)
{
dst.at<uchar>(y, x) = saturate_cast<uchar>(src.at<uchar>(y, x) + cvRound(c*laplacianFilterImg.at<double>(y, x)));
}
}
return 0;
}
int LaplacianSharpen(Mat src, Mat dst, string title, double c, int filterNum)//dst是锐化后的结果图像
{
Mat laplacianFilter_n4 = (Mat_<double>(3, 3) <<
0, 1, 0,
1, -4, 1,
0, 1, 0);
/*Mat laplacianFilter_n8 = (Mat_<double>(3, 3) <<
1, 1, 1,
1, -8, 1,
1, 1, 1);*/
Mat laplacianFilter;
string filterTitle;
laplacianFilter = laplacianFilter_n4;
filterTitle = "1 -4 1";
Mat laplacianFilterImg = Mat::zeros(src.size(), CV_64F);//滤波后得到的边缘图像
LaplacianFilterProcessing(src, dst, laplacianFilter, laplacianFilterImg, c);
/*标定Laplacian滤波得到的边缘结果*/
double maxLap, minLap;
minMaxLoc(laplacianFilterImg, &minLap, &maxLap, <