文章目录
一、实验目的:
掌握利用模板对图像进行空域滤波操作,熟练掌握常用空域模板的使用。 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, 0, 0);
laplacianFilterImg.convertTo(laplacianFilterImg, CV_8U, 255. / (maxLap - minLap), (-255.*minLap) / (maxLap - minLap));
if (title.compare("") != 0)//标题不空则显示结果
{
namedWindow(title + "Laplacian Filter Img" + filterTitle, WINDOW_AUTOSIZE);
imshow(title + "Laplacian Filter Img" + filterTitle, laplacianFilterImg);
namedWindow(title + "Laplacian Sharpen Img" + filterTitle, WINDOW_AUTOSIZE);
imshow(title + "Laplacian Sharpen Img" + filterTitle, dst);
namedWindow(title, WINDOW_AUTOSIZE);
imshow(title, src);
waitKey(3000);
destroyAllWindows();
}
return 0;
}
实验结果:
实验3、利用 Laplacian模板锐化灰度图像。

彩色图像下拉普拉斯处理,分为RGB三个通道解决,最后再合并:
void laplacia_rbgfilter(const Mat &image,Mat &gray){
vector<Mat> BGRchannels;
split(image, BGRchannels);
Mat bChannel, gChannel, rChannel;
bChannel = BGRchannels.at(0);
gChannel = BGRchannels.at(1);
rChannel = BGRchannels.at(2);
vector<Mat> BGRchannels_merge(3);
/*Laplacian*/
int lablacianFilterNum = 1;//1为中心为-4的laplacian模板,2为中心为-8的
double cLap = -1;
Mat laplacianSharpen_bChannel = Mat::zeros(gray.size(), gray.type());
Mat laplacianSharpen_gChannel = Mat::zeros(gray.size(), gray.type());
Mat laplacianSharpen_rChannel = Mat::zeros(gray.size(), gray.type());
Mat laplacianSharpenImg = Mat::zeros(image.size(), image.type());
LaplacianSharpen(bChannel, laplacianSharpen_bChannel, "B channel ", cLap, lablacianFilterNum);
LaplacianSharpen(gChannel, laplacianSharpen_gChannel, "G channel ", cLap, lablacianFilterNum);
LaplacianSharpen(rChannel, laplacianSharpen_rChannel, "R channel ", cLap, lablacianFilterNum);
BGRchannels_merge.at(0) = laplacianSharpen_bChannel;
BGRchannels_merge.at(1) = laplacianSharpen_gChannel;
BGRchannels_merge.at(2) = laplacianSharpen_rChannel;
merge(BGRchannels_merge, laplacianSharpenImg);
namedWindow("Original - 原始图像", WINDOW_AUTOSIZE);
imshow("Original - 原始图像", image);
namedWindow("Laplacian Sharpen Img", WINDOW_AUTOSIZE);
imshow("Laplacian Sharpen Img", laplacianSharpenImg);
waitKey(1000);
}
处理结果:
实验7、利用 Laplacian模板锐化彩色图像。

(4)实验3、利用Robert模板锐化灰度图像。实验7、利用Robert模板锐化彩色图像。
//实验三:使用Robert锐化
//灰度下:
int robert_Sharpen(Mat src, Mat dst, string title, double c)
{
Mat robertFilterImg = Mat::zeros(src.size(), CV_64F);//滤波后得到的边缘图像
for (int y = 0; y < src.rows - 1; y++)
{
for (int x = 0; x < src.cols - 1; x++)
{
robertFilterImg.at<double>(y, x) =
abs(src.at<uchar>(y + 1, x + 1) - src.at<uchar>(y, x)) + abs(src.at<uchar>(y + 1, x) - src.at<uchar>(y,x+ 1));
dst.at <uchar>(y, x) = saturate_cast<uchar>(src.at<uchar>(y, x) + cvRound(c*robertFilterImg.at<double>(y,x)));
}
}
/*标定Rober滤波得到的边缘结果*/
double maxRob, minRob;
minMaxLoc(robertFilterImg, &minRob, &maxRob, 0, 0);
robertFilterImg.convertTo(robertFilterImg, CV_8U, 255. / (maxRob - minRob), (-255.*minRob) / (maxRob - minRob));
namedWindow(title + "Robert Filter Img", WINDOW_AUTOSIZE);
imshow(title + "Robert Filter Img", robertFilterImg);
namedWindow(title + "Robert Sharpen Img", WINDOW_AUTOSIZE);
imshow(title + "Robert Sharpen Img", dst);
namedWindow(title, WINDOW_AUTOSIZE);
imshow(title, src);
waitKey(3000);
destroyAllWindows();
return 0;
}
实验结果:

实验7、利用Robert 模板锐化彩色图像。
//彩色下:
void robot_rbgfilter(const Mat &image,Mat &gray){
vector<Mat> BGRchannels;
split(image, BGRchannels);
Mat bChannel, gChannel, rChannel;
bChannel = BGRchannels.at(0);
gChannel = BGRchannels.at(1);
rChannel = BGRchannels.at(2);
vector<Mat> BGRchannels_merge(3);
/*Robert*/
double cRob = 1;
Mat robertSharpen_bChannel = Mat::zeros(gray.size(), gray.type());
Mat robertSharpen_gChannel = Mat::zeros(gray.size(), gray.type());
Mat robertSharpen_rChannel = Mat::zeros(gray.size(), gray.type());
Mat robertSharpenImg = Mat::zeros(image.size(), image.type());
robert_Sharpen(bChannel, robertSharpen_bChannel, "B channel ", cRob);
robert_Sharpen(gChannel, robertSharpen_gChannel, "G channel ", cRob);
robert_Sharpen(rChannel, robertSharpen_rChannel, "R channel ", cRob);
BGRchannels_merge.at(0) = robertSharpen_bChannel;
BGRchannels_merge.at(1) = robertSharpen_gChannel;
BGRchannels_merge.at(2) = robertSharpen_rChannel;
merge(BGRchannels_merge, robertSharpenImg);
namedWindow("Original - 原始图像", WINDOW_AUTOSIZE);
imshow("Original - 原始图像", image);
namedWindow("Robert Sharpen Img", WINDOW_AUTOSIZE);
imshow("Robert Sharpen Img", robertSharpenImg);
waitKey(1000);
}
处理结果:

(5)实验3、利用 Sobel 模板锐化灰度图像。实验7、利用Sobel模板锐化彩色图像。
//实验三:sobel下
int SobelSharpen(Mat src, Mat dst, string title, double c)
{
Mat sobelFilterImg = Mat::zeros(src.size(), CV_64F);//滤波后得到的边缘图像
Mat filterArea;
Mat sobelFilter_x= (Mat_<double>(3, 3) <<
-1, 0, 1,
-2, 0, 2,
-1, 0, 1);
Mat sobelFilter_y = (Mat_<double>(3, 3) <<
-1, -2, -1,
0, 0, 0,
1, 2, 1);
for (int y = 1; y < src.rows - 1; y++)
{
for (int x = 1; x < src.cols - 1; x++)
{
filterArea = src(Range(y - 1, y + 1 + 1), Range(x - 1, x + 1 + 1));
sobelFilterImg.at<double>(y, x) = abs(LinearFilterCalc(filterArea, sobelFilter_x)) + abs(LinearFilterCalc(filterArea, sobelFilter_y));
dst.at <uchar>(y, x) = saturate_cast<uchar>(src.at<uchar>(y, x) + cvRound(c*sobelFilterImg.at<double>(y, x)));
}
}
/*标定Sobel滤波得到的边缘结果*/
double maxSob, minSob;
minMaxLoc(sobelFilterImg, &minSob, &maxSob, 0, 0);
sobelFilterImg.convertTo(sobelFilterImg, CV_8U, 255. / (maxSob - minSob), (-255.*minSob) / (maxSob - minSob));
if (title != "")//标题不空则显示结果
{
namedWindow(title + "Sobel Filter Img", WINDOW_AUTOSIZE);
imshow(title + "Sobel Filter Img", sobelFilterImg);
namedWindow(title + "Sobel Sharpen Img", WINDOW_AUTOSIZE);
imshow(title + "Sobel Sharpen Img", dst);
namedWindow(title, WINDOW_AUTOSIZE);
imshow(title, src);
waitKey(1000);
destroyAllWindows();
}
return 0;
}
对灰度图像处理:

实验7、利用Sobel 模板锐化彩色图像。
//Sobel彩色下
void sobel_rbgfilter(const Mat &image,Mat &gray){
vector<Mat> BGRchannels;
split(image, BGRchannels);
Mat bChannel, gChannel, rChannel;
bChannel = BGRchannels.at(0);
gChannel = BGRchannels.at(1);
rChannel = BGRchannels.at(2);
vector<Mat> BGRchannels_merge(3);
/*Sobel*/
double cSob = 0.5;
Mat sobelSharpen_bChannel = Mat::zeros(gray.size(), gray.type());
Mat sobelSharpen_gChannel = Mat::zeros(gray.size(), gray.type());
Mat sobelSharpen_rChannel = Mat::zeros(gray.size(), gray.type());
Mat sobelSharpenImg = Mat::zeros(image.size(), image.type());
SobelSharpen(bChannel, sobelSharpen_bChannel, "B channel ", cSob);
SobelSharpen(gChannel, sobelSharpen_gChannel, "G channel ", cSob);
SobelSharpen(rChannel, sobelSharpen_rChannel, "R channel ", cSob);
BGRchannels_merge.at(0) = sobelSharpen_bChannel;
BGRchannels_merge.at(1) = sobelSharpen_gChannel;
BGRchannels_merge.at(2) = sobelSharpen_rChannel;
merge(BGRchannels_merge, sobelSharpenImg);
namedWindow("Original - 原始图像", WINDOW_AUTOSIZE);
imshow("Original - 原始图像", image);
namedWindow("Sobel Sharpen Img", WINDOW_AUTOSIZE);
imshow("Sobel Sharpen Img", sobelSharpenImg);
waitKey(1000);
}
彩色Sobel实现结果:

(6)实验4、利用高提升滤波算法增强灰度图像。
用原图像减去平滑后的图像得到边缘,然后再用得到的边缘增强原图像。
//实验四:利用高提升滤波算法增强灰度图像
int HighboostFilterProcessing(Mat &gray)
{
double k = 1.5;//k>1时为高提升滤波
Mat meanFilter_3x3 = ((double)1 / 9)*Mat::ones(3, 3, CV_64F);//CV_64F对应double,若CV_32F对饮double会报错
Mat filter;
filter=meanFilter_3x3;
Mat highboostFilterImg = Mat::zeros(gray.size(), gray.type());
Mat unsharpMask= Mat::zeros(gray.size(), CV_64F);//非锐化掩蔽
Mat blurImg = Mat::zeros(gray.size(), gray.type());
FilterProcessing(gray, blurImg, filter, LinearFilterCalc);
gray.convertTo(gray, CV_64F);
blurImg.convertTo(blurImg, CV_64F);
unsharpMask = gray - blurImg;
gray.convertTo(gray, CV_8U);
for (int y = 0; y < highboostFilterImg.rows; y++)
{
for (int x = 0; x < highboostFilterImg.cols; x++)
{
highboostFilterImg.at <uchar>(y, x) = saturate_cast<uchar>(gray.at<uchar>(y, x) + k*unsharpMask.at<double>(y, x));
}
}
//标定 scaling unsharp mask
double maxMast, minMast;
minMaxLoc(unsharpMask, &minMast, &maxMast, 0, 0);
unsharpMask.convertTo(unsharpMask, CV_8U, 255. / (maxMast - minMast), (-255.*minMast) / (maxMast - minMast));
namedWindow("Gray - 灰度图像", WINDOW_AUTOSIZE);
imshow("Gray - 灰度图像", gray);
namedWindow("Unsharp Mask with scaling", WINDOW_AUTOSIZE);
imshow("Unsharp Mask with scaling", unsharpMask);
namedWindow("Highboost Filter Img", WINDOW_AUTOSIZE);
imshow("Highboost Filter Img", highboostFilterImg);
waitKey(0);
destroyAllWindows();
return 0;
}
增强后实现结果:

完整代码:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#include <vector>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
using namespace cv;
//函数声明
Mat Filter(const Mat &src, Mat &dst, int ksize, double** templateMatrix);
void MeanFilter(const Mat &src, Mat &dst, int ksize);
void GaussianFilter(const Mat &src, Mat &dst, int ksize, double sigma);
double LinearFilterCalc(Mat filterArea, Mat linearFilter);
int FilterProcessing(Mat src, Mat dst, Mat filter,double ProcessingMethod(Mat filterArea, Mat filter));
int LaplacianFilterProcessing(Mat src, Mat dst, Mat laplacianFilter, Mat laplacianFilterImg, double c);
int LaplacianSharpen(Mat src, Mat dst, string title, double c, int filterNum);
void laplacia_rbgfilter(const Mat &image,Mat &gray);
int robert_Sharpen(Mat src, Mat dst, string title, double c);
void robot_rbgfilter(const Mat &image,Mat &gray);
int SobelSharpen(Mat src, Mat dst, string title, double c);
void sobel_rbgfilter(const Mat &image,Mat &gray);
int HighboostFilterProcessing(Mat &gray);
//主函数实现
int main(int argc,char* argv[]){
const char *imageName="/Users/Admin/Desktop/myProject/3.jpg";
Mat img,grayImage;
//读入彩色图片
img=imread(imageName);
//读入灰度图片
grayImage=imread(imageName,0);
imshow("grayImage", grayImage);
waitKey(1000);
char flag='1';
cout << "1. 利用均值模板平滑灰度图像\n";
cout << "2. 利用高斯模板平滑灰度图像\n";
cout << "3. 利用 Laplacian 模板锐化灰度图像\n";
cout << "4. 利用 Robert 模板锐化灰度图像\n";
cout << "5. 利用 Sobel 模板锐化灰度图像\n";
cout << "6. 利用高提升滤波算法增强灰度图像\n";
cout << "*************\n";
cout << "a. 利用均值模板平滑彩色图像\n";
cout << "b. 利用高斯模板平滑彩色图像\n";
cout << "c. 利用 Laplacian 模板锐化彩色图像\n";
cout << "d. 利用 Robert 模板锐化彩色图像\n";
cout << "e. 利用 Sobel 模板锐化彩色图像\n";
while(true){
cout<<"\n请输入实验编号:";
cin>>flag;
switch (flag) {
case '1':
{
cout << "1. 利用均值模板平滑灰度图像\n";
Mat dst1;
dst1=grayImage.clone();
//改变ksize不同的值使其变成不同尺寸的均值模版
MeanFilter(grayImage,dst1,3);
break;
}
case '2':
{
cout << "2. 利用高斯模板平滑灰度图像\n";
Mat dst2;
dst2=grayImage.clone();
//参数:(const Mat &src,Mat &dst,int ksize,double sigma)
GaussianFilter(grayImage, dst2, 3, 2);
break;
}
case '3':
{
cout << "3. 利用 Laplacian 模板锐化灰度图像\n";
Mat dst3;
dst3=grayImage.clone();
LaplacianSharpen(grayImage,dst3,"LaplacianSharpen", 1, 1);
break;
}
case '4':
{
cout << "4. 利用 Robert 模板锐化灰度图像\n";
Mat dst4;
dst4=grayImage.clone();
//robert_filter(img);
robert_Sharpen(grayImage,dst4, "case 4", 1);
break;
}
case '5':
{
cout << "5. 利用 Sobel 模板锐化灰度图像\n";
Mat dst5;
dst5=grayImage.clone();
SobelSharpen(grayImage,dst5, "05", 1);
break;
}
case '6':
{
cout << "6. 利用高提升滤波算法增强灰度图像\n";
Mat dst6;
dst6=grayImage.clone();
HighboostFilterProcessing(dst6);
}
case 'a':
{
cout << "7. 利用均值模板平滑彩色图像\n";
Mat dst7;
dst7=img.clone();
//改变ksize不同的值使其变成不同尺寸的均值模版
MeanFilter(img,dst7,3);
break;
}
case 'b':
{
cout << "b. 利用高斯模板平滑彩色图像\n";
Mat dst8;
dst8=img.clone();
//ksize,sigma
GaussianFilter(img, dst8, 3, 2);
break;
}
case 'c':
{
cout << "c. 利用 Laplacian 模板锐化彩色图像\n";
Mat dst9;
dst9=grayImage.clone();
laplacia_rbgfilter(img,dst9);
break;
}
case 'd':
{
cout << "d. 利用 Robert 模板锐化彩色图像\n";
Mat dst0;
dst0=grayImage.clone();
robot_rbgfilter(img,dst0);
break;
}
case 'e':
cout << "e. 利用 Sobel 模板锐化彩色图像\n";
Mat dsta;
dsta=grayImage.clone();
sobel_rbgfilter(img,dsta);
break;
}
}
return 0;
}
//利用模版进行平滑处理
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;
}
//实验一:
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);
}
//实验二:利用高斯模板平滑灰度图像。
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);
}
//实验三:使用拉普拉斯进行锐化
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, 0, 0);
laplacianFilterImg.convertTo(laplacianFilterImg, CV_8U, 255. / (maxLap - minLap), (-255.*minLap) / (maxLap - minLap));
if (title.compare("") != 0)//标题不空则显示结果
{
namedWindow(title + "Laplacian Filter Img" + filterTitle, WINDOW_AUTOSIZE);
imshow(title + "Laplacian Filter Img" + filterTitle, laplacianFilterImg);
namedWindow(title + "Laplacian Sharpen Img" + filterTitle, WINDOW_AUTOSIZE);
imshow(title + "Laplacian Sharpen Img" + filterTitle, dst);
namedWindow(title, WINDOW_AUTOSIZE);
imshow(title, src);
waitKey(3000);
destroyAllWindows();
}
return 0;
}
void laplacia_rbgfilter(const Mat &image,Mat &gray){
vector<Mat> BGRchannels;
split(image, BGRchannels);
Mat bChannel, gChannel, rChannel;
bChannel = BGRchannels.at(0);
gChannel = BGRchannels.at(1);
rChannel = BGRchannels.at(2);
vector<Mat> BGRchannels_merge(3);
/*Laplacian*/
int lablacianFilterNum = 1;//1为中心为-4的laplacian模板,2为中心为-8的
double cLap = -1;
Mat laplacianSharpen_bChannel = Mat::zeros(gray.size(), gray.type());
Mat laplacianSharpen_gChannel = Mat::zeros(gray.size(), gray.type());
Mat laplacianSharpen_rChannel = Mat::zeros(gray.size(), gray.type());
Mat laplacianSharpenImg = Mat::zeros(image.size(), image.type());
LaplacianSharpen(bChannel, laplacianSharpen_bChannel, "B channel ", cLap, lablacianFilterNum);
LaplacianSharpen(gChannel, laplacianSharpen_gChannel, "G channel ", cLap, lablacianFilterNum);
LaplacianSharpen(rChannel, laplacianSharpen_rChannel, "R channel ", cLap, lablacianFilterNum);
BGRchannels_merge.at(0) = laplacianSharpen_bChannel;
BGRchannels_merge.at(1) = laplacianSharpen_gChannel;
BGRchannels_merge.at(2) = laplacianSharpen_rChannel;
merge(BGRchannels_merge, laplacianSharpenImg);
namedWindow("Original - 原始图像", WINDOW_AUTOSIZE);
imshow("Original - 原始图像", image);
namedWindow("Laplacian Sharpen Img", WINDOW_AUTOSIZE);
imshow("Laplacian Sharpen Img", laplacianSharpenImg);
waitKey(1000);
}
//实验三:使用Robert锐化
//灰度下:
int robert_Sharpen(Mat src, Mat dst, string title, double c)
{
Mat robertFilterImg = Mat::zeros(src.size(), CV_64F);//滤波后得到的边缘图像
for (int y = 0; y < src.rows - 1; y++)
{
for (int x = 0; x < src.cols - 1; x++)
{
robertFilterImg.at<double>(y, x) =
abs(src.at<uchar>(y + 1, x + 1) - src.at<uchar>(y, x)) + abs(src.at<uchar>(y + 1, x) - src.at<uchar>(y,x+ 1));
dst.at <uchar>(y, x) = saturate_cast<uchar>(src.at<uchar>(y, x) + cvRound(c*robertFilterImg.at<double>(y,x)));
}
}
/*标定Rober滤波得到的边缘结果*/
double maxRob, minRob;
minMaxLoc(robertFilterImg, &minRob, &maxRob, 0, 0);
robertFilterImg.convertTo(robertFilterImg, CV_8U, 255. / (maxRob - minRob), (-255.*minRob) / (maxRob - minRob));
namedWindow(title + "Robert Filter Img", WINDOW_AUTOSIZE);
imshow(title + "Robert Filter Img", robertFilterImg);
namedWindow(title + "Robert Sharpen Img", WINDOW_AUTOSIZE);
imshow(title + "Robert Sharpen Img", dst);
namedWindow(title, WINDOW_AUTOSIZE);
imshow(title, src);
waitKey(3000);
destroyAllWindows();
return 0;
}
//彩色下:
void robot_rbgfilter(const Mat &image,Mat &gray){
vector<Mat> BGRchannels;
split(image, BGRchannels);
Mat bChannel, gChannel, rChannel;
bChannel = BGRchannels.at(0);
gChannel = BGRchannels.at(1);
rChannel = BGRchannels.at(2);
vector<Mat> BGRchannels_merge(3);
/*Robert*/
double cRob = 1;
Mat robertSharpen_bChannel = Mat::zeros(gray.size(), gray.type());
Mat robertSharpen_gChannel = Mat::zeros(gray.size(), gray.type());
Mat robertSharpen_rChannel = Mat::zeros(gray.size(), gray.type());
Mat robertSharpenImg = Mat::zeros(image.size(), image.type());
robert_Sharpen(bChannel, robertSharpen_bChannel, "B channel ", cRob);
robert_Sharpen(gChannel, robertSharpen_gChannel, "G channel ", cRob);
robert_Sharpen(rChannel, robertSharpen_rChannel, "R channel ", cRob);
BGRchannels_merge.at(0) = robertSharpen_bChannel;
BGRchannels_merge.at(1) = robertSharpen_gChannel;
BGRchannels_merge.at(2) = robertSharpen_rChannel;
merge(BGRchannels_merge, robertSharpenImg);
namedWindow("Original - 原始图像", WINDOW_AUTOSIZE);
imshow("Original - 原始图像", image);
namedWindow("Robert Sharpen Img", WINDOW_AUTOSIZE);
imshow("Robert Sharpen Img", robertSharpenImg);
waitKey(1000);
}
//实验三:sobel下
int SobelSharpen(Mat src, Mat dst, string title, double c)
{
Mat sobelFilterImg = Mat::zeros(src.size(), CV_64F);//滤波后得到的边缘图像
Mat filterArea;
Mat sobelFilter_x= (Mat_<double>(3, 3) <<
-1, 0, 1,
-2, 0, 2,
-1, 0, 1);
Mat sobelFilter_y = (Mat_<double>(3, 3) <<
-1, -2, -1,
0, 0, 0,
1, 2, 1);
for (int y = 1; y < src.rows - 1; y++)
{
for (int x = 1; x < src.cols - 1; x++)
{
filterArea = src(Range(y - 1, y + 1 + 1), Range(x - 1, x + 1 + 1));
sobelFilterImg.at<double>(y, x) = abs(LinearFilterCalc(filterArea, sobelFilter_x)) + abs(LinearFilterCalc(filterArea, sobelFilter_y));
dst.at <uchar>(y, x) = saturate_cast<uchar>(src.at<uchar>(y, x) + cvRound(c*sobelFilterImg.at<double>(y, x)));
}
}
/*标定Sobel滤波得到的边缘结果*/
double maxSob, minSob;
minMaxLoc(sobelFilterImg, &minSob, &maxSob, 0, 0);
sobelFilterImg.convertTo(sobelFilterImg, CV_8U, 255. / (maxSob - minSob), (-255.*minSob) / (maxSob - minSob));
if (title != "")//标题不空则显示结果
{
namedWindow(title + "Sobel Filter Img", WINDOW_AUTOSIZE);
imshow(title + "Sobel Filter Img", sobelFilterImg);
namedWindow(title + "Sobel Sharpen Img", WINDOW_AUTOSIZE);
imshow(title + "Sobel Sharpen Img", dst);
namedWindow(title, WINDOW_AUTOSIZE);
imshow(title, src);
waitKey(1000);
destroyAllWindows();
}
return 0;
}
//Sobel彩色下
void sobel_rbgfilter(const Mat &image,Mat &gray){
vector<Mat> BGRchannels;
split(image, BGRchannels);
Mat bChannel, gChannel, rChannel;
bChannel = BGRchannels.at(0);
gChannel = BGRchannels.at(1);
rChannel = BGRchannels.at(2);
vector<Mat> BGRchannels_merge(3);
/*Sobel*/
double cSob = 0.5;
Mat sobelSharpen_bChannel = Mat::zeros(gray.size(), gray.type());
Mat sobelSharpen_gChannel = Mat::zeros(gray.size(), gray.type());
Mat sobelSharpen_rChannel = Mat::zeros(gray.size(), gray.type());
Mat sobelSharpenImg = Mat::zeros(image.size(), image.type());
SobelSharpen(bChannel, sobelSharpen_bChannel, "B channel ", cSob);
SobelSharpen(gChannel, sobelSharpen_gChannel, "G channel ", cSob);
SobelSharpen(rChannel, sobelSharpen_rChannel, "R channel ", cSob);
BGRchannels_merge.at(0) = sobelSharpen_bChannel;
BGRchannels_merge.at(1) = sobelSharpen_gChannel;
BGRchannels_merge.at(2) = sobelSharpen_rChannel;
merge(BGRchannels_merge, sobelSharpenImg);
namedWindow("Original - 原始图像", WINDOW_AUTOSIZE);
imshow("Original - 原始图像", image);
namedWindow("Sobel Sharpen Img", WINDOW_AUTOSIZE);
imshow("Sobel Sharpen Img", sobelSharpenImg);
waitKey(1000);
}
//实验四:利用高提升滤波算法增强灰度图像
int HighboostFilterProcessing(Mat &gray)
{
double k = 1.5;//k>1时为高提升滤波
Mat meanFilter_3x3 = ((double)1 / 9)*Mat::ones(3, 3, CV_64F);//CV_64F对应double,若CV_32F对饮double会报错
Mat filter;
filter=meanFilter_3x3;
Mat highboostFilterImg = Mat::zeros(gray.size(), gray.type());
Mat unsharpMask= Mat::zeros(gray.size(), CV_64F);//非锐化掩蔽
Mat blurImg = Mat::zeros(gray.size(), gray.type());
FilterProcessing(gray, blurImg, filter, LinearFilterCalc);
gray.convertTo(gray, CV_64F);
blurImg.convertTo(blurImg, CV_64F);
unsharpMask = gray - blurImg;
gray.convertTo(gray, CV_8U);
for (int y = 0; y < highboostFilterImg.rows; y++)
{
for (int x = 0; x < highboostFilterImg.cols; x++)
{
highboostFilterImg.at <uchar>(y, x) = saturate_cast<uchar>(gray.at<uchar>(y, x) + k*unsharpMask.at<double>(y, x));
}
}
//标定 scaling unsharp mask
double maxMast, minMast;
minMaxLoc(unsharpMask, &minMast, &maxMast, 0, 0);
unsharpMask.convertTo(unsharpMask, CV_8U, 255. / (maxMast - minMast), (-255.*minMast) / (maxMast - minMast));
namedWindow("Gray - 灰度图像", WINDOW_AUTOSIZE);
imshow("Gray - 灰度图像", gray);
namedWindow("Unsharp Mask with scaling", WINDOW_AUTOSIZE);
imshow("Unsharp Mask with scaling", unsharpMask);
namedWindow("Highboost Filter Img", WINDOW_AUTOSIZE);
imshow("Highboost Filter Img", highboostFilterImg);
waitKey(0);
destroyAllWindows();
return 0;
}
本文详细介绍了使用OpenCV进行空域滤波的实验,包括均值和高斯模板平滑灰度及彩色图像,以及Laplacian、Robert、Sobel模板的锐化操作。实验中,作者探讨了通用滤波器的设计,并展示了各滤波效果,如灰度图像的Laplacian锐化和彩色图像的Sobel锐化。

2806

被折叠的 条评论
为什么被折叠?



