C++(五):终章:C++大作业

一学期的C++课程要结束了,最后用一篇博客记录一下大作业的过程,记录的可能会有点乱。。。。

1. 开始

1.1 菜单栏

qt的菜单栏的UI界面其实很友好,直接编辑就好

1.1.1 打开图片

打开图片使用到的主要函数是:QFileDialog中的getOpenFileName。该函数包含四个参数,分别表示为:

  • 参数一:父窗口
  • 参数二:对话框标题
  • 参数三:默认打开位置。为空则表示打开当前工程所在目录
  • 参数四:文件的过滤器,文档的类型之间用;;隔开

参考:1

1.1.2 图片另存为

使用的函数:QFileDialog::getSaveFileNameQGuiApplication::primaryScreen()
包含的头文件:<QGuiApplication><QScreen>
保存时要注意将后缀写上,否则有错误提醒

  • getSaveFileName:函数的参数与上面的getOpenFileName的参数含义是一样的
  • QGuiApplication::primaryScreen()
  • screen->grabWindow(ui->label->winId()).save(file_name)

参考:1

1.1.3 保存图片

和上面的差不多,少了一行

1.1.4 新建

把label空间清除。

1.1.5 关闭

close()

2 算法实现

2.1 高斯滤波

滤波是对输入信号进行卷积处理的一个过程,表达式为:
滤波 = 卷积(输入信号,卷积模板),卷积模板/掩膜的不同决定了不同的滤波方式。
高斯滤波:利用高斯掩膜对输入信号进行卷积,也叫高斯模糊,是一种线性平滑滤波器。
高斯分布公式为:
在这里插入图片描述
前面的系数是一个常数不会影响相互之间的比例关系,由于最终都要进行归一化所以在实际计算中只需要计算后半部分。
在这里插入图片描述
其中(x,y)是掩膜内任一点的坐标,(ux,uy)是掩膜内中心点的坐标,再图像处理中可以认为是整数,σ是标准差。

2.1.1 高斯平滑流程

  1. 确定权重矩阵
    如果要产生一个3x3的高斯滤波模板,模板的中心位置和周围的点的坐标为:
    在这里插入图片描述
    计算权重矩阵需要设定σ的值,假设为1,则模糊半径为1 的权重矩阵为:
    在这里插入图片描述
    以上九个点的权重之和小于1,如果只计算9个点的加权平均,必须使得它们的权重之和等于1,所以还需要将9个值分别除以他们的权重之和得到最终的权重矩阵。(也就是归一化)
    在这里插入图片描述
  2. 计算高斯模糊
    得到权重矩阵之后进行高斯模糊。
    假设9个像素点的灰度值如下所示:
    在这里插入图片描述
    将每个点乘以对应的权重值,可得:

    然后再将得到的就九个值相加得到中心点的高斯模糊的值。
    然后对所有的点重复这个过程就得到高斯模糊之后的图像。如果原图是彩色的可以对RGB三个通道分别做高斯平滑。
  3. σ的选取
    高斯滤波生成最重要的参数就是σ,标准差代表着数据的离散程度。如果σ较小,那么生成模板的中心系数较大,而周围系数较小会导致对图像的平滑效果不是很明显;反之,如果σ较大那个生成的模板的各个系数相差就不是很大,类似均值模板。对图像的平滑效果比较明显。
2.1.1.1卷积核大小的定义

高度和宽度应该为奇数并且可以不同。

2.2 均值滤波

对目标像素及周边像素取平均值后再填回目标像素来实现滤波目的的方法。
公式:
在这里插入图片描述

均值滤波:由一个归一化卷积框完成,只是用卷积框覆盖区域所有像素的平均值来代替中心元素
在这里插入图片描述
上图中红色点的值是周围蓝色背景区域像素值之和除以25,25是蓝色区域的大小。
优点: 算法简单,计算速度较快
缺点:去噪的同时去除了很多细节部分,将图像变模糊。

2.3 直方图均衡化

直方图根据灰度图绘制而不是彩色图,所以在使用时需要将彩色图转为灰度图。
直方图均衡化把原始图像的灰度直方图从比较集中的某个灰度区间变成比较广泛灰度范围内的分布。也就是对图像进行非线性拉伸,重新分配图像像素值,是一定灰度范围内的像素数量大致相同。

2.3.1 流程

  1. 遍历全图,统计每个灰度下的像素点个数
  2. 计算每个灰度级的像素点占总像素的点的比例
  3. 根据求出的比例重新计算每个灰度级下的新的灰度值
  4. 更新图像的灰度图

2.4 动态库的创建与使用

感谢这个B站视频,动态库的创建与使用有以下几个流程:

  1. 新建共享库工程,然后编译获得dll文件

  2. 在另一个工程中导入相关头文件,需要将动态库的两个头文件复制到该工程下。如下图所示,enhance的两个头文件是我动态库的两个头文件
    在这里插入图片描述

  3. 然后在qt中选择添加现有文件,将新复制的两个头文件加入工程中,如下图所示
    在这里插入图片描述
    在这里插入图片描述

  4. 链接库,配置pro文件,将动态库的dll文件的路劲加入pro文件中
    在这里插入图片描述

  5. 编译执行,会发现只弹出一个对话窗口没有显示要显示的东西,此时,到该工程的debug文件夹下,将动态库的dll文件复制进去然后再次执行,完成。
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
以上就是动态库创建与使用的测试。测试成功,接下来开始继续大作业的推动。

2.5.1 问题

问题:出现“ACCESS_MASK“问题,在加入动态库之前没有这个问题但加入洞开库之后出现了这个问题,将所有的using namespace cv改掉之后,还是不行,所以应该是include文件重复引用导致的,将动态库中的h文件中一部分uinclude文件放入cpp文件中,解决。

3. 总结

大作业结束了,但是对c++的学习并不会因此而结束,这门课的结束,是结束也是开始,结束了课程上的学习,开始了自己的探索之旅。

4. 参考

高斯滤波
“CV_RGB2BGR”: 未声明的标识符
转换
静态成员
获取ui中combobox的值
程序异常报错

第一次作业 这个作业将让你去练习建立一些简单的类和使用C++的基本功能,包括:封装,引用,动态内存开辟, 简单构造函数和析构函数和const。 下面给的程序片段未经过编译或调试. 做出合理的错误修正是你任务的一部分。 一般的,我们会给你最基本部分的代码,如果你需要,你可以在一个类里添加额外的变量或方法,这个作业被分为三个部分,那么你们要按照步骤一步一步地完成。 1. 设计要求 第一部分) 构建简单的类 R1.1) 创建一个Person类, 其模型在下面的代码结构里。 R1.2) 人类(Persons)应该有一些属性: name, email_address, birthdate 作为表示人类的属性。 R1.3) 按下面的要求创建一个Date类。 R1.4) 每个类都应该可以使用输出运算符(<<)输出内容。 //file Date.h class Date { public: Date(); Date( int year, int month, int day ); ... private: int _year; int _month; int _day; }; //end file Date.h //file Person.h class Person { public: Person(void); Person(char * their_name, char * email, int day, int month, int year); char * GetName(); char * GetEmailAddress(); Date GetBirthDate(); void Print(); private: char* name; char* email_address; Date date; }; //end file Person.h 第二部分) 构建一个容器类 Set container. R2.1) 建立一个set的模型PersonSet类, 并且它只能保存Person的对象. R2.2) 这个set应该存储person的地址(指针),以便可以获取原始对象(非拷贝). R2.3) set的存储应该用动态数组来保存Person的指针(用new来创建), 但是set不应该有界限(数组大小), 它们应该在成员进行添加或移除时,适当进行扩展.. R2.4) 成员不按任何特定顺序存储(无排序). R2.5) set允许存储副本(相同对象). R2.6) Add() 函数应该当在添加的时候,并且需要的情况,进行扩展数组大小并且输出一串信息. R2.7) Remove() 函数应该在移除的时候, 并且在需要的情况, 可以进行缩小数组大小并输出一串信息. R2.8) Add() 函数应该带一个引用类型的参数(Person&). R2.9) 迭代应该通过NextElement()函数来提供. R2.10) NextElement()和 RemoveElement() 应该通过引用返回 对于现在我们将去建立sets去只保存Person对象,因此类名是PersonSet. //file PersonSet.h class PersonSet { public: //default constructor allocate appropriate heap storage store elements on //heap array declared like this: new Person*[initial_size]; PersonSet (int initial_size = 4); //store element in the set if the set is full allocate more memory ~ PersonSet (void); public: void Add(Person & element) ; Person & NextElement() ; // 从set中移除最后一个成员 //如果Set空的数据超过一半,释放一些内存 Person & RemoveElement(); // 从Set中的index索引处移除成员 // 如果Set空的数据超过一半, 释放一些内存 Person & RemoveElement( int index ); int Size(); //answer the number of elements in the set. void Print();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值