实验三 空域滤波

本文详细介绍了使用OpenCV进行空域滤波的实验,包括均值和高斯模板平滑灰度及彩色图像,以及Laplacian、Robert、Sobel模板的锐化操作。实验中,作者探讨了通用滤波器的设计,并展示了各滤波效果,如灰度图像的Laplacian锐化和彩色图像的Sobel锐化。

一、实验目的:

掌握利用模板对图像进行空域滤波操作,熟练掌握常用空域模板的使用。 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值