实验6继承

这个实验旨在掌握C++中的继承概念,通过创建Matrix基类和Image派生类来处理图像数据。实验内容包括:定义Matrix类,实现其成员函数和友元函数;从Matrix类公有派生Image类并添加构造函数;处理数据类型的转换以及在处理图像后确保数据在0-255范围内;在main函数中测试各类成员函数。
摘要由CSDN通过智能技术生成

实验6 继承

实验要求

实验目的

掌握如何编写基类,如何通过继承基类的属性和函数编写派生类。
掌握如何在派生类成员函数中调用基类的成员函数。
掌握如何声明基类和派生类的对象,如何调用派生类对象的成员函数。

实验内容

1.创建Matrix类,作为Image类的基类。下面的代码已把实验5里的Image类的数据成员“转移至”了父类Matrix中,并将Image类中适用于矩阵的操作“转移至”Matrix类。请完成Matrix类的相关成员函数和友元函数的实现。
2.从Matrix类公有派生Image类,在Image类中实现一个新的构造函数,该构造函数由基类对象构造派生类对象。
3.对派生类的某些构造函数进行改造,使其能给基类构造函数传递参数完成基类成员的初始化。
4.在main函数中完成对Matrix类和Image类成员函数的调用。
注意:
自己学习关于矩阵的基本知识,包括矩阵的加法、减法、转置、单位矩阵等。
类Matrix中的数据类型是double,注意在派生类Image中如何把从图像文件里的数据类型从unsigned char转化为double。更重要的是,在对矩阵完成变换后存储成图像文件时,如何把数据类型再转换回unsigned char。在转换时如何对数据范围进行改变。
图像相加和相减后,结果图像的数据可能是负的或者大于255的,在写回图像文件时,应该处理这种情况。请参考后面的提示设计你的解决办法。

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 ReadText(char* filename); //从文本文件中读入图像数据;
void WriteText(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();  // 获得矩阵的行数

int Width(); // 获得矩阵的列数
Matrix MajorDiagonal();// 求矩阵主对角线上的元素,输出一个N行1列的矩阵,N为主对角线元素的个数
Matrix MinorDiagonal();// 求矩阵的副对角线上的元素,输出一个N行1列的矩阵,N为副对角线上元素的个数
Matrix Row(int n);// 返回矩阵的第n行上的元素,组出一个1行N列的矩阵输出,N为第n行上元素的个数
Matrix Column(int n);// 返回矩阵的第n列上的元素,组出一个N行1列的矩阵输出,N为第n列上元素的个数

void Transpose(); // 将矩阵转置

double& At(int row, int col); //获取第row行第col列的矩阵元素的值
void Set(int row, int col, double value); //设置第row行第col列矩阵元素的值为value
void Set(double value); //设置矩阵所有元素为同一值value

void Normalize(); // 该函数把矩阵的数据线性缩放至[0,1]区间,即把当前矩阵所有元素中的最小值min变成0,最大值max变为1,其他元素的值线性变到[0,1]区间,公式为:t’=(t-min)/max;

void Reshape(int h, int w); //在矩阵元素总数不变的情况下,将矩阵行列变为参数给定的大小
bool IsEmpty();// 判断矩阵是否为空矩阵
bool IsSquare();// 判断矩阵是否为方阵
void CopyTo(Matrix &m); // 将矩阵复制给m
void Mult(double s); // 矩阵的每个元素都乘以参数s
void Cat(Matrix &m, int code); // 将矩阵m与当前矩阵进行拼接,code代表拼接的方式:将m拼接到当前矩阵的上、下、左、右,具体例子见本大纲后面的说明

friend Matrix Add(const Matrix &m1, const Matrix &m2); // 友元函数,将矩阵m1和m2相加,结果矩阵作为函数的返回值

friend Matrix Sub(const Matrix &m1, const Matrix &m2); // 友元函数,将矩阵m1和m2相减,结果矩阵作为函数的返回值
friend void Swap(Matrix &a, Matrix &b); // 友元函数,交换两个矩阵

protected:
int height;
int width;
double **data;
};

#endif

Image.h
#ifndef Image_H
#define Image_H

#include “Matrix.h”

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(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(char* ImageName); //从硬盘文件中读入图像数据;
void WriteBMP(char* filename); //将图像数据保存为图像文件;
    
void Flip(int code); //图像的翻转; code为0左右,1 上下;
void Resize(int h, int w); //图像的缩放为参数指定的大小
void Cut(int x1,int y1,int x2,int y2);//裁剪点(x1,y1)到点(x2,y2)的图像
void Rotate(int degree);//图像旋转的函数(旋转角度为90度的整数倍)

double Mean();//返回图像的均值
double Variance();//求图像的方差
};
#endif

Main.cpp中测试你写的类和函数,以下代码仅为示例,供参考。
#include
#include “Image.h”

int main(int argc, char* argv[])
{
Matrix m(160000, 1);
for (int i = 0; i < 160000; i++)
{
m.At(i, 0) = i%256;
// m.Set(i,0,i%256);
}
m.Reshape(400, 400);
Image img(m);
img.WriteBMP(“Matrix.bmp”);

Matrix d = m.Diagonal();
Image *p = new Image(d);
p->WriteBMP("pImage.bmp");
p->Reshape(20,20);
p->WriteBMP("pImageReshaped.bmp");
delete p;
p = NULL;

Image im(“Fruits.jpg”);
im.Resize(200, 200);
im.WriteBMP(“Resized.bmp”);
im.Rotate(40);
im.Show(“Rotated.bmp”);

Image img1("Fruits.bmp");     
Image img2("Word.bmp"); 

//两图片相加

Image img_add(Add(img1, img2)) ;
img_add.WriteBMP(“Add.bmp”);

//两图片相减
Image img_sub(Sub(img1, img2));
img_sub.WriteBMP(“Sub.bmp”);

//图片的转置
Image img3(“lena.bmp”);
img3.Transpose();
img3.WriteBMP(“Transpose.bmp”);

//在右边拼接图片;
Image img4("Airplane.bmp"); 
Image img5("Baboon.bmp");
img4.Cat(img5,1);
img4.WriteBMP("CATRight.bmp");
//在下面拼接图片
Image img6("Airplane.bmp"); 
Image img7("Baboon.bmp");
img6.Cat(img7,2);
img6.WriteBMP("CATDown.bmp");
return 0;

}

实现代码:

main.cpp

#include <iostream>
#include <ctime>
#include "Image.h"
using namespace std;

int main(int argc, char* argv[])
{
   
//裁剪
	Image im1("Fruits.bmp");
	im1.Cut(0,10,200,200);
	im1.WriteBMP("cut.bmp");
	//转换
	Image im2("Fruits.bmp");
	im2.Flip(1);//true上下
	im2.WriteBMP("UpDown.bmp");
	Image im3("Fruits.bmp");
	im3.Flip(0);//false左右
	im3.WriteBMP("LeftRight.bmp");
	//缩放
	Image im4("Fruits.bmp");
	im4.Resize(200, 200);
	im4.WriteBMP("small.bmp");
	Image im5("Fruits.bmp");
	im5.Resize(1600, 1200);
	im5.WriteBMP("big.bmp");
	//拼接
	Image im6("Baboon.bmp");
	Image im7("Lena.bmp");
	Image im8("Baboon.bmp");//1接右
	im8.Cat(im7, 1);
	im8.WriteBMP("catRight.bmp");
	Image im9("Lena.bmp");//2接下
	im9.Cat(im6, 2);
	im9.WriteBMP("catDown.bmp");

	//转置
	Image im10("Lena.bmp");
	im10.Transpose();
	im10.WriteBMP("transpose.bmp");
	//相加
	Image im11("Baboon.bmp");
	im11.Resize(480, 512);
	Image im12("Lena.bmp");
	im12.Resize(480, 512);
	Image im13(Add(im12, im11));
	im13.ih = im12.ih;
	im13.fh = im12.fh;
	im13.WriteBMP("add.bmp");
	//相减
	Image im14("scene2_fg.bmp");
	Image im15("scene2_bg.bmp");
	Image im16(Sub(im14, im15));
	im16.ih = im14.ih;
	im16.fh = im14.fh;
	im16.WriteBMP("sub.bmp");
	//转换角度
	Image im17("Airplane.bmp");
	im17.Rotate(90);
	im17.WriteBMP("90.bmp");
	im17.Rotate(180);
	im17.WriteBMP("180.bmp");
	im17.Rotate(270);
	im17.WriteBMP("270.bmp");
	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给出;
{
   
	Mat_he = rows;
	Mat_w = 100;
	Mat_da = new double* [Mat_he];

	for (int i = 0; i < Mat_he; i++)
	{
   
		Mat_da[i] = new double[Mat_w];
		for (int j = 0; j < Mat_w; j++)
		{
   
			Mat_da[i][j] = static_cast<unsigned char>(m[i][j]);
		}
	}
}
Image::Image(unsigned char** m, int h, int w)//从动态数组(二级指针)创建Image对象,
//图像的行数和列数由后面两个参数给出;
{
   
	Mat_he = h;
	Mat_w = w;
	Mat_da = new double* [Mat_he];

	for (int i = 0; i < Mat_he; i++)
	{
   
		Mat_da[i] = new double[Mat_w];
		for (int j = 0; j < Mat_w; j++)
		{
   
			Mat_da[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() {
   
}


//从硬盘读入图像文件,存储到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);

	Mat_he = ih.biHeight;
	Mat_w = ih.biWidth;

	Mat_da = new double* [Mat_he];
	for (int i = 0; i < Mat_he; i++)
	{
   
		Mat_da[i] = new double[Mat_w];
		for (int j = 0; j < Mat_w; j++)
		{
   
			unsigned char tdb[3] = {
    0 };
			fread(&tdb[0], 1, 1, fp);
			fread(&tdb[1], 1, 1, fp);
			fread(&tdb[2], 1, 1, fp);

			//把三通道变为单通道,不是只保留一个通道,而是原来的三个通道都设置成一样
			Mat_da[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 (Mat_w % 4)
	{
   
		Mat_w++;
	}

	ih.biWidth = Mat_w;
	ih.biHeight = Mat_he;
	ih.biSizeImage = flag ?
		((((Mat_w * ih.biBitCount) + 31) / 32 * 4) * Mat_he) : Mat_w * Mat_he;

	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>(Mat_da[i][j]);
			fwrite(&t, 1, 1, fp);
			fwrite(&t, 1, 1, fp);
			fwrite(&t, 1, 1, fp);
		}
	}

	fclose(fp);
}



//false 左右,true 上下
void Image::Flip(int code)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值