本项目旨在实现一系列基于矩阵运算和图像处理(卷积操作)的功能,同时包含扩展任务(例如 OTSU 算法和目标提取),OTSU 算法直接采用 OpenCV 库中 threshold
,目标提取则是简单采取 contours
中面积最大的一块作为目标,其余涂黑。
项目采用模块化设计,将基础功能与扩展功能分别封装到独立的源文件和目录中,便于后续扩展。
此外,本项目同时提供了基于二维数组的矩阵运算(在 Matrix
目录下)和利用一维数组实现的矩阵运算(在 ExtendedMatrix
目录下)。图像处理部分分为基本卷积处理(ImageProcessing
模块)和扩展模块(ExtendedImageProcessing
模块)。
├── Matrix.sln // Visual Studio 解决方案文件
|
├── brain.jpg // 测试图像
├── demolena.jpg
├── polyhedrosis.jpg
├── ship.jpg
├── snowball.jpg
|
├── README.md
|
├── Main.cpp // 主程序入口(二维矩阵和基本与扩展图像处理)
├── ExtendedMain.cpp // 扩展主程序入口(矩阵运算基于一维数组实现)
|
├── ImageProcessing.h // 基本图像卷积处理模块接口
├── ImageProcessing.cpp // 基本图像卷积处理实现
├── ExtendedImageProcessing.h // 扩展图像处理模块接口
├── ExtendedImageProcessing.cpp // 扩展图像处理实现
├── Matrix.h // 二维矩阵运算接口
├── Matrix.cpp // 二维矩阵运算实现
├── ExtendedMatrix.h // 一维数组实现的矩阵运算接口
└── ExtendedMatrix.cpp // 一维数组实现的矩阵运算
- 开发环境:Visual Studio(推荐使用 VS2022),或其他支持 C++ 和 OpenCV 的 IDE。
- 依赖库:OpenCV。
- 操作系统:Windows,使用
_getch()
实现无回车输入。
- 将所有源代码和图像文件放置在同一工作目录下,按照上面的目录结构组织文件。
- 在 Visual Studio 中打开
Matrix.sln
。 - 配置 OpenCV 的包含目录和库目录。
- 编译并运行项目(分别编译
Matrix
项目和ExtendedMatrix
项目)。 - 根据提示在主菜单选择相应功能进行测试。
图片处理时,文件目录不应包含空格或中文字符!
- 主菜单中包含矩阵运算(加法、数乘、转置、乘法、Hadamard 乘积、卷积)、卷积应用(图像处理)、OTSU 算法和目标提取功能。
- 根据需要切换使用二维矩阵运算(通过
Main.cpp
入口)或一维矩阵运算(通过ExtendedMain.cpp
入口)。
欢迎提交 Issue 和 Pull Request。
MIT License
相信你已经在线性代数或者高等代数中接触过矩阵的概念。矩阵是一个按照长方阵列排列的复数或实数集合,支持加法、减法、数乘、乘法等运算。矩阵还具有行列式、秩、特征值和特征向量等重要概念和性质,在数学中广泛应用于线性方程组求解、向量空间变换等方面,同时在物理学、计算机科学、工程学等众多领域也发挥着关键作用,是进行数据处理和分析、解决实际问题的重要数学工具。本次作业要求你实现一个矩阵操作的程序,支持矩阵的一系列运算,并简单探索矩阵在计算机图形学中的应用。详细内容如下:
在阅读下面的题目要求前,建议你先下载附件,对照其中的参考代码框架阅读。
附件下载链接: 矩阵运算大作业附件.zip
设计一个主菜单,让用户选择具体运算,界面大致如下。退出系统前用户可进行任意次操作。
注意: 用户选择菜单项后不需要输入回车直接跳转到相应选项中。
如果输入非法字符(除
下面是你需要实现功能的具体说明。
矩阵加法结果为对应元素相加。
\begin{bmatrix} 6 & 8 \ 10 & 12 \end{bmatrix} $$
注意:两个列数、行数都相等的矩阵(同型矩阵),加法运算才有意义。
将整数与矩阵中的每一个元素分别相乘所得的矩阵。
\begin{bmatrix} 4 & 8 \ 12 & 16 \end{bmatrix} $$
将
设矩阵 $$ A = (a_{ij}){m \times s}, \quad B = (b{ij}){s \times n}, $$ 则 $A$ 与 $B$ 的乘积为 $$ C = (c{ij}){m \times n}, \quad \text{其中 } c{ij} = \sum_{k=1}^{s} a_{ik} b_{kj}, \quad (i=1,2,\ldots,m; ; j=1,2,\ldots,n). $$ 比如: $$ \begin{bmatrix} 1 & 2 & 3 \ 4 & 5 & 6 \end{bmatrix} \times \begin{bmatrix} 3 & -4 \ -2 & 5 \ 1 & -6 \end{bmatrix}
\begin{bmatrix} 2 & -12 \ 8 & -27 \end{bmatrix} $$
注意:矩阵
$A$ 的列数和矩阵$B$ 的行数相等时,矩阵乘法运算才有意义。
合法性约束与矩阵加法相同,只是对应元素运算变为乘法:
\begin{bmatrix} 1 & 4 \ 9 & 16 \end{bmatrix} $$
卷积的计算方式如下
设矩阵
-
先把
$B$ 放到矩阵$A$ 上,并且$A$ 的[0,0]
元素与$B$ 的[0,0]
元素对齐,则重叠出$3\times3$ 的矩阵。 -
再把重叠位置对应的元素相乘,得到 1 个
$3\times3$ 的矩阵([0,0]
位置对齐的结果如下)。 -
把上面结果的所有元素相加,得到卷积结果矩阵
[0,0]
位置的值。 $$ 0\times(-1) + 25\times0 + 75\times1 + 0\times(-1) + 75\times0 + 80\times1 + 0\times(-1) + 75\times0 + 80\times1 = 235 $$ -
这里采用的步长 (stride) 是
$1$ ,填补 (padding) 为$0$ 。则接下来把$B$ 的[0,0]
与$A$ 的[0,1]
对齐,再进行上面步骤的计算,得到结果矩阵[0,1]
位置的值。当一行计算完成,则把$B$ 的[0,0]
与$A$ 的[1,0]
对齐,进行计算,以此类推。 -
如果增加填充 (padding),以
padding=1
为例,则在矩阵$A$ 的外围填补一圈$0$ ,使得矩阵$A$ 变成$7\times7$ 的矩阵。 -
不考虑 dilation.
注意: 本次作业要求
kernel size = 3, padding = 1, stride = 1, dilation = 1
;可参考示例网站:https://ezyang.github.io/convolution-visualizer/index.html.
实现一个利用卷积操作应用与图像处理的简单示例:
假设矩阵 demolena.jpg
(大小为 int
),分别采用如下卷积核(矩阵
提示:这都是数字图像处理中非常经典的滤波器,所得到的图片效果也不尽相同,注意观察并分析原因。
对于这一部分内容,请认真阅读 “vs+opencv 配置说明”,操作完成后,取消框架程序开始的两段注释:
#include <opencv2/opencv.hpp>
using namespace cv;
然后完成 demo
函数功能,将原图和不同卷积操作后的图像显示在屏幕上,并观察结果。具体包括:
- 读取原图并显示;
- 计算原图矩阵与卷积核
$B_1$ 的卷积结果并图像显示; - 计算原图矩阵与卷积核
$B_2$ 的卷积结果并图像显示; - 计算原图矩阵与卷积核
$B_3$ 的卷积结果并图像显示; - 计算原图矩阵与卷积核
$B_4$ 的卷积结果并图像显示; - 计算原图矩阵与卷积核
$B_5$ 的卷积结果并图像显示; - 计算原图矩阵与卷积核
$B_6$ 的卷积结果并图像显示。
学有余力的同学可以选取下面一个或多个任务完成。加分项开放使用 opencv
库函数。
使用一维数组实现上述功能。
在菜单中加入功能 “8 OTSU 算法”,并完成下述功能:使用 OTSU 算法对 lena 图像进行二值化,结果如下所示:
请自行学习该算法原理与实现方法。
你已经掌握了上述图像处理的简单方法—二值化,请在此基础上配合其它方法,对下述测试样例进行处理,保留目标区域并设置背景为黑色,结果如下所示,处理结果类似即可,没有标准答案:
① 实验室前任团宠“雪球” - snowball.jpg
(200×150)
② 多角星形 - polyhedrosis.jpg
(98×90)
请按照文件打包要求上传你的项目代码。务必记得清除不必要的文件(包括一些隐藏文件)!