1 条题解
-
0
题意分析
本题要求对给定的二值图像进行形态学处理,具体包括两种基本操作:腐蚀和膨胀,并利用这两种操作分别实现图像的开运算和闭运算。
输入一个大小为 m×n 的二值图像,用字符串数组表示,每个字符为 ' * '(表示前景像素)或 '.'(表示背景像素)。
结构元素 B,其大小为 (2s+1)×(2s+1),同样用字符串数组表示,其中 ' * ' 表示参与操作的像素点,'.' 表示不考虑的位置。
相关操作:
腐蚀:对于图像中每个像素 (i, j),将结构元素 B 放置到以 (i, j) 为中心的区域,如果 B 中所有为' * ' 的位置在原图像中对应位置也均为 ' * ',则输出图像 (i, j) 位置为 ' * ';否则输出为 '.'。注意边界处可能因结构元素超出图像范围而直接判定为背景。
膨胀:对于图像中每个像素 (i, j),若该像素为 ' * ',则将结构元素 B 放置到图像上(即对 B 中每个 ' * ' 所在位置,将 (i+bi-s, j+bj-s) 处设为 ' * ',前提是该位置在图像范围内)。
开运算:对原图像进行腐蚀,再对腐蚀后的图像进行膨胀。主要用于去除噪点,同时保持图像的主要结构。
闭运算:对原图像进行膨胀,再对膨胀后的图像进行腐蚀。主要用于填充图像中的小空洞,同时保持主要结构不变。
题解思路
1、数据预处理:
读取图像的尺寸 m 和 n,以及结构元素半径 s(实际结构元素大小为 2*s+1)。
分别读入图像 A 和结构元素 B。
2、腐蚀操作:
对于图像中每个像素 (i, j),将结构元素 B 中每个 ' * ' 的位置对应到原图像上,判断映射后的坐标 (i + bi - s, j + bj - s) 是否在图像范围内且为 ' * '。
若存在任一位置不满足上述条件(即越界或原图像中对应位置为背景 '.'),则当前点 (i, j) 在腐蚀结果中设为 '.';否则设为 ' * '。
3、膨胀操作:
遍历原图像中所有像素 (i, j),若该像素为 ' * ',则将结构元素 B 中每个 ' * ' 对应的位置 (i + bi - s, j + bj - s) 置为 ' * '(前提是该位置在图像范围内)。
由于多个前景像素可能会影响同一个位置,所以只要有一次赋值 ' * ',该位置在输出图像中即为 ' * '。
4、开运算:
首先对原图像 A 调用腐蚀操作得到腐蚀图像;然后对腐蚀图像调用膨胀操作,得到开运算结果。
5、闭运算:
首先对原图像 A 调用膨胀操作得到膨胀图像;然后对膨胀图像调用腐蚀操作,得到闭运算结果。
本题代码
#include <iostream> #include <vector> #include <string> #include <algorithm> using namespace std; vector<string> erosion(const vector<string>& img, const vector<string>& B, int m, int n, int s) { int bs = 2 * s + 1; vector<string> out(m, string(n, '.')); int i, j, bi, bj; for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { bool ok = true; for (bi = 0; bi < bs && ok; bi++) { for (bj = 0; bj < bs && ok; bj++) { if (B[bi][bj] == '*') { int ii = i + bi - s; int jj = j + bj - s; if (ii < 0 || ii >= m || jj < 0 || jj >= n || img[ii][jj] == '.') { ok = false; } } } } if (ok) out[i][j] = '*'; else out[i][j] = '.'; } } return out; } vector<string> dilation(const vector<string>& img, const vector<string>& B, int m, int n, int s) { int bs = 2 * s + 1; vector<string> out(m, string(n, '.')); int i, j, bi, bj; for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { if (img[i][j] == '*') { for (bi = 0; bi < bs; bi++) { for (bj = 0; bj < bs; bj++) { if (B[bi][bj] == '*') { int ii = i + bi - s; int jj = j + bj - s; if (ii >= 0 && ii < m && jj >= 0 && jj < n) out[ii][jj] = '*'; } } } } } } return out; } int main() { ios::sync_with_stdio(false); cin.tie(NULL); int m, n, s; int caseNum = 1; bool firstCase = true; while(cin >> m >> n >> s) { if(m == 0 && n == 0 && s == 0) break; int i; vector<string> A(m); for(i = 0; i < m; i++){ cin >> A[i]; } int bs = 2 * s + 1; vector<string> B(bs); for(i = 0; i < bs; i++){ cin >> B[i]; } vector<string> eroded = erosion(A, B, m, n, s); vector<string> openImg = dilation(eroded, B, m, n, s); vector<string> dilated = dilation(A, B, m, n, s); vector<string> closeImg = erosion(dilated, B, m, n, s); if(!firstCase) cout << string(75, '=') << "\n"; firstCase = false; cout << "Case " << caseNum++ << "\n\n"; for(i = 0; i < m; i++){ cout << openImg[i] << "\n"; } cout << "\n"; for(i = 0; i < m; i++){ cout << closeImg[i] << "\n"; } cout << "\n"; } return 0; }
- 1
信息
- ID
- 1716
- 时间
- 10000ms
- 内存
- 64MiB
- 难度
- 10
- 标签
- 递交数
- 5
- 已通过
- 1
- 上传者