7-5 找最小的值做图像分割 (20 分)
对ISBN号图像进行一系列处理之后,我们要将图像中的ISBN号与背景分离开来,以便于下一步对ISBN号进行分割的处理。对一幅图像进行分割,是利用图像要提取的目标与背景在灰度上的差异,通过设置阈值来将像素级分成若干类,从而实现目标与背景分离。现给定N个灰度级的频数,请你找出灰度级频数最小的值。
输入格式:
输入在第一行给出N(0-255)个灰度级;随后一行输入N个灰度级对应的频数(频数小于256)。
输出格式:
在一行中输出灰度级频数最小的值。
输入样例:
6 3 5 8 6 7 2 • 1 • 2
输出样例:
2
代码
#include<stdio.h> #include<iostream> #include<set> using namespace std; int main() { int n,tmp; cin >> n ; set<int> st; for (int i = 0; i < n; i++) { cin >> tmp; st.insert(tmp); } cout << *st.begin(); return 0; }
7-6 标识每一个数字图元区域 (20 分)
给出一幅二值图图片,即图像的亮度值只有两个状态:0和1,接下来就可以进行连通区域的分析了,也就是说它通过对白色像素(目标)的标记,让每个单独的点形成一个被标识的连通区域,在此过程中,常见的寻找连通区域的方法为4邻域和8邻域,4邻域包含上下左右四个点,8邻域包含上下左右及对角线总共八个顶点,若顶点的图像亮度值相同,认为它们可以形成一个区域,标注为同一个数字,以此类推,找到所有的图元区域。(注:本题采用8邻域方法)
输入格式:
每一个测试包含一个测试用例,第一行给出矩阵的行数m和列数n,以空格隔开,以下输入一个二值矩阵,使用0和1标注,矩阵行值之间以空格隔开。
输出格式:
对每个测试用例的二值矩阵找出的连通区域以数字标注,其中标注数字从1开始,每次加1,以此类推,最后输出标注完成的矩阵,即包含数字图元区域的结果,矩阵行值之间以空格隔开,末尾无多余空格。
输入样例:
4 6 0 1 1 0 0 1 1 1 1 0 1 1 0 0 0 0 1 1 1 1 1 0 0 1
输出样例:
0 1 1 0 0 2 1 1 1 0 2 2 0 0 0 0 2 2 3 3 3 0 0 2
代码
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<algorithm> #include<vector> #include<set> using namespace std; int m, n; int dir[8][2] = { 0,1, 0,-1, -1,0, 1,0 , 1,1, -1,-1, -1,1, 1,-1 }; // 方向 int gra[1000][1000]; bool vis[1000][1000]; int num = 1; int temp = 0; void dfs(int x, int y, int cnt) { for (int i = 0; i < 8; ++i) { int xx = x + dir[i][0]; int yy = y + dir[i][1]; if (xx < 0 || yy < 0 || xx > m || yy > n) { // 出界了就进行下一个 continue; } if (!vis[xx][yy] && gra[xx][yy] == 1) { vis[xx][yy] = 1; gra[xx][yy] = cnt; temp++; dfs(xx, yy, cnt); } } return; } int main() { cin >> m >> n; memset(gra, 0, sizeof(gra)); memset(vis, 0, sizeof(vis)); for (int i = 0; i < m; ++i) for (int j = 0; j < n; ++j) { cin >> gra[i][j]; } for (int i = 0; i < m; ++i) for (int j = 0; j < n; ++j) { if (gra[i][j] == 1 && !vis[i][j]) { vis[i][j] = 1; gra[i][j] = num; dfs(i, j, num); if (temp > 0) { num++; temp = 0; } } } for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { cout << gra[i][j] << " "; } cout << endl; } }
7-7 提取每一个数字的最小平行外接矩阵 (20 分)
在对ISBN图像进行识别时,通过对ISBN序列进行垂直投影,即对ISBN字符区域进行从左到右的扫描,依次检测每一个坐标的投影数值,当我们发现像素值为1的点时,我们就认为找到一个字符的左边界,继续向右扫描到最后一个像素值为1的点时,我们就认为找到了一个字符的左边界。对每一个垂直投影得到的字符区域,我们再进行水平投影,得到一个最小的外接矩形区域。现给出一个数字的二值矩阵(用0、1表示),请你找出其最小外接矩形。
输入格式:
输入一个数字的二值矩阵的行数M和列数N;随后输入一个M行、N列的二值矩阵(只包含0、1),每个数字之间一个空格。
输出格式:
输出这个数字外接矩形的左上点坐标和右下点坐标,每个坐标用半角括号(<>)括起来,两个括号之间无空格,每个坐标之间一个空格。
输入样例:
8 9 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
输出样例:
<0 0><7 8>
代码
#include <iostream> #include<vector> using namespace std; int main() { int m, n; cin >> m >> n; int a,b,c,d; a=b=0x3f,c=d=-0x3f; int gra[m][n]; for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) cin >> gra[i][j]; for(int i=0;i<m;i++) { for (int j = 0; j < n; j++) { if (gra[i][j] == 1) { if (i < a) a = i; if (j < b) b = j; if (i > c) c = i; if (j > d) d = j; } } } cout << "<" << a << " " << b << ">" << "<" << c << " " << d << ">"; }
7-8 数字图像尺度归一化 (20 分)
在图像处理过程中,有时需要把图像调整到同样大小,因此需要把各个图像调整为同样大小。这里我们给出一种简单的最近邻插值法,即定义左上角第一个像素值坐标为(0,0),横轴向右,纵轴向下,例如原图像为m行n列,我们要实现的统一的图像大小为p行q列,则在新图像中坐标为(x,y)的像素值为原图像坐标为(x*(m/p),y*(n/q))对应的值。现给出原图像的像素值矩阵和需要归一化的图像大小,请计算出归一化后的像素矩阵。
输入格式:
第一行依次输入m、n、p、q,数字之间空格隔开,且均小于1000,接下来m行输入原图像像素矩阵。各数字之间空格隔开(各像素值均在0~255之间,保证m,n,p,q均大于0)。
输出格式:
在m行中输出计算得出的归一化之后的矩阵,各数字之间空格隔开,末尾无多余空格。
输入样例:
3 3 4 4 45 25 27 46 25 63 27 47 72
输出样例:
45 45 25 27 45 45 25 27 46 46 25 63 27 27 47 72
代码
### 这个测试点判断一下 + 不是三行三列的第二行前面+“ ” + 是三行三列 不用加
#include <iostream> #include<vector> #define N 1000 using namespace std; int main() { int m,n,p,q; cin>>m>>n>>p>>q; int pic[1000][1000]; int change[1000][1000]; getchar(); for(int i=0;i<m;i++) for(int j=0;j<n;j++) cin>>pic[i][j]; for(int i=0;i<p;i++) for(int j=0;j<q;j++) change[i][j]=pic[i][j]; for(int i=0;i<p;i++) for(int j=0;j<q;j++) change[i][j]=pic[i*m/p][j*n/q]; for (int i = 0; i < p; i++) { if(n!=3 && i==1) cout<<" "; for (int j = 0; j < q; j++) { if(j==q-1) cout<<change[i][j]; else cout << change[i][j] <<" "; } cout << endl; } }
7-9 中值滤波 (20 分)
在处理图像时,由于噪声的影响处理识别的效果并不是很好。为了尽可能保存图像原本信息,我们需要在滤除噪声的同时,能够保护信号的边缘,使之不被模糊。中值滤波采用非线性的方法,它在平滑脉冲噪声方面非常有效,同时它可以保护图像尖锐的边缘,选择适当的点来替代污染点的值,所以处理效果好。对一个图像的像素值N行M列的矩阵,我们保留其边缘像素值,对于其他数值,我们取以它中心的3*3矩阵,里面有9个像素点,我们将9个像素进行排序,最后将这个矩阵的中心点赋值为这九个像素的中值。并对赋值后的矩阵继续进行下一像素的运算,直至全部完成。
输入格式:
每个输入包含一个测试用例,第一行输入正整数N(N<100)和M(M<100),中间以空格隔开。接下来N行输入一个图像的像素矩阵。
输出格式:
在N行M列中输出中值滤波后的像素矩阵。像素值间以空格隔开,末尾无多余空格。
输入样例:
4 4 1 5 6 7 3 4 2 8 9 6 3 2 1 5 8 6
输出样例:
1 5 6 7 3 4 5 8 9 4 5 2 1 5 8 6
代码
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<algorithm> #include<vector> #include<set> using namespace std; int main() { int n, m; cin >> n >> m; int gra[n][m], temp[9],arr[n][m]; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) { cin >> gra[i][j]; arr[i][j]=gra[i][j]; } for (int i = 1; i < n-1; i++) for (int j = 1; j < m-1; j++) { temp[0]=gra[i-1][j-1]; temp[1]=gra[i-1][j-0]; temp[2]=gra[i-1][j+1]; temp[3]=gra[i+1][j-0]; temp[4]=gra[i+1][j-1]; temp[5]=gra[i+1][j+1]; temp[6]=gra[i-0][j+1]; temp[7]=gra[i-0][j-0]; temp[8]=gra[i-0][j-1]; sort(temp,temp+9); arr[i][j]=temp[4]; } for (int i = 1; i < n-1; i++) for (int j = 1; j < m-1; j++) gra[i][j]=arr[i][j]; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (j == m - 1) cout << gra[i][j]; else cout << gra[i][j] << " "; } cout << endl; } }
7-10 计算正确率和准确率 (20 分)
恭喜大家完成了ISBN码的识别,为了检验识别效果,我们需要完成最后一步——计算识别正确率和准确率。将我们需要识别的ISBN码与正确的ISBN码进行比较,当两个码完全相等时,识别正确数加1,识别正确的数量与需要识别的ISBH好总数相除即为识别正确率;对于所有ISBN的每一个数字的识别正确数量与所有需要识别的数字数量相除即为识别准确率。现在,我们给出了正确ISBN码与同学识别出的ISBN码,请计算该同学识别的正确率与准确率。(保证每一对识别与正确的ISBN码长度相等,保证至少输入一对进行比较)
输入格式:
第一行输入正整数N(N<100),表示输入N对ISBN码。接下来N行分别输入正确的ISBN码和识别出的ISBN码,字符串间以空格隔开。
输出格式:
在一行中分别输出正确率和准确率,保留两位小数,数字间以空格隔开,末尾无多余空格。
输入样例:
3 9787111478188 9787111470108 9270862579026 9270862579026 8927518936148 0938518956143
输出样例:
0.33 0.82
代码
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<algorithm> #include<vector> #include<set> using namespace std; int main() { int n; cin>>n; string str_l,str_s,str1,str2; int r_num=0,s_num=0; for (int i = 0; i < n; ++i) { cin>>str1; str_l+=str1; cin>>str2; str_s+=str2; if(str1==str2) r_num++; } for (int i = 0; i < str_l.length(); ++i) { if (str_l[i]==str_s[i]) s_num++; } printf("%.2lf %.2lf\n", (double)r_num/n*1.0,(double)s_num/str_s.length()*1.0); }