C++实验6——模板

实验目的

掌握类模板的定义和使用

实验内容

在之前的实验中,我们定义了一个矩阵类Matrix和其子类图像类Image。在数据的存储和处理过程中,我们用过unsigned char和double类型的data指针获取矩阵元素或者图像像素的值。但是现实中的矩阵或者图像数据并不仅仅使用浮点类型和8bits的无符号整数类型,比如有的单反相机可以拍摄32bits无符号整数像素值的图像(unsigned int);在图像处理中经常将图像灰度值缩放到区间[0,1]内的浮点数(double);再比如对图像进行傅里叶变换后,得到是复数。因此矩阵的数据类型可以有很多变化。为了实现代码的重用,现在我们使用类模板重构之前的类。

要求:

  1. 定义类模板Mat描述矩阵,矩阵元素的数据类型可以是任意类型,即二级指针data所指向的数据类型采用模板技术进行泛化。
  2. 参考之前的实验,实现Mat类模板的构造函数、析构函数、拷贝构造函数、运算符重载等各种函数。
  3. 使用“引用计数”机制,实现Mat对象间的“浅拷贝”和“浅赋值”。
  4. 实现该类模板的ReadBMP,WriteBMP等函数。在存储图像文件时,像素值一般选取 unsigned char类型(这也是我们前面实验使用该类型的原因)。但是我们的Mat模板类的数据范围不局限于此,因此需要在这两个函数体内完成数据类型转换操作。即把矩阵的元素转换成[0,255]区间内的整数,然后才能保存成BMP文件。通常的做法是计算所有矩阵元素的最大值和最小值,在WriteBMP函数内将对应的数据分别赋成255和0,其它中间的数据转换成0和255之间的无符号8bit整数。这么做仅仅是为了存储时迁就图片文件的格式要求,丢失了原来数据的精度。
  5. ReadText和WriteText函数把数据写入文本文件,这两个函数在实现时需要特别注意,思考如何才能把不同类型的数据合理在文本文件中写入和读取。先自行设计解决方案,更好的办法在实验10中实现。
  6. 定义成员函数Normalize,该函数返回以double特化的模板类对象,该对象将调用者的数据缩放到[0,1]区间。
  7. 将实验8的滤波器类进行模板化重构,能够适用于Mat类模板。

主函数中实现:

  1. 读入图像文件,并将数据缩放到[0,1]区间
  2. 将图像取反色,并输出显示。
  3. 获取矩阵中某个元素的值。
  4. 对矩阵进行旋转、缩放、裁剪、reshape等操作。
  5. 对矩阵进行加减等操作。
  6. 对矩阵进行滤波,显示并保存成图像文件。
  7. 计算原矩阵和滤波后矩阵的差,并把结果保存。
    #ifndef MAT_H
    #define MAT_H
    #include <iostream>
    #include <cmath>
    #include <fstream>
    
    #pragma pack(push,1)
    struct BMPFILEHEADER
    {
        unsigned short bfType;
        unsigned int   bfSize;
        unsigned short bfReserved1;
        unsigned short bfReserved2;
        unsigned int   bfOffBits;
    };
    #pragma pack(pop)
    
    struct BITMAPINFOHEADER
    {
        unsigned long    biSize;            //本结构所占用字节数 40字节
        long             biWidth;           //位图的宽度,以像素为单位
        long             biHeight;          //位图的高度,以像素为单位
        unsigned short   biPlanes;          //目标设备的级别,必须为1
        unsigned short   biBitCount;        //每个像素所需的位数,必须是1(双色)、
        //4(16色)、8(256色)或24(真彩色)之一
        unsigned long    biCompression;     //位图压缩类型,必须是 0(BI_RGB不压缩)、
        //1(BI_RLE8压缩类型)
        //2(BI_RLE压缩类型)之一
        unsigned long    biSizeImage;       //位图的大小,以字节为单位
        long             biXPelsPerMeter;   //位图水平分辨率,每米像素数
        long             biYPelsPerMeter;   //位图垂直分辨率,每米像素数
        unsigned long    biClrUsed;         //位图实际使用的颜色表中的颜色数
        unsigned long    biClrImportant;    //位图显示过程中重要的颜色数
    };
    
    template< typename T>
    class Mat
    {
    public:
        Mat()//无参数的构造函数,创建行列都为零的Mat对象
        {
            point->height=0;
            point->width=0;
            point->data=NULL;
            point->count=new int[1];
            *point->count=1;
        }
    
        Mat(int h, int w)//构造函数重载,创建h行,w列的Mat对象
        {
            point->height=h;
            point->width=w;
            point->data=new T*[h];
            for(int i=0; i<point->height; i++)
            {
                point->data[i]=new T[w];
            }
            point->count=new int[1];
            *point->count=1;
            for(int i=0; i<h; i++) //赋值
            {
                for(int j=0; j<w; j++)
                {
                    point->data[i][j]=T(0);
                }
            }
        }
    
        Mat(int h, int w, T val) //构造函数重载,矩阵元素的值都为val;
        {
            point->height=h;
            point->width=w;
            point->data=new T*[h];
            for(int i=0; i<point->height; i++)
            {
                point->data[i]=new T[w];
            }
            point->count=new int[1];
            *point->count=1;
            for(int i=0; i<h; i++) //赋值
            {
                for(int j=0; j<w; j++)
                {
                    point->data[i][j]=val;
                }
            }
        }
    
        Mat(const char* ImageName) //构造函数重载,利用文件名从硬盘加载图像文件成为Mat对象;
        {
            FILE* pfin = NULL; // 保存文件的文件指针
            fopen_s(&pfin, ImageName, "rb"); // 二进制写入方式打开文件
            BMPFILEHEADER fileheader;
            BITMAPINFOHEADER infoheader;
            fread(&fileheader, sizeof(BMPFILEHEADER), 1, pfin);
            fread(&infoheader, sizeof(BITMAPINFOHEADER), 1, pfin);
            point->height = infoheader.biHeight;
            point->width = infoheader.biWidth;
    
            int i, j;
            point->data = new T *[point->height];//动态内存开辟
            for (i = 0; i < point->height; i++)
            {
                point->data[i] = new T[point->width];
            }
    
            unsigned char a, b, c;
            for (i = 0; i < point->height; i++)
            {
                for (j = 0; j < point->width; j++)
                {
                    fread(&a, sizeof(unsigned char), 1, pfin);
                    fread(&b, sizeof(unsigned char), 1, pfin);
                    fread(&c, sizeof(unsigned char), 1, pfin);//读出三通道
                    point->data[i][j] = (static_cast<T>(a+b+c)) / 3;
                }//转为灰度图,存入数组,转double
            }
            fclose(pfin);
            point->count=new int[1];
            *point->count=1;
        }
    
        Mat(T **m, int h, int w)//构造函数重载,从动态数组创建Mat对象;
        {
            point->height=h;
            point->width=w;
            point->data=new T*[h];
            for(int i=0; i<point->height; i++)
            {
                point->data[i]=new T[point->width];
            }
            point->count=new int[1];
            *point->count=1;
            for(int i=0; i<h; i++) //赋值
            {
                for(int j=0; j<w; j++)
                {
                    point->data[i][j]=m[i][j];
                }
            }
        }
    
        Mat(const Mat &m) //拷贝构造函数;
        {
            point->count=m.point->count;
            *point->count++;
            point->height=m.point->height;
            point->width=m.point->width;
            point->data=m.point->data;
        }
    
        virtual ~Mat() //析构函数;
        {
            if(--(*point->count)==0)//无论如何count都减1
            {
                for (int i = 0; i < point->height; i++)//释放二维数组空间
                    delete[] point->data[i];
                delete[] point->data;
                delete point->count;
            }
        }
    
        void wcopy()//即时拷贝
        {
            if(*point->count>1)
            {
                T **prep=new T*[point->height];//开辟新空间给prep
                for(int i=0; i<point->height; i++)
                {
                    prep[i]=new T[point->width];
                }
                for(int i=0; i<point->height; i++) //赋值
                {
                    for(int j=0; j<point->width; j++)
                    {
                        prep[i][j]=point->data[i][j];
                    }
                }
                *point->count--; //共用计数器--
                int *prepint = new int[1];
                *prepint = 1;//开辟一个新计数器
                point->count=prepint;
                prepint=NULL;
    
                point->data=prep;
                prep=NULL;
            }
        }
    
        void clean(T **pdata, int h)
        {
            int i;
            for (i = 0; i < h; i++)//释放空间
                delete[] pdata[i];
            delete[] pdata;
        }
    
        void judge_delete()//判断是否有其他对象利用这块空间,若没有,便删除原来的空间,以便改变空间大小
        {
            if(*point->count>1)//有其他对象利用这片空间
            {
                *point->count--; //共用计数器减一
                int *prepint = new int[1];
                *prepint = 1;//开辟一个新计数器
                point->count = prepint;
                prepint=NULL;
            }
            else//否则释放空间
            {
                for(int i=0; i<point->height; i++)
                    delete [] point->data[i];
                delete [] point->data;
            }
        }
    
        void ReadBMP(const char *ImageName) //从硬盘文件中读入图像数据到一个对象
        {
            int i, j;
            FILE* pfin = NULL; // 保存文件的文件指针
            fopen_s(&pfin, ImageName, "rb"); // 二进制写入方式打开文件
            BMPFILEHEADER fileheader;
            BITMAPINFOHEADER infoheader;
            fread(&fileheader, sizeof(BMPFILEHEADER), 1, pfin);
            fread(&infoheader, sizeof(BITMAPINFOHEADER), 1, pfin);
            point->height = infoheader.biHeight;
            point->width = infoheader.biWidth;
    
            if(*point->count>1)
            {
                point->data = new T *[point->height];//动态内存开辟,不破坏原来共享的空间
                for (i = 0; i < point->height; i++)
                {
                    point->data[i] = new T[point->width];
                }
                *point->count--; //共用计数器减一
                int *prepint = new int[1];
                *prepint = 1;//开辟一个新计数器
                point->count=prepint;
            }
    
            unsigned char a, b, c;
            for (i = 0; i < point->height; i++)
            {
                for (j = 0; j < point->width; j++)
                {
                    fread(&a, sizeof(unsigned char), 1, pfin);
                    fread(&b, sizeof(unsigned char), 1, pfin);
                    fread(&c, sizeof(unsigned char), 1, pfin);//读出三通道
                    point->data[i][j] = (static_cast<T>(a+b+c)) / 3;
                }//转为灰度图,存入数组,转double
            }
            fclose(pfin);
        }
    
        void WriteBMP(const char *filename)//将数据保存为图像文件
        {
            FILE* pfout = NULL; // 保存文件的文件指针
            fopen_s(&pfout, filename, "wb"); // 二进制写入方式打开文件
    
            FILE* pfin = NULL; // 保存文件的文件指针
            fopen_s(&pfin, "Fruits.bmp", "rb"); // 打开一个文件,获取文件头和信息头
            BMPFILEHEADER fileheader;
            BITMAPINFOHEADER infoheader;
            fread(&fileheader, sizeof(BMPFILEHEADER), 1, pfin);
            fread(&infoheader, sizeof(BITMAPINFOHEADER), 1, pfin);
    
            bool flag = false;
            while (point->width % 4)
            {
                point->width++;
            }
            infoheader.biWidth = point->width;
            infoheader.biHeight = point->height;
            infoheader.biSizeImage = flag?
                                     ((((point->width * infoheader.biBitCount) + 31) / 32 * 4) * point->height) : point->width * point->height;
    
            fwrite(&fileheader, sizeof(fileheader), 1, pfout);
            fwrite(&infoheader, sizeof(infoheader), 1, pfout);
    
            enlarge();//判断数据范围,若在01之间,转为0到255之间
            int i, j, k;
            for(i=0; i<point->height; i++)
            {
                for(j=0; j<point->width; j++)
                {
                    if (point->data[i][j] > 255)
                        point->data[i][j] = 255;
                    if (point->data[i][j] < 0)
                        point->data[i][j] = 0;
                }
            }
    
            unsigned char prep=0;
            for (i = 0; i < infoheader.biHeight; i++)
            {
                for (j = 0; j < infoheader.biWidth; j++)
                {
                    prep=(unsigned char)(point->data[i][j]);
                    for (k = 0; k < 3; k++)
                        fwrite(&prep,1,1,pfout);
                }
            }
            fclose(pfout);
            fclose(pfin);
        }
    
        void WriteBMP(const char *filename, T** pdata, int h, int w)
        {
            FILE* pfout = NULL; // 保存文件的文件指针
            fopen_s(&pfout, filename, "wb"); // 二进制写入方式打开文件
    
            FILE* pfin = NULL; // 保存文件的文件指针
            fopen_s(&pfin, "Fruits.bmp", "rb"); // 打开一个文件,获取文件头和信息头
            BMPFILEHEADER fileheader;
            BITMAPINFOHEADER infoheader;
            fread(&fileheader, sizeof(BMPFILEHEADER), 1, pfin);
            fread(&infoheader, sizeof(BITMAPINFOHEADER), 1, pfin);
    
            bool flag = false;
            while (w % 4)
            {
                w++;
            }
            infoheader.biWidth = w;
            infoheader.biHeight = h;
            infoheader.biSizeImage = flag?
                                     ((((w * infoheader.biBitCount) + 31) / 32 * 4) * h) : w * h;
    
            fwrite(&fileheader, sizeof(fileheader), 1, pfout);
            fwrite(&infoheader, sizeof(infoheader), 1, pfout);
            int i, j, k;
            unsigned char prep=0;
            for (i = 0; i < infoheader.biHeight; i++)
            {
                for (j = 0; j < infoheader.biWidth; j++)
                {
                    prep=(unsigned char)(pdata[i][j]);
                    for (k = 0; k < 3; k++)
                        fwrite(&prep,1,1,pfout);
                }
            }
            fclose(pfout);
            fclose(pfin);
        }
    
    
    // 下面2个读写文本文件的函数,需要考虑不同数据类型的存储
        void ReadText(const char *fileName) //从文本文件中读入数据
        {
            std::ifstream fin(fileName);
            while(!fin.eof())
            {
                int i,j,k;
                judge_delete();//判断是否有其他对象利用这块空间,若没有,便删除原来的空间,以便改变空间大小
                fin>>point->height;
                fin>>point->width;
                point->data=new T*[point->height];//开辟新空间
                for(i=0; i<point->height; i++)
                {
                    point->data[i]=new T[point->width];
                }
    
                T a,b,c;
                for (i = 0; i < point->height; i++)
                {
                    for (j = 0; j < point->width; j++)
                    {
                        fin>>a;
                        fin>>b;
                        fin>>c;
                        point->data[i][j]=(a+b+c)/3;
                    }
                }
            }
            fin.close();
        }
    
        void WriteText(const char *filename) //将数据保存为文本文件
        {
            std::ofstream fout(filename);
            fout<<point->height;
            fout<<point->width;
            for(int i=0; i<point->height; i++)
            {
                for(int j=0; j<point->width; j++)
                {
                    for (int k = 0; k < 3; k++)
                        fout<<point->data[i][j];
                }
            }
            fout.close();
        }
    
        int Height()//得到矩阵高度
        {
            return point->height;
        }
        int Height() const//得到矩阵高度
        {
            return point->height;
        }
    
        int Width()//得到矩阵宽度
        {
            return point->width;
        }
        int Width() const//得到矩阵宽度
        {
            return point->width;
        }
    
        T Min() //得到矩阵元素的最小值
        {
            T smallest=point->data[0][0];
            for(int i=0; i<point->height; i++)
            {
                for(int j=0; j<point->width; j++)
                {
                    if(point->data[i][j]<smallest)
                        smallest=point->data[i][j];
                }
            }
            return smallest;
        }
    
        T Min() const //得到矩阵元素的最小值
        {
            T smallest=point->data[0][0];
            for(int i=0; i<point->height; i++)
            {
                for(int j=0; j<point->width; j++)
                {
                    if(point->data[i][j]<smallest)
                        smallest=point->data[i][j];
                }
            }
            return smallest;
        }
    
        T Max() //得到矩阵元素的最大值
        {
            T biggest=point->data[0][0];
            for(int i=0; i<point->height; i++)
            {
                for(int j=0; j<point->width; j++)
                {
                    if(point->data[i][j]>biggest)
                        biggest=point->data[i][j];
                }
            }
            return biggest;
        }
        T Max() const //得到矩阵元素的最大值
        {
            T biggest=point->data[0][0];
            for(int i=0; i<point->height; i++)
            {
                for(int j=0; j<point->width; j++)
                {
                    if(point->data[i][j]>biggest)
                        biggest=point->data[i][j];
                }
            }
            return biggest;
        }
    
        T& At(int row, int col)        //获取某点的值
        {
            return point->data[row][col];
        }
    
        const T& At(int row, int col) const//获取某点的值,const重载
        {
            return point->data[row][col];
        }
    
        int Height() const
        {
            return point->height;
        }
        int Width() const
        {
            return point->width;
        }
    
        void Set(int row, int col, T value) //设置元素(row,col)为某值;
        {
            point->data[row][col]=value;
        }
    
        void Set(T value) //设置所有元素为同一值;
        {
            for(int i=0; i<point->height; i++)
            {
                for(int j=0; j<point->width; j++)
                {
                    point->data[i][j]=value;
                }
            }
        }
    
        void Flip(int code) //翻转; 根据code的值:0:左右翻转,1:上下翻转;
        {
            int i, j;
            T **pdata = new T *[point->height];//中间数组
            for (i = 0; i < point->height; i++)
            {
                pdata[i] = new T[point->width];
            }
    
            if (code == 0)
            {
                for (i = 0; i < point->height; i++)
                {
                    for (j = 0; j < point->width; j++)
                    {
                        pdata[i][point->width - j - 1] = point->data[i][j];
                    }
                }
                wcopy();//即时拷贝
                for (i = 0; i < point->height; i++)
                {
                    for (j = 0; j < point->width; j++)
                    {
                        point->data[i][j] = pdata[i][j];
                    }
                }
                WriteBMP("Flipliftright.bmp");
            }
    
            if (code == 1)
            {
                for (i = 0; i < point->height; i++)
                {
                    for (j = 0; j < point->width; j++)
                    {
                        pdata[point->height - 1 - i][j] = point->data[i][j];
                    }
                }
                wcopy();//即时拷贝
                for (i = 0; i < point->height; i++)
                {
                    for (j = 0; j < point->width; j++)
                    {
                        point->data[i][j] = pdata[i][j];
                    }
                }
                WriteBMP("Flipupdown.bmp");
            }
            clean(pdata, point->height);
        }
    
        void Resize(int code) //缩放0小1大
        {
            int i,j;
            if (code == 0)
            {
                T **pdata = new T *[point->height / 2];//中间数组
                for (i = 0; i < point->height / 2; i++)
                {
                    pdata[i] = new T[point->width / 2];
                }
                for (i = 0; i * 2 < point->height; i++)
                {
                    for (j = 0; j * 2 < point->width; j++)
                    {
                        pdata[i][j] = point->data[i * 2][j * 2];
                    }
                }
                judge_delete();//判断是否有其他对象利用这块空间,若没有,删除原来的空间,以便改变空间大小
                point->height/=2;
                point->width/=2;
                point->data=new T*[point->height];//开辟新空间
                for(i=0; i<point->height; i++)
                {
                    point->data[i]=new T[point->width];
                }
                for (i = 0; i < point->height; i++)
                {
                    for (j = 0; j < point->width; j++)
                    {
                        point->data[i][j] = pdata[i][j];
                    }
                }
                WriteBMP("Resize smaller.bmp");
                clean(pdata, point->height);
            }
    
            if (code == 1)
            {
                T **pdata = new T *[2 * point->height];
                for (i = 0; i < 2 * point->height; i++)
                {
                    pdata[i] = new T[2 * point->width];
                }
                for (i = 0; i < point->height; i++)
                {
                    for (j = 0; j < point->width; j++)
                    {
                        pdata[i * 2][j * 2] = point->data[i][j];
                        pdata[i * 2 + 1][j * 2] = point->data[i][j];
                        pdata[i * 2][j * 2 + 1] = point->data[i][j];
                        pdata[i * 2 + 1][j * 2 + 1] = point->data[i][j];  //原来的一个像素变四个
                    }
                }
                judge_delete();//判断是否有其他对象利用这块空间,若没有,删除原来的空间,以便改变空间大小
                point->height*=2;
                point->width*=2;
                point->data=new T*[point->height];//开辟新空间
                for(i=0; i<point->height; i++)
                {
                    point->data[i]=new T[point->width];
                }
                for (i = 0; i < point->height; i++)
                {
                    for (j = 0; j < point->width; j++)
                    {
                        point->data[i][j] = pdata[i][j];
                    }
                }
                WriteBMP("Resize bigger.bmp");
                clean(pdata, point->height);
            }
        }
    
        void Resize(int h,int w)
        {
            int oldw = point->width;
            int oldh = point->height;
            int neww = w;
            int newh = h;
    
            if (ceil(neww * 1.0 / oldw) <= 2)//width满足条件,只考虑height
            {
                if (ceil(newh * 1.0 / oldh) <= 2)//height满足条件
                {
                    Resize(newh, neww, 1);
                }
                else//height不满足条件
                {
                    int cnt = newh / oldh;//需要循环次数
                    int temph = oldh;//另暂时的h等于原来的h
                    for (int i = 0; i < cnt - 1; i++)
                    {
                        temph += oldh;//每次加上一个原来的h,就能保证满足条件
                        Resize(temph, neww, 1);
                    }
                    Resize(temph + (newh%oldh), neww, 1);//最后在加上多出来又不足一个h的部分
                }
            }
            else//width不满足条件
            {
                if (ceil(newh * 1.0 / oldh) <= 2)//height满足条件
                {
                    int cnt = neww / oldw;
                    int tempw = oldw;
                    for (int i = 0; i < cnt - 1; i++)
                    {
                        tempw += oldw;
                        Resize(newh, tempw, 1);
                    }
                    Resize(newh, tempw + (neww%oldw), 1);
                }
                else//height不满足条件
                {
                    int cnt = newh / oldh;
                    int temph = oldh;
                    for (int i = 0; i < cnt - 1; i++)
                    {
                        temph += oldh;
                        Resize(temph, oldw, 1);
                    }
                    Resize(temph + (newh%oldh), oldw, 1);
    
                    cnt = neww / oldw;
                    int tempw = oldw;
                    for (int i = 0; i < cnt - 1; i++)
                    {
                        tempw += oldw;
                        Resize(newh, tempw, 1);
                    }
                    Resize(newh, tempw + (neww%oldw), 1);
                }
            }
        }
        void Resize(int h,int w,int)
        {
            //记录原有的h,w
            int oldh = h;
            int oldw = w;
    
            //记录原来的尺寸
            int width = point->width;
            int height = point->height;
            //新值与原值的差值
            int dw = static_cast<int>(fabs(width - w));
            int dh = static_cast<int>(fabs(height - h));
            //插入的间隔
            if (dw < 1)//防止dw == 0
            {
                dw = 1;
            }
            if (dh < 1)
            {
                dh = 1;
            }
            int maxw = w > width ? w : width;
            int maxh = h > height ? h : height;
            int difw = maxw / dw;
            int difh = maxh / dh;
    
            T** data = new T*[h];
            for(int i=0; i<h; i++)
            {
                data[i]=new T*[w];
            }
            for (int i = 0, prii = 0; i < h; i++)
            {
                if ((i + 1) % difh == 0)
                {
                    if (h < height)
                    {
                        prii++;
                    }
                    else
                    {
                        continue;
                    }
                }
                for (int j = 0, prij = 0; j < w; j++)
                {
                    if ((j + 1) % difw == 0)
                    {
                        if (w < width)
                        {
                            prij++;//指定 增/删 列跳过
                        }
                        else
                        {
                            continue;
                        }
                    }
                    data[i][j] = point->m_data[prii][prij];
                    if (prij < width - 1)
                        prij++;
                }
                if (prii < height - 1)
                    prii++;
            }
            //填充跳过的指定增行/列
            if (w > width)//先填充列
            {
                for (int i = 0; i < h; i++)
                {
                    for (int j = 0; j < w; j++)
                    {
                        if ((j + 1) % difw == 0)
                        {
                            data[i][j] = data[i][j - 1];//指定 增 列填充
                        }
                    }
                }
            }
    
            if (h > height)//再填充行
            {
                for (int i = 0; i < h; i++)
                {
                    if ((i + 1) % difh == 0)//指定 增 行填充
                    {
                        for (int j = 0; j < w; j++)
                        {
                            data[i][j] = data[i - 1][j];
                        }
                    }
                }
            }
    
        }
    
        void Crop(int x1, int y1, int x2, int y2) //裁剪点(x1,y1)到点(x2,y2)
        {
            if (x2 > x1 && y2 > y1)
            {
                int h = y2 - y1 + 1;
                int w = x2 - x1 + 1;
                while (w % 4)
                {
                    w++;
                }
                int i, j;
                T **pdata = new T *[h];
                for (i = 0; i < h; i++)
                {
                    pdata[i] = new T[w];
                }
    
                int m,n;
                for(i=y1,m=0; i<=y2; i++,m++)
                {
                    for(j=x1,n=0; j<=x2; j++,n++)
                    {
                        pdata[m][n]=point->data[i][j];
                    }
                }
                judge_delete();//判断是否有其他对象利用这块空间,若没有,删除原来的空间,以便改变空间大小
                point->height=h;
                point->width=w;
                point->data=new T*[point->height];//开辟新空间
                for(i=0; i<point->height; i++)
                {
                    point->data[i]=new T[point->width];
                }
                for (i = 0; i < point->height; i++)
                {
                    for (j = 0; j < point->width; j++)
                    {
                        point->data[i][j] = pdata[i][j];
                    }
                }
                WriteBMP("cutImage.bmp");
                clean(pdata, h);
            }
            else
            {
                puts("输入坐标有误");
            }
        }
    
        void Rotate(int degree) //旋转,90度的整数倍
        {
            int i, j;
            if(degree%360==0)//还是原图
            {
                WriteBMP("rotate0.bmp");//保存图片
            }
    
            else if(degree<0)
            {
                if ((degree%90==0)&&(degree%180!=0)&&(degree%270!=0))
                {
                    T **pdata = new T *[point->width];
                    for (i = 0; i < point->width; i++)
                    {
                        pdata[i] = new T[point->height];
                    }
                    for (i = 0; i < point->width; i++)
                    {
                        for (j = 0; j < point->height; j++)
                        {
                            pdata[i][j] = point->data[point->height - j - 1][i];
                        }
                    }
                    judge_delete();
                    int prep=point->height; //交换
                    point->height=point->width;
                    point->width=prep;
                    point->data=new T*[point->height];//开辟新空间
                    for(i=0; i<point->height; i++)
                    {
                        point->data[i]=new T[point->width];
                    }
                    for (i = 0; i < point->height; i++)
                    {
                        for (j = 0; j < point->width; j++)
                        {
                            point->data[i][j] = pdata[i][j];
                        }
                    }
                    WriteBMP("rotate-90.bmp");
                    clean(pdata, point->width);
                }
    
                else if ((degree %180==0)&&(degree%270!=0))
                {
                    int i, j;
                    T **pdata = new T *[point->height];
                    for (i = 0; i < point->height; i++)
                    {
                        pdata[i] = new T[point->width];
                    }
                    for (i = 0; i < point->height; i++)
                    {
                        for (j = 0; j < point->width; j++)
                        {
                            pdata[point->height-i-1][point->width - j - 1] = point->data[i][j];
                        }
                    }
                    judge_delete();
                    point->data=new T*[point->height];//开辟新空间
                    for(i=0; i<point->height; i++)
                    {
                        point->data[i]=new T[point->width];
                    }
                    for (i = 0; i < point->height; i++)
                    {
                        for (j = 0; j < point->width; j++)
                        {
                            point->data[i][j] = pdata[i][j];
                        }
                    }
                    //保存图片
                    WriteBMP("rotate-180.bmp");
                    clean(pdata, point->height);
                }
    
                else if (degree %270==0)
                {
                    T **pdata = new T *[point->width];
                    for (i = 0; i < point->width; i++)
                    {
                        pdata[i] = new T[point->height];
                    }
                    for (int i = 0; i < point->width; i++)
                    {
                        for (int j = 0; j < point->height; j++)
                        {
                            pdata[i][j] = point->data[j][point->width - i - 1];
                        }
                    }
                    judge_delete();
                    int prep=point->height; //交换
                    point->height=point->width;
                    point->width=prep;
                    point->data=new T*[point->height];//开辟新空间
                    for(i=0; i<point->height; i++)
                    {
                        point->data[i]=new T[point->width];
                    }
                    for (i = 0; i < point->height; i++)
                    {
                        for (j = 0; j < point->width; j++)
                        {
                            point->data[i][j] = pdata[i][j];
                        }
                    }
                    //保存图片
                    WriteBMP("rotate-270.bmp");
                    clean(pdata, point->width);
                }
            }
    
            else if(degree>0)
            {
                if ((degree%90==0)&&(degree%180!=0)&&(degree%270!=0))
                {
                    T **pdata = new T *[point->width];
                    for (i = 0; i < point->width; i++)
                    {
                        pdata[i] = new T[point->height];
                    }
                    for (i = 0; i < point->width; i++)
                    {
                        for (j = 0; j < point->height; j++)
                        {
                            pdata[i][j] = point->data[j][point->width - i - 1];
                        }
                    }
                    judge_delete();
                    int prep=point->height; //交换
                    point->height=point->width;
                    point->width=prep;
                    point->data=new T*[point->height];//开辟新空间
                    for(i=0; i<point->height; i++)
                    {
                        point->data[i]=new T[point->width];
                    }
                    for (i = 0; i < point->height; i++)
                    {
                        for (j = 0; j < point->width; j++)
                        {
                            point->data[i][j] = pdata[i][j];
                        }
                    }
                    //保存图片
                    WriteBMP("rotate90.bmp");
                    clean(pdata, point->width);
                }
    
                else if ((degree %180==0)&&(degree%270!=0))
                {
                    int i, j;
                    T **pdata = new T *[point->height];
                    for (i = 0; i < point->height; i++)
                    {
                        pdata[i] = new T[point->width];
                    }
                    for (i = 0; i < point->height; i++)
                    {
                        for (j = 0; j < point->width; j++)
                        {
                            pdata[point->height-i-1][point->width - j - 1] = point->data[i][j];
                        }
                    }
                    judge_delete();
                    point->data=new T*[point->height];//开辟新空间
                    for(i=0; i<point->height; i++)
                    {
                        point->data[i]=new T[point->width];
                    }
                    for (i = 0; i < point->height; i++)
                    {
                        for (j = 0; j < point->width; j++)
                        {
                            point->data[i][j] = pdata[i][j];
                        }
                    }
                    //保存图片
                    WriteBMP("rotate180.bmp", pdata, point->height, point->width);
                    clean(pdata, point->height);
                }
    
                else if (degree %270==0)
                {
                    T **pdata = new T *[point->width];
                    for (i = 0; i < point->width; i++)
                    {
                        pdata[i] = new T[point->height];
                    }
    
                    for (int i = 0; i < point->width; i++)
                    {
                        for (int j = 0; j < point->height; j++)
                        {
                            pdata[i][j] = point->data[point->height - j - 1][i];
                        }
                    }
                    judge_delete();
                    int prep=point->height; //交换
                    point->height=point->width;
                    point->width=prep;
                    point->data=new T*[point->height];//开辟新空间
                    for(i=0; i<point->height; i++)
                    {
                        point->data[i]=new T[point->width];
                    }
                    for (i = 0; i < point->height; i++)
                    {
                        for (j = 0; j < point->width; j++)
                        {
                            point->data[i][j] = pdata[i][j];
                        }
                    }
                    //保存图片
                    WriteBMP("rotate270.bmp");
                    clean(pdata, point->width);
                }
            }
            else
            {
                puts("输入的角度不是90的整数倍");
            }
        }
    
        void Transpose()  // 转置
        {
            int i, j;
            T** pdata = new T*[point->width];
            for (i = 0; i < point->width; i++)
            {
                pdata[i] = new T[point->height];
            }
            for (i = 0; i < point->width; i++)
            {
                for (j = 0; j < point->height; j++)
                {
                    pdata[i][j] = point->data[j][i];
                }
            }
            judge_delete();
            int prep=point->height; //交换
            point->height=point->width;
            point->width=prep;
            point->data=new T*[point->height];//开辟新空间
            for(i=0; i<point->height; i++)
            {
                point->data[i]=new T[point->width];
            }
            for (i = 0; i < point->height; i++)
            {
                for (j = 0; j < point->width; j++)
                {
                    point->data[i][j] = pdata[i][j];
                }
            }
            WriteBMP("transpose.bmp");
            clean(pdata, point->width);
        }
    
        void Reshape(int h, int w) //在元素总数不变的情况下,将矩阵的行列变为参数给定的大小
        {
            int i, j;
            int scale = h * w;
            if (scale == h * w)
            {
                T* a = new T[scale];//变量做大小得用动态内存开辟
                for (i = 0; i < point->height; i++)
                {
                    for (j = 0; j < point->width; j++)
                    {
                        a[i*point->width + j] = point->data[i][j];
                    }
                }
                judge_delete();
                point->height = h;
                point->width = w;
                point->data=new T*[point->height];//开辟新空间
                for(i=0; i<point->height; i++)
                {
                    point->data[i]=new T[point->width];
                }
                for (i = 0; i < point->height; i++)
                {
                    for (j = 0; j < point->width; j++)
                    {
                        point->data[i][j] = a[i*point->width + j];
                    }
                }
                WriteBMP("Reshape.bmp");
                delete[] a;
            }
            else
                printf("总数不一致");
        }
    
        bool IsEmpty()// 判断是否为空矩阵
        {
            if (point->width == 0 && point->height == 0)
                return 1;
            else
                return 0;
        }
    
        bool IsSquare()// 判断矩阵是否为方阵
        {
            if (point->height = point->width)
                return 1;
            else
                return 0;
        }
    
        Mat<T>  MajorDiagonal()// 求主对角线上的元素,输出一个N行1列的矩阵,N为主对角线上元素的个数
        {
            Mat<T> prep(point->height,1);
            for (int i = 0; i < point->height; i++)
            {
                prep.point->data[i][0] = point->data[i][i];
            }
            return prep;
        }
    
        Mat<T> MinorDiagonal()// 求副对角线上的元素,输出一个N行1列的矩阵,N为副对角线上元素的个数
        {
            Mat<T> prep(point->height,1);
            for (int i = 0; i < point->height; i++)
            {
                for (int j = 0; j < point->width; j++)
                {
                    if (j == point->width - i - 1)
                        prep.point->data[i][0] = point->data[i][j];
                }
            }
            return prep;
        }
    
        Mat<T> Row(int n)// 返回矩阵的第n行上的元素,组出一个1行N列的矩阵输出,N为第n行上元素的个数
        {
            Mat<T> prep(1,point->width);
            for (int i = 0; i < point->height; i++)
            {
                for (int j = 0; j < point->width; j++)
                {
                    if (i == n - 1)
                    {
                        for (j = 0; j < point->width; j++)
                            prep.point->data[0][j] = point->data[i][j];
                    }
                }
            }
            return prep;
        }
    
        Mat<T> Column(int n)// 返回矩阵的第n列上的元素,组出一个N行1列的矩阵输出,N为第n列上元素的个数
        {
            Mat<T> prep(point->height,1);
            for (int i = 0; i < point->height; i++)
            {
                for (int j = 0; j < point->width; j++)
                {
                    if (i == n - 1)
                    {
                        if (j == n)
                            prep.point->data[i][0] = point->data[i][j];
                    }
                }
            }
            return prep;
        }
    
        void Cat(Mat<T> &m, int code) // 将m与当前对象进行拼接,code代表拼接的方式
        {
            int i, j, h, w;
            T **a = new T*[point->height];
            for (i = 0; i < point->height; i++)
                a[i] = new T[point->width];
    
            for (i = 0; i < point->height; i++)
            {
                for (j = 0; j < point->width; j++)
                {
                    a[i][j] = point->data[i][j];//保存原数组
                }
            }
            judge_delete();//判断是否有其他对象利用这块空间,若没有,便删除原来的空间,以便改变空间大小
    
            if (code == 1)
            {
                h = point->height;
                w = point->width;
                point->width = point->width + m.point->width;
    
                point->data = new T*[point->height];
                for (i = 0; i < point->height; i++)
                    point->data[i] = new T[point->width];//新空间
    
                for (i = 0; i < h; i++)
                {
                    for (j = 0; j < w; j++)
                    {
                        point->data[i][j] = a[i][j];//第一个数组复制
                    }
                }
                for (i = 0; i < point->height; i++)
                {
                    for (j = w; j < point->width; j++)
                    {
                        point->data[i][j] = m.point->data[i][j - w];//第二个数组复制
                    }
                }
                WriteBMP("Catliftright.bmp");
                for (i = 0; i < point->height; i++)
                    delete []a[i];
                delete[]a;
            }
    
            if (code == 2)
            {
                h = point->height;
                w = point->width;
                point->height = point->height + m.point->height;
    
                point->data = new T*[point->height];
                for (i = 0; i < point->height; i++)
                    point->data[i] = new T[point->width];//新空间
    
                for (i = 0; i < h; i++)
                {
                    for (j = 0; j < w; j++)
                    {
                        point->data[i][j] = a[i][j];//第一个数组复制
                    }
                }
                for (i = h; i < point->height; i++)
                {
                    for (j = 0; j < point->width; j++)
                    {
                        point->data[i][j] = m.point->data[i - h][j];//第二个数组复制
                    }
                }
                WriteBMP("Catupdown");
                for (i = 0; i < h; i++)
                    delete []a[i];
                delete[]a;
            }
        }
    
        void CopyTo(Mat<T> &m) // 将矩阵复制给m,完成深拷贝
        {
            int i, j;
            m.point->height = point->height;
            m.point->width = point->width;
            m.point->data = new T*[point->height];
            for (i = 0; i < point->height; i++)
                m.point->data[i] = new T[point->width];
    
            for (i = 0; i < point->height; i++)
            {
                for (j = 0; j < point->width; j++)
                {
                    m.point->data[i][j] = point->data[i][j];
                }
            }
            m.point->count=new int[1];
            *m.point->count=1;
        }
    
        Mat<T> Clone() // 从当前对象拷贝创建一个新的矩阵,完成深拷贝
        {
            int i,j;
            Mat<T> prep;
            prep.point->height=point->height;
            prep.point->width=point->width;
            prep.point->data = new T*[point->height];//开辟空间
            for (i = 0; i < point->height; i++)
                prep.point->data[i] = new T[point->width];
            for (i = 0; i < point->height; i++)
            {
                for (j = 0; j < point->width; j++)
                {
                    prep.point->data[i][j] = point->data[i][j];
                }
            }
            prep.point->count=new int[1];
            *prep.point->count=1;
        }
    
        Mat<double> Normalize()//将矩阵元素的值变换到0-1范围内,以double类型的Mat对象输出。注意:在这个函数里,无法访问Mat<double>类型的对象的私有成员data,需要调用其At函数获得某个元素。
        {
            double mi = 0, ma = 0;
            int i, j;
            for (i = 0; i < point->height; i++)
            {
                for (j = 0; j < point->width; j++)
                {
                    if (At(i,j) > ma)
                    {
                        ma = At(i,j);
                    }
                    if (At(i,j) < mi)
                    {
                        mi = At(i,j);
                    }
                }
            }
            for (i = 0; i < point->height; i++)
            {
                for (j = 0; j < point->width; j++)
                {
                    if (At(i,j) == mi)
                    {
                        At(i,j) = 0;
                    }
                    else if (At(i,j) == ma)
                    {
                        At(i,j) = 1;
                    }
                    else
                    {
                        At(i,j) = (At(i,j) - mi) / ma;
                    }
                }
            }
    
        }
    
        void enlarge()//如果是01之间,放大到0-255
        {
            int i,j;
            int flag=0;
            for (i = 0; i < point->height; i++)
            {
                for (j = 0; j < point->width; j++)
                {
                    if(point->data[i][j]>1)
                    {
                        flag=1;
                        break;//判断是否在零一之间
                    }
                }
            }
            if(flag==0)
            {
                for (i = 0; i < point->height; i++)
                {
                    for (j = 0; j < point->width; j++)
                    {
                        point->data[i][j]=point->data[i][j]*255;
                    }
                }
            }
        }
    
        Mat<T>& operator=(const Mat<T> &m)  //重载赋值运算符,完成对象间的拷贝;
        {
            if(this != &m)
            {
                if(*point->count>1)//还有对象使用
                {
                    *point->count--;
                }
                else//删除空间
                {
                    for(int i=0; i<point->height; i++)
                        delete [] point->data[i];
                    delete [] point->data;
                }
                point->count=m.point->count;
                *m.point->count++;
                point->height=m.point->height;
                point->width=m.point->width;
                point->data=m.point->data;
            }
            return *this;
        }
    
        bool operator==(const Mat<T> &m)  //判断两个Mat对象是否相等
        {
            bool flag = 1;
            int i,j;
            if(point->height==m.point->height&&point->width==m.point->width)
            {
                for(i=0; i<point->height; i++)
                {
                    for(j=0; j<point->width; j++)
                    {
                        if(point->data[i][j]!=m.point->data[i][j])
                        {
                            flag=0;
                            break;
                        }
                    }
                }
            }
            else
            {
                flag=0;
            }
            return flag;
        }
    
        friend Mat<T> operator+(const Mat<T> &lhs, const Mat<T> &rhs)  //对应元素的数值相加;
        {
            int i,j;
            Mat<T> result(lhs.point->height, lhs.point->width);
            if(lhs.point->height==rhs.point->height&&lhs.point->width==rhs.point->width)
            {
                for(i=0; i<lhs.point->height; i++)
                {
                    for(j=0; j<lhs.point->width; j++)
                    {
                        result.point->data[i][j]=lhs.point->data[i][j]+rhs.point->data[i][j];
                    }
                }
            }
            else
                printf("两矩阵尺寸不同");
            return result;
        }
    
        friend Mat<T> operator-(const Mat<T> &lhs, const Mat<T> &rhs)  //对应元素的数值相减;
        {
            int i,j;
            Mat<T> result(lhs.point->height, lhs.point->width);
            if(lhs.point->height==rhs.point->height&&lhs.point->width==rhs.point->width)
            {
                for(i=0; i<lhs.point->height; i++)
                {
                    for(j=0; j<lhs.point->width; j++)
                    {
                        result.point->data[i][j]=lhs.point->data[i][j]-rhs.point->data[i][j];
                    }
                }
            }
            else
                printf("两矩阵尺寸不同");
            return result;
        }
    
        Mat<T>& operator++()  //前置自加;
        {
            int i,j;
            for(i=0; i<point->height; i++)
            {
                for(j=0; j<point->width; j++)
                {
                    point->data[i][j]=point->data[i][j]+1;
                }
            }
            return *this;
        }
    
        Mat<T>& operator--()  //前置自减;
        {
            int i,j;
            for(i=0; i<point->height; i++)
            {
                for(j=0; j<point->width; j++)
                {
                    point->data[i][j]=point->data[i][j]-1;
                }
            }
            return *this;
        }
    
        Mat<T> operator ++(int) //后置自加;
        {
            Mat<T> old=*this;
            ++(*this);
            return old;
        }
    
        Mat<T> operator --(int)  //后置自减;
        {
            Mat<T> old=*this;
            --(*this);
            return old;
        }
    
        Mat<double> operator-()  // 取反;注意要把矩阵的数据规整到[0,1]区间后,再用1减
        {
            int i,j;
            Normalize();//缩小到01之间
            for (i = 0; i < point->height; i++)
            {
                for (j = 0; j < point->width; j++)
                {
                    point->data[i][j]=1-point->data[i][j];
                }
            }
            return *this;
        }
    
        friend Mat<T> operator+(Mat<T> &m, T num) //所有元素加上同一数值;
        {
            int i,j;
            Mat<T> nummatrix(m.point->height,m.point->width,num);//实现对double型num的升级,使其成为Matrix对象
            for(i=0; i<m.point->height; i++)
            {
                for(j=0; j<m.point->width; j++)
                {
                    m.point->data[i][j]=m.point->data[i][j] + nummatrix->point->data[i][j];
                }
            }
            return m;
        }
    
        friend Mat<T> operator-(Mat<T> &m, T num) //所有元素减去同一数值;
        {
            int i,j;
            Mat<T> nummatrix(m.point->height,m.point->width,num);//实现对double型num的升级,使其成为Matrix对象
            for(i=0; i<m.point->height; i++)
            {
                for(j=0; j<m.point->width; j++)
                {
                    m.point->data[i][j]=m.point->data[i][j] - nummatrix->point->data[i][j];
                }
            }
            return m;
        }
    
        friend Mat<T> operator*(Mat<T> &m, T num) //所有元素乘上同一数值;
        {
            int i,j;
            Mat<T> nummatrix(m.point->height,m.point->width,num);//实现对double型num的升级,使其成为Matrix对象
            for(i=0; i<m.point->height; i++)
            {
                for(j=0; j<m.point->width; j++)
                {
                    m.point->data[i][j]=m.point->data[i][j] * nummatrix->point->data[i][j];
                }
            }
            return m;
        }
    
        friend Mat<T> operator/(Mat<T> &m, T num) //所有元素除以同一数值;
        {
            int i,j;
            Mat<T> nummatrix(m.point->height,m.point->width,num);//实现对double型num的升级,使其成为Matrix对象
            for(i=0; i<m.point->height; i++)
            {
                for(j=0; j<m.point->width; j++)
                {
                    m.point->data[i][j]=m.point->data[i][j] / nummatrix->point->data[i][j];
                }
            }
            return m;
        }
    //另外,用友元函数再写出一个T类型的数和一个Mat对象的加,减,乘,除
        friend Mat<T> operator+(T num, Mat<T> &m)
        {
            int i,j;
            Mat<T> nummatrix(m.point->height,m.point->width,num);//实现对double型num的升级,使其成为Matrix对象
            for(i=0; i<m.point->height; i++)
            {
                for(j=0; j<m.point->width; j++)
                {
                    m.point->data[i][j]=m.point->data[i][j] + nummatrix->point->data[i][j];
                }
            }
            return m;
        }
    
        friend Mat<T> operator-(T num, Mat<T> &m)
        {
            int i,j;
            Mat<T> nummatrix(m.point->height,m.point->width,num);//实现对double型num的升级,使其成为Matrix对象
            for(i=0; i<m.point->height; i++)
            {
                for(j=0; j<m.point->width; j++)
                {
                    m.point->data[i][j]=nummatrix->point->data[i][j] - m.point->data[i][j];
                }
            }
            return m;
        }
    
        friend Mat<T> operator*(T num, Mat<T> &m)
        {
            int i,j;
            Mat<T> nummatrix(m.point->height,m.point->width,num);//实现对double型num的升级,使其成为Matrix对象
            for(i=0; i<m.point->height; i++)
            {
                for(j=0; j<m.point->width; j++)
                {
                    m.point->data[i][j]=nummatrix->point->data[i][j] * m.point->data[i][j];
                }
            }
            return m;
        }
    
        friend Mat<T> operator/(T num, Mat<T> &m)
        {
            int i,j;
            Mat<T> nummatrix(m.point->height,m.point->width,num);//实现对double型num的升级,使其成为Matrix对象
            for(i=0; i<m.point->height; i++)
            {
                for(j=0; j<m.point->width; j++)
                {
                    m.point->data[i][j]=nummatrix->point->data[i][j] / m.point->data[i][j];
                }
            }
            return m;
        }
    
        Mat<T> gray2bw(T t) //以给定阈值t进行二值化,返回结果对象
        {
            int i,j;
            Normalize();//缩小到01之间
            for (i = 0; i < point->height; i++)
            {
                for (j = 0; j < point->width; j++)
                {
                    if(point->data[i][j]>=t)
                        point->data[i][j]=1;
                    else
                        point->data[i][j]=0;
                }
            }
            return *this;
        }
    
        friend void Swap(Mat<T> &a, Mat<T> &b)//使用友元函数交换两个Mat对象
        {
            int prep=a.point->height;
            a.point->height=b.point->height;
            b.point->height=a.point->height;
            prep=a.point->width;
            a.point->width=b.point->width;
            b.point->width=a.point->width;
            T **i=a.point->data;
            a.point->data=b.point->data;
            b.point->data=i;
            int **j=a.point->count;
            a.point->count=b.point->count;
            b.point->count=i;
            matrix_count *k=a.p;
            a.p=b.p;
            b.p=k;
        }
    
    protected:
        struct matrix_count
        {
            int height;
            int width;
            T **data;
            int *count;
        };// 自己实现一个结构体,来存储矩阵的行数、列数、引用计数和数据指针
        struct matrix_count *point;// 这里需要声明指向该结构体的指针作为数据成员
    };
    
    #endif // MAT_H
    
    #ifndef FILTER_H
    #define FILTER_H
    #include "Mat.h"
    
    template <class T>
    class Filter
    {
    public:
    	Filter<T>(int size)//构造函数
    	{
    		filterSize = size;
    	}
    	virtual ~Filter<T>() {}//析构函数
    	virtual Mat<T> Filtering(const Mat<T> &input) = 0; //滤波函数(纯虚函数);
    protected:
    	int filterSize;
    };
    
    //meanFilter类
    template <class T>
    class MeanFilter : public Filter<T>
    {
    public:
        MeanFilter<T>(int size):Filter<T>(size)
        {
        }
    	virtual ~MeanFilter<T>()
    	{
    	}
    
        virtual Mat<T> Filtering(const Mat<T> &input) //均值滤波函数
        {
            Mat<T> prep(input);
            int i,j;
            double sum;
            double s=Filter<T>::filtersize*Filter<T>::filtersize;
            int l,m;
            int f=Filter<T>::filtersize;
            int w=(Filter<T>::filtersize-1)/2;
    
            int nh=input.Height()+2*(Filter<T>::filtersize-1);
            int nw=input.Width()+2*(Filter<T>::filtersize-1);//新长宽
            Mat<T> p(nh,nw,T(1));
    
            for(i=0; i<input.Height(); i++) //镜像拓展
            {
                for(j=0; j<input.Width(); j++)
                {
                    p.matrix.data[i+f-1][j+f-1]=input.matrix.data[i][j];
                }
            }
            for(i=0; i<f-1; i++)
            {
                for(j=f-1; j<=nw-f; j++)
                {
                    p.matrix.data[i][j]=p.matrix.data[2*(f-1)-1-i][j];
                }
            }
            for(i=nh-f; i<nh-1; i++)
            {
                for(j=f-1; j<=nw-f; j++)
                {
                    p.matrix.data[i][j]=p.matrix.data[2*nh-2*(f-1)-i-1][j];
                }
            }
            for(i=0; i<nh-1; i++)
            {
                for(j=0; j<f-1; j++)
                {
                    p.matrix.data[i][j]=p.matrix.data[i][2*(f-1)-1-j];
                }
            }
            for(i=0; i<nh-1; i++)
            {
                for(j=nw-f+1; j<nw-1; j++)
                {
                    p.matrix.data[i][j]=p.matrix.data[i][2*nw-2*(f-1)-j-1];
                }
            }
    
            for(i=f-1; i<=nh-f; i++)//进行滤波
            {
                for(j=f-1; j<=nw-f; j++)
                {
                    sum=0;
                    for(l=0; l<Filter<T>::filtersize; l++)
                    {
                        for(m=0; m<Filter<T>::filtersize; m++)
                        {
                            sum = sum+p.matrix.data[i-w+l][j-w+m];
                        }
                    }
                    prep.matrix.data[i-f+1][j-f+1]=sum/s;
                }
            }
            return prep;
        }
    };
    
    
    //median类
    template <class T>
    class MedianFilter : public Filter<T>
    {
    public:
        MedianFilter<T>(int size):Filter<T>(size)
        {
    
        }
        virtual ~MedianFilter()
        {
    
        }
        virtual Mat<T> Filtering(const Mat<T> &input) // 中值滤波器函数
        {
            Mat<T> prep(input);
            int i,j;
            double sum;
            double s=Filter<T>::filtersize*Filter<T>::filtersize;
            T *array=new T[s];//开辟一个一维数组
            int l,m;
            int f=Filter<T>::filtersize;
            int w=(Filter<T>::filtersize-1)/2;
    
            int nh=input.Height()+2*(Filter<T>::filtersize-1);
            int nw=input.Width()+2*(Filter<T>::filtersize-1);//新长宽
    
            Mat<T> p(nh,nw,T(1));
    
            for(i=0; i<input.Height(); i++) //镜像拓展
            {
                for(j=0; j<input.Width(); j++)
                {
                    p.matrix.data[i+f-1][j+f-1]=input.matrix.data[i][j];
                }
            }
            for(i=0; i<f-1; i++)
            {
                for(j=f-1; j<=nw-f; j++)
                {
                    p.matrix.data[i][j]=p.matrix.data[2*(f-1)-1-i][j];
                }
            }
            for(i=nh-f; i<nh-1; i++)
            {
                for(j=f-1; j<=nw-f; j++)
                {
                    p.matrix.data[i][j]=p.matrix.data[2*nh-2*(f-1)-i-1][j];
                }
            }
            for(i=0; i<nh-1; i++)
            {
                for(j=0; j<f-1; j++)
                {
                    p.matrix.data[i][j]=p.matrix.data[i][2*(f-1)-1-j];
                }
            }
            for(i=0; i<nh-1; i++)
            {
                for(j=nw-f+1; j<nw-1; j++)
                {
                    p.matrix.data[i][j]=p.matrix.data[i][2*nw-2*(f-1)-j-1];
                }
            }
    
            for(i=f-1; i<=nh-f; i++)
            {
                for(j=f-1; j<=nw-f; j++)
                {
                    int c=0;
                    for(l=0; l<Filter<T>::filtersize; l++) //正方形区域内相加
                    {
                        for(m=0; m<Filter<T>::filtersize; m++)
                        {
                            array[c]=p.matrix.data[i-w+l][j-w+m];
                            c++;
                        }
                    }
                    prep.matrix.data[i-f+1][j-f+1] = sorted(array,s);
                }
            }
            return prep;
        }
    
    #endif // FILTER_H
    
    #include "Mat.h"
    
    Mat::Mat()
    {
        //ctor
    }
    
    Mat::~Mat()
    {
        //dtor
    }
    
    #include "Filter.h"
    
    Filter::Filter()
    {
        //ctor
    }
    
    Filter::~Filter()
    {
        //dtor
    }
    

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值