题目描述
当被拍摄物偏离出焦距以外,成像模糊,就会造成失焦。对给出的模糊的原始图像进行恢复是图像处理中最有趣的课题之一。这一过程被称为去模糊,这也是本题要求您解决的任务。
在本题中,所有的图像都是灰色的(没有颜色);一个图像表示为一个实数的二维矩阵,其中每个单元是对应像素的亮度。虽然在数学上讲并不精确,但是,一个清晰的图像被模糊化,就是将距离每个像素(包括该像素本身)的某个曼哈顿距离内(小于或等于)的所有像素的值取平均值,赋给这个像素。下面是一个如何计算模糊距离为 1 的 3×3
图像的模糊度的示例:
本题给出一个图像的模糊版本,要求恢复原始图像的版本。本题设定给出的图像是模糊的,如上所述。 两点之间的曼哈顿距离(也被称为出租车距离)是它们坐标的绝对值的差的总和。 下面的网格给出了与灰色单元格之间的曼哈顿距离。
输入输出格式
输入格式 输入包含若干测试用例。每个测试用例 H+1 行,第一行给出三个非负整数,分别表示模糊图像的宽度 W,高度 H,以及模糊距离 D,其中,1≤W,H≤10
,且 D≤min(W/2,H/2)
。接下来的 H 行给出模糊图像中每个像素的灰度,每行给出 W 个非负实数,实数保留小数点后两位,所有给出的实数值都小于 100。 在测试用例之间可能是零行,也可能有多行(完全由空格组成)。输入的最后一行由三个零组成。
输出格式 对于每个测试用例,输出一个 W×H
的实数矩阵,表示图像的去模糊之后的版本。矩阵中的每个元素精确到两位小数,并在宽度为 8 的字段中向右对齐。用一个空行分隔两个连续的测试用例的输出。在最后一个测试用例之后不要输出空行。本题设定每个测试用例都有一个唯一的解。
输入输出样例1
输入
2 2 1
1 1
1 1
3 3 1
19 14 20
12 15 18
13 14 16
4 4 2
14 15 14 15
14 15 14 15
14 15 14 15
14 15 14 15
0 0 0
输出
1.00 1.00
1.00 1.00
2.00 30.00 17.00
25.00 7.00 13.00
14.00 0.00 35.00
1.00 27.00 2.00 28.00
21.00 12.00 17.00 8.00
21.00 12.00 17.00 8.00
1.00 27.00 2.00 28.00
#include <iostream> #include <cstring> #include <cmath> #include <iomanip> #define endl '\n' #define IOS ios::sync_with_stdio(false); using namespace std; typedef long long ll; const double eps = 1e-8; bool isFirst = true; struct Matrix { int h, w; double m[105][105]; void init(int totalh, int totalw) { h = totalh; w = totalw; memset(m, 0, sizeof m); } void Guass() { for (int i = 0 ; i < h-1 ; i++) { //交换行(减小误差) int t = i; for (int j = i+1 ; j < h ; j++) { if (fabs(m[j][i]) > fabs(m[t][i])) t = j; } if (t != i) { for (int j = 0 ; j < w ; j++) swap(m[t][j],m[i][j]); } //消元 for (int j = i+1 ; j < h ; j++) { if (fabs(m[j][i]) < eps) continue; double mul = m[j][i] / m[i][i]; for (int k = i ; k < w ; k++) m[j][k] -= m[i][k] * mul; } } //反向求解 for (int i = h-1 ; i >= 0 ; i--) { if (fabs(m[i][i]) < eps) continue; for (int j = i+1 ; j < h ; j++) m[i][w-1] -= m[i][j]*m[j][w-1]; m[i][w-1] /= m[i][i]; } } }; int main() { //IOS; cin.tie(0), cout.tie(0); int w, h, d; double a[15][15]; while (cin >> w >> h >> d) { if (w == 0 && h == 0 && d == 0) break; for (int i = 0; i < h; ++i) { for (int j = 0; j < w; ++j) { cin >> a[i][j]; } } if (isFirst) { isFirst = false; } else { cout << endl; } Matrix ans; ans.init(h * w, h * w + 1); //高斯消元的不可少的步骤 for (int i = 0; i < h; ++i) { for (int j = 0; j < w; ++j) { int cnt = 0; //记录一个点的曼哈顿距离能够到达的个数 for (int k = i - d; k <= i + d; ++k) //枚举能到达的行 { if (k < 0 || k >= h) continue; int left = d - abs(i - k); for (int l = j - left; l <= j + left; ++l) { if (l < 0 || l >= w) continue; cnt++; ans.m[i * w + j][k * w + l] = 1; //第i * w + j行方程的第k * w + l } } ans.m[i * w + j][h * w] = cnt * a[i][j]; } } ans.Guass(); for (int i = 0 ; i < h ; ++i) { for (int j = 0 ; j < w ; ++j) printf ("%8.2lf",ans.m[i * w + j][ans.w - 1]); printf ("\n"); } } return 0; }