实验要求
实验目的
掌握运算符重载
实现对Matrix类的运算符重载
实验内容
在之前的实验中,我们实现了矩阵类Matrix及其子类Image。本次实验我们给Matrix类添加一些重载的运算符,包括赋值运算符“=”,两个Matrix对象的“+”、“-”、“”、“/”(都是矩阵对应元素间的运算,而不是矩阵的乘除),自加自减,矩阵(或图像)对象和一个数(标量)的“=”、“+”、“-”、“”、“/”操作,判断两个矩阵(或图像)是否相等的“==”。
给Image类添加一个单目运算符“-”,作用是图像的像素值取反,即黑的变成白的,白的变成黑的。再给Image类添加一个成员函数gray2bw,该函数以给定的阈值参数把灰度图像转化为二值图像。假设图像的像素值范围在[0,1]之间的实数,给定阈值double t∈[0,1]。该函数对图像中的所有像素做如下处理:如果该像素的像素值小于t,则输出图像对应像素值赋值为0,如果该像素的像素值大于等于t,则输出图像对应像素赋值为1。此函数的输出图像对象仅含有0和1两种像素值,因此该操作在图像处理里称为“二值化”操作或“阈值分割”。
注意:这两种函数假设操作对象的数据是在[0,1]之间的实数。但是实际对象的元素数值可能不在这个范围内。因此,在这两个函数内部,需要先把所有元素的范围normalize到[0,1]区间,然后再做相应的操作。同样,在把结果保存为BMP图像的时候,要把范围再缩放到[0,255]的整数区间,注意相关的操作。
之前给大家的图片中有两幅场景图scene2_bg.bmp和scene2_fg.bmp,要求通过图像相减,再做阈值分割,分离出前景物体。
1在Matrix类中重载运算符,添加一些运算符重载函数(有的是成员函数,有的是友元函数,思考哪些适合使用成员函数,哪些适合使用友元函数?):
1)重载两个Matrix对象的赋值运算符“=”,完成类似a=b的操作。要求进行数据的深拷贝。并再次重载赋值运算符,使右操作数可以是一个double类型的数,完成矩阵所有元素赋值为该数,如a=128。
2)重载判断两个Matrix对象是否相等的“==”运算符,两个矩阵相等的条件是行列大小相同,所有元素的值也相等。
3)重载“+”运算符,针对两幅尺寸相同的矩阵,完成对应元素值相加。
4)重载“+”运算符,实现一个矩阵所有元素加上同一数值。
5)重载“-”运算符,针对两个尺寸相同的矩阵,实现对元素值相减。
6)重载“-”运算符,实现一个矩阵所有元素减去同一数值。
7)重载“”运算符,针对两个尺寸相同的矩阵,实现对元素值相乘。
8)重载“”运算符,实现一个矩阵所有元素乘以同一数值。
9)重载“/”运算符,针对两个尺寸相同的矩阵,实现对元素值相除;自己设计除数为0时的处理办法。
10)重载“/”运算符,实现一个矩阵所有元素除以同一数值;自己设计除数为0时的处理办法。
2在Image类里,实现如下运算符和函数:
1)重载“-”单目运算符,实现一个Image对象的所有元素“取反”。
2)实现函数gray2bw,以给定的阈值对图像进行二值化,函数返回结果Image对象。
3)重载“++”运算符,实现一个矩阵所有元素自加1(分别实现前置版本和后置版本)。注意,使用该运算符的对象的像素值范围应该是[0,255],如果是[0,1]之间的,应该首先扩展到[0,255],再进行加1操作,然后再normalize回[0,1]。
4)重载“–”运算符,实现一个矩阵所有元素自减1(分别实现前置版本和后置版本)。注意,使用该运算符的对象的像素值范围应该是[0,255],如果是[0,1]之间的,应该首先扩展到[0,255],再进行加1操作,然后再normalize回[0,1]。
3在main函数中对所有实现的函数进行测试,比如前面提到的分离前景物体。
创建Image对象img1和img2,分别读入两幅图像scene2_fg和scene2_bg。新建Image对象sub,使用“-”运算符,实现img1和img2相减,并保存。对sub调用gray2bw函数进行阈值分割,保存结果。
代码示例
Matrix.h
#ifndef MATRIX_H
#define MATRIX_H
class Matrix
{
public:
// 构造函数等其它成员略
//运算符重载函数;
Matrix& operator=(const Matrix &m); //重载赋值运算符,完成对象间的深拷贝;
bool operator==(const Matrix &m); //判断两个Matrix对象是否相等
Matrix& operator++(); //前置自加;
Matrix& operator--(); //前置自减;
Matrix operator++(int); //后置自加;
Matrix operator–(int); //后置自减;
//两个尺寸相同的矩阵,对应元素的数值相加;
friend Matrix operator+(const Matrix &m1, const Matrix &m2);
//所有元素加上同一数值;
friend Matrix operator+(Matrix &m, double num);
//两个尺寸相同的矩阵,对应元素的数值相减;
friend Matrix operator-(const Matrix &m1, const Matrix &m2);
//所有元素减去同一数值;
friend Matrix operator-(Matrix &m, double num);
//两幅尺寸相同的矩阵,对应元素的数值相乘;
friend Matrix operator*(const Matrix &m1, const Matrix &m2);
//所有元素乘上同一数值;
friend Matrix operator*(Matrix &m, double num);
//两幅尺寸相同的矩阵,对应元素的数值相除;
friend Matrix operator/( const Matrix &m1, const Matrix &m2);
//所有元素除以同一数值;
friend Matrix operator/(Matrix &m, double num);
//以上友元函数实现了Matrix对象和一个数的加减乘除,如果交换这两个操作数,即一个数和一个Matrix对象的加减乘除,应该如何做?请自行写出相关代码。
//其它成员略
};
#endif
在Image类中实现Image特有的运算符和成员函数
Image operator-(); //对图像取反,把所有像素的值都规整到[0,1]之间,然后每个像素都被1.0减
Image gray2bw(double t); //以给定阈值t对图像进行二值化,返回结果图像对象;
自加、自减的前置版本和后置版本
代码实现:
main.cpp
#include <iostream>
#include "Image.h"
#include"Matrix.h"
using namespace std;
int main(int argc, char* argv[])
{
//写入数据
Image im1("Airplane.bmp");
im1.WriteBMP("1.bmp");
Image im2("Baboon.bmp");
im2.WriteBMP("2.bmp");
//重载加
Image im3(im1 + im2);
im3.WriteBMP("3.bmp");
//重载减
Image im4("scene2_fg.bmp");
Image im5("scene2_bg.bmp");
Image im6(im4 - im5);
im6.WriteBMP("6.bmp");
//相等
Image im7("Airplane.bmp");
Image im8("Baboon.bmp");
im7 = im8;
im7.WriteBMP("7.bmp");
//加上一个数
Image im9("Fruits.bmp");
Image im10(im9 + 400.0);
im10.WriteBMP("10.bmp");
//乘一个数
Image im11("Fruits.bmp");
Image im12(im11 * 4.0);
im12.WriteBMP("12.bmp");
//前置自加
Image im13("Fruits.bmp");
Image im14(++im13);
im14.WriteBMP("14.bmp");
//前置自减
Image im15("Fruits.bmp");
Image im16(--im15);
im16.WriteBMP("16.bmp");
//取反
Image im17("Fruits.bmp");
Image im18(-im17 );
im18.WriteBMP("18.bmp");
//阈值
Image im19(im6.gray2bw(0.5));
cout << 666;
im19.WriteBMP("6.6.bmp");
cout << 1;
return 0;
}
image.cpp
#include "Image.h"
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
Image::Image(int h, int w) :Matrix(h, w) {}
Image::Image(int h, int w, unsigned char val) : Matrix(h, w, val) {}//创建的图像像素值都为val;
Image::Image(const char* ImageName)//利用文件名从硬盘加载图像文件成为Image对象;
{
ReadBMP(ImageName);
}
Image::Image(unsigned char m[][100], int rows)//从静态二维数组创建Image对象,
//图像的行数(二维数组的第一个维度)由第二个参数rows给出;
{
height = rows;
width = 100;
data = new double* [height];
for (int i = 0; i < height; i++)
{
data[i] = new double[width];
for (int j = 0; j < width; j++)
{
data[i][j] = static_cast<unsigned char>(m[i][j]);
}
}
}
Image::Image(unsigned char** m, int h, int w)//从动态数组(二级指针)创建Image对象,
//图像的行数和列数由后面两个参数给出;
{
height = h;
width = w;
data = new double* [height];
for (int i = 0; i < height; i++)
{
data[i] = new double[width];
for (int j = 0; j < width; j++)
{
data[i][j] = static_cast<unsigned char>(m[i][j]);
}
}
}
Image::Image(const Matrix& m) :Matrix(m) {}//构造函数重载,由Matrix类对象构造Image类对象
Image::Image(const Image& im) : Matrix(im) //拷贝构造函数;
{
fh = im.fh;
ih = im.ih;
}
Image::~Image() {
for (int i = 0; i < height; i++)
{
delete[] data[i];
}
delete[]data;
}
//从硬盘读入图像文件,存储到image类中
void Image::ReadBMP(const char* filename)
{
FILE* fp;
fopen_s(&fp, filename, "rb");
fread(&fh, sizeof(fh), 1, fp);
fread(&ih, sizeof(ih), 1, fp);
height = ih.biHeight;
width = ih.biWidth;
data = new double* [height];
for (int i = 0; i < height; i++)
{
data[i] = new double[width];
for (int j = 0; j < width; j++)
{
unsigned char tdb[3] = { 0 };
fread(&tdb[0], 1, 1, fp);
fread(&tdb[1], 1, 1, fp);
fread(&tdb[2], 1, 1, fp);
//把三通道变为单通道,不是只保留一个通道,而是原来的三个通道都设置成一样
data[i][j] = (static_cast<double>(tdb[0] + tdb[1] + tdb[2])) / 3;
}
}
fclose(fp);
}
//保存bmp图像
void Image::WriteBMP(const char* filename)
{
FILE* fp = NULL;
fopen_s(&fp, filename, "wb");
//补位
bool flag = false;
while (width % 4)
{
width++;
}
ih.biWidth = width;
ih.biHeight = height;
ih.biSizeImage = flag ?
((((width * ih.biBitCount) + 31) / 32 * 4) * height) : width * height;
fwrite(&fh, sizeof(fh), 1, fp);
fwrite(&ih, sizeof(ih), 1, fp);
unsigned char t = 0;
for (int i = 0; i < ih.biHeight; i++)
{
for (int j = 0; j < ih.biWidth; j++)
{
t = static_cast<unsigned char>(data[i][j]);
fwrite(&t, 1, 1, fp);
fwrite(&t, 1, 1, fp);
fwrite(&t, 1, 1, fp);
}
}
fclose(fp);
}
Image& Image::operator=(const Image& m)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = m.data[i][j];
}
}
return *this;
}
Image& Image::operator+ (const Image& m1)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] + m1.data[i][j];
}
}
return *this;
}
Image& Image::operator- (const Image& m1)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] - m1.data[i][j];
}
}
return *this;
}
Image& Image::operator* (const Image& m1)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] * m1.data[i][j];
}
}
return *this;
}
Image& Image::operator/ (const Image& m1)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] / m1.data[i][j];
}
}
return *this;
}
bool Image::operator==(const Image& m) //判断两个Matrix对象是否相等
{
bool s = true;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (this->data[i][j] != m.data[i][j])
{
cout << "不相等" << endl;
s = false;
break;
}
}
}
cout << "相等" << endl;
return s;
}
Image& Image::operator+(double num)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] + num;
}
}
return *this;
}
Image& Image::operator-(double num)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] - num;
}
}
return *this;
}
Image& Image::operator*(double num)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] * num;
}
}
return *this;
}
Image& Image::operator/(double num)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] / num;
}
}
return *this;
}
Image& Image::operator++() //前置自加;
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] * 2;
}
}
return *this;
}
Image& Image::operator--() //前置自加;
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] - this->data[i][j];
}
}
return *this;
}
Image Image::operator-()
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] =1.0 - this->data[i][j] ;
}
}
return *this;
}
Image Image::gray2bw(double t)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (this->data[i][j] > t)
{
this->data[i][j] = 255;
}
else
{
this->data[i][j] = 0;
}
}
}
cout << 555;
return *this;
}
image.h
#ifndef Image_H
#define Image_H
#include "Matrix.h"
#include "Image.h"
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
// 针对该结构体的字节对齐问题调整对齐策略
#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; //位图显示过程中重要的颜色数
};
class Image : public Matrix
{
public:
Image() {}//构造函数,创建行列都为零的Image对象
Image(int h, int w); //构造函数重载,创建h行,w列的Image对象
Image(int h, int w, unsigned char val); //构造函数重载,创建的图像像素值都为val;
Image(const char* ImageName); //构造函数重载,利用文件名从硬盘加载图像文件成为Image对象;
Image(unsigned char m[][100], int n); //构造函数重载,从静态数组创建Image对象;
Image(unsigned char** m, int h, int w); //构造函数重载,从动态数组创建Image对象;
Image(const Matrix& m); //构造函数重载,由Matrix类对象构造Image类对象
Image(const Image& im); //拷贝构造函数;
virtual ~Image(); //析构函数;
void ReadBMP(const char* ImageName); //从硬盘文件中读入图像数据;
void WriteBMP(const char* filename); //将图像数据保存为图像文件;
void Flip(int code); //图像的翻转; code为0左右,1 上下;
// void Resize(int h, int w); //图像的缩放为参数指定的大小
// void Resize(int h, int w, int);
void Cut(int x1, int y1, int x2, int y2);//裁剪点(x1,y1)到点(x2,y2)的图像
void Rotate(int degree);//图像旋转的函数(旋转角度为90度的整数倍)
double Mean();//返回图像的均值
double Variance();//求图像的方差
Image& operator++(); //前置自加;
Image& operator--(); //前置自减
Image& operator+ (const Image& m1);
Image& operator- (const Image& m1);
Image& operator* (const Image& m1);
Image& operator/ (const Image& m1);
Image& operator+(double num);
Image& operator-(double num);
Image& operator*(double num);
Image& operator/(double num);
Image& operator=(const Image& m);
bool operator==(const Image& m);
Image operator-(); //对图像取反,把所有像素的值都规整到[0,1]之间,然后每个像素都被1.0减
Image gray2bw(double t); //以给定阈值t对图像进行二值化,返回结果图像对象;
//自加、自减的前置版本和后置版本
void Image::Resize(int h, int w)
{
//由于 void Resize(int h, int w, int); 放大倍数一次不能超过两倍,
//所以这里用迭代放大来实现任意倍数放大
int oldw = width;
int oldh = 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 Image::Resize(int h, int w, int)//图像的缩放为参数指定的大小
{
//记录原有的h,w
int oldh = h;
int oldw = w;
//记录原来的尺寸
int twidth = width;
int theight = height;
//新值与原值的差值
int dw = static_cast<int>(fabs(twidth - w));
int dh = static_cast<int>(fabs(theight - h));
//插入的间隔
if (dw < 1)//防止dw == 0
{
dw = 1;
}
if (dh < 1)
{
dh = 1;
}
int maxw = w > twidth ? w : twidth;
int maxh = h > theight ? h : theight;
int difw = maxw / dw;
int difh = maxh / dh;
//创建新数据
double** tdata = new double* [h];
//用i,j控制新空间的索引值
//用prii,prij控制原空间的索引值
for (int i = 0, prii = 0; i < h; i++)
{
tdata[i] = new double[w];
if ((i + 1) % difh == 0)
{
if (h < theight)
{
prii++;//指定 增/删 行跳过
//删除时跳过的是原空间的相应位置,而不是新空间的
}
else
{
continue;//指定 增/删 行跳过
//增加时,跳过的是新空间的相应位置,而不是原空间的,故直接continue
}
}
for (int j = 0, prij = 0; j < w; j++)
{
if ((j + 1) % difw == 0)
{
if (w < twidth)
{
prij++;//指定 增/删 列跳过
}
else
{
continue;
}
}
tdata[i][j] = data[prii][prij];
if (prij < twidth - 1)
prij++;
}
if (prii < theight - 1)
prii++;
}
//填充跳过的指定增行/列
if (w > twidth)//先填充列
{
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
if ((j + 1) % difw == 0)
{
tdata[i][j] = tdata[i][j - 1];//指定 增 列填充
}
}
}
}
if (h > theight)//再填充行
{
for (int i = 0; i < h; i++)
{
if ((i + 1) % difh == 0)//指定 增 行填充
{
for (int j = 0; j < w; j++)
{
tdata[i][j] = tdata[i - 1][j];
}
}
}
}
//保存
data = tdata;
height = h;
width = w;
}
BITMAPINFOHEADER ih;
BMPFILEHEADER fh;
};
#endif
Matrix.cpp
#include <iostream>
#include <iomanip>
#include "Matrix.h"
using namespace std;
Matrix::Matrix() :height(0), width(0), data(NULL)
{
}
Matrix::Matrix(int h, int w)
{
height = h;
width = w;
data = new double* [height];
for (int i = 0; i < height; i++)
{
data[i] = new double[width];
for (int j = 0; j < width; j++)
{
data[i][j] = 0;
}
}
}
Matrix::Matrix(int h, int w, double val)
{
height = h;
width = w;
data = new double* [height];
for (int i = 0; i < height; i++)
{
data[i] = new double[width];
for (int j = 0; j < width; j++)
{
data[i][j] = val;
}
}
}
Matrix::Matrix(const Matrix& m)
{
width = m.width;
height = m.height;
data = new double* [height];
for (int i = 0; i < height; i++)
{
data[i] = new double[width];
for (int j = 0; j < width; j++)
{
data[i][j] = m.data[i][j];
}
}
}
Matrix::~Matrix()
{
for (int i = 0; i < height; i++)
{
delete[] data[i];
}
delete[] data;
}
void Matrix::ReadText(const char* filename) //从文本文件中读入图像数据;
{
/*
FILE* fp = NULL;
fopen_s(&fp, filename, "rb");
//读取文件头、信息头
fread(&fh, sizeof(fh), 1, fp);
fread(&ih, sizeof(ih), 1, fp);
data = new unsigned char* [ih.biHeight];//相当于data[ih.biheight][ih.biwidth*3];
for (int i = 0; i < ih.biHeight; i++)
{
data[i] = new unsigned char[ih.biWidth * 3];
for (int j = 0; j < ih.biWidth * 3; j++)
{
fread(&data[i][j], 1, 1, fp);
}
}
fclose(fp);*/
FILE* fp = NULL;
fopen_s(&fp, filename, "rb");
fread(&height, sizeof(height), 1, fp);
fread(&width, sizeof(width), 1, fp);
data = new double* [height];
for (int i = 0; i < height; i++)
{
data[i] = new double[width * 3];
for (int j = 0; j < width; j++)
{
unsigned char temp[3] = { 0 };
for (int t = 0; t < 3; t++)
{
fread(&temp[t], 1, 1, fp);
}
data[i][j * 3 + 0] = (temp[0] + temp[1] + temp[2]) / 3;
data[i][j * 3 + 1] = (temp[0] + temp[1] + temp[2]) / 3;
data[i][j * 3 + 2] = (temp[0] + temp[1] + temp[2]) / 3;
}
}
fclose(fp);
}
void Matrix::WriteText(const char* filename) //将图像数据保存为文本文件;
{
/* FILE* fp2 = NULL;
fopen_s(&fp2, filename, "wb");
fwrite(&fh, sizeof(fh), 1, fp2);
fwrite(&ih, sizeof(ih), 1, fp2);
for (int i = 0; i < ih.biHeight; i++)
{
fwrite(data[i], ih.biWidth * 3, 1, fp2);
}
fclose(fp2);*/
FILE* fp = NULL;
fopen_s(&fp, filename, "wb");
fwrite(&height, sizeof(height), 1, fp);
fwrite(&width, sizeof(width), 1, fp);
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
fwrite((unsigned char*)&data[i][j], sizeof(unsigned char), 1, fp);
}
}
fclose(fp);
}
Matrix& Matrix::operator=(const Matrix& m)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = m.data[i][j];
}
}
return *this;
}
Matrix& Matrix::operator+(const Matrix& m1)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] + m1.data[i][j];
}
}
return *this;
}
Matrix& Matrix::operator-(const Matrix& m1)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] - m1.data[i][j];
}
}
return *this;
}
Matrix& Matrix::operator*(const Matrix& m1)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] * m1.data[i][j];
}
}
return *this;
}
Matrix& Matrix::operator/(const Matrix& m1)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] / m1.data[i][j];
}
}
return *this;
}
bool Matrix::operator==(const Matrix& m) //判断两个Matrix对象是否相等
{
bool s = true;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (this->data[i][j] != m.data[i][j])
{
cout << "不相等"<<endl;
s = false;
break;
}
}
}
cout << "相等" << endl;
return s;
}
Matrix& Matrix::operator+( double num)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] + num;
}
}
return *this;
}
Matrix& Matrix::operator-(double num)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] - num;
}
}
return *this;
}
Matrix& Matrix::operator*(double num)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] * num;
}
}
return *this;
}
Matrix& Matrix::operator/(double num)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] / num;
}
}
return *this;
}
Matrix& Matrix::operator++() //前置自加;
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j]*2;
}
}
return *this;
}
Matrix& Matrix::operator--() //前置自减;
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
this->data[i][j] = this->data[i][j] - this->data[i][j];
}
}
return *this;
}
Matrix.h
#ifndef MATRIX_H
#define MATRIX_H
class Matrix
{
public:
Matrix();
Matrix(int h, int w);
Matrix(int h, int w, double val);
Matrix(const Matrix& m);
virtual ~Matrix();
void str(int h, int w);
void ReadText(const char* filename); //从文本文件中读入图像数据;
void WriteText(const char* filename); //将图像数据保存为文本文件;
void Zeros(int h, int w); // 根据参数产生h行w列的全零矩阵
void Ones(int h, int w); // 根据参数产生h行w列的全1矩阵
void Random(int h, int w); //产生h行w列的随机矩阵,矩阵的元素为[0,1]之间的随机实数(double类型)
void Identity(int n); // 根据参数产生n行n列的单位矩阵
int Height() { return height; } // 获得矩阵的行数
int Width() { return width; } // 获得矩阵的列数
double& At(int row, int col); //获取第row行第col列的矩阵元素的值
void Set(int row, int col, double value); //设置第row行第col列矩阵元素的值为value
void Set(double value); //设置矩阵所有元素为同一值value
//运算符重载函数;
Matrix& operator=(const Matrix& m); //重载赋值运算符,完成对象间的深拷贝;
bool operator==(const Matrix& m); //判断两个Matrix对象是否相等
Matrix& operator++(); //前置自加;
Matrix& operator--(); //前置自减;
Matrix operator++(int); //后置自加;
Matrix operator--(int); //后置自减;
//两个尺寸相同的矩阵,对应元素的数值相加;
Matrix& operator+(const Matrix& m1);//两个尺寸相同的矩阵,对应元素的数值相加;
//两个尺寸相同的矩阵,对应元素的数值相减;
Matrix& operator-(const Matrix& m1);
//两幅尺寸相同的矩阵,对应元素的数值相乘;
Matrix& operator*(const Matrix& m1);
//两幅尺寸相同的矩阵,对应元素的数值相除;
Matrix& operator/(const Matrix& m1);
//所有元素加上同一数值;
Matrix& operator+( double num);
//所有元素减去同一数值;
Matrix& operator-(double num);
//所有元素乘上同一数值;
Matrix& operator*(double num);
//所有元素除以同一数值;
Matrix& operator/(double num);
void Matrix::Normalize()
{
double max = 0;
double min = 0;
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
if (data[i][j] > max)
max = data[i][j];
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
if (data[i][j] < min)
min = data[i][j];
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
data[i][j] = (data[i][j] - min) / (max - min);
}
void Matrix::Reshape(int h, int w)
{
double** a = new double* [1000];
for (int i = 0; i < 1000; i++)
a[i] = new double[1000];
for (int i = 0; i < h; i++)
for (int j = 0; j < w; j++)
{
int c = (i * w + j) / width;
int d = (i * w + j) % width;
a[i][j] = data[c][d];
}
for (int i = 0; i < height; i++)
delete[]data[i];
delete[]data;
data = new double* [h];
for (int i = 0; i < h; i++)
data[i] = new double[w];
for (int i = 0; i < h; i++)
for (int j = 0; j < w; j++)
data[i][j] = a[i][j];
for (int i = 0; i < 1000; i++)
delete[]a[i];
delete[]a;
height = h;
width = w;
}
//其它成员略
int height;
int width;
double** data;
};
#endif