hihocoder #1363 图像算子
Time Limit:10000ms
Case Time Limit:1000ms
Memory Limit:256MB
Description
在图像处理的技术中,经常会用到算子与图像进行卷积运算,从而达到平滑图像或是查找边界的效果。
假设原图为H × W的矩阵A,算子矩阵为D × D的矩阵Op,则处理后的矩阵B大小为(H-D+1) × (W-D+1)。其中:
B[i][j] = ∑(A[i-1+dx][j-1+dy]*Op[dx][dy]) | (dx = 1 .. D, dy = 1 .. D), 1 ≤ i ≤ H-D+1, 1 ≤ j ≤ W-D+1
给定矩阵A和B,以及算子矩阵的边长D。你能求出算子矩阵中每个元素的值吗?
Input
第1行:3个整数,H, W, D,分别表示原图的高度和宽度,以及算子矩阵的大小。5≤H,W≤60,1≤D≤5,D一定是奇数。
第2..H+1行:每行W个整数,第i+1行第j列表示A[i][j],0≤A[i][j]≤255
接下来H-D+1行:每行W-D+1个整数,表示B[i][j],B[i][j]在int范围内,可能为负数。
输入保证有唯一解,并且解矩阵的每个元素都是整数。
Output
第1..D行:每行D个整数,第i行第j列表示Op[i][j]。
- Sample Input
-
5 5 3 1 6 13 10 3 13 1 5 6 15 8 2 15 0 12 19 19 17 18 18 9 18 19 5 17 22 15 6 35 -36 51 -20 3 -32
Sample Output
0 1 0 1 -4 1 0 1 0
Solution:
1 #include <iostream> 2 #include <climits> 3 #include <cmath> 4 #include <algorithm> 5 #include <cstdio> 6 #include <cstring> 7 using namespace std; 8 int H, W, D; 9 10 int **img; 11 int **fimg; 12 float **matrix; 13 float *Y; 14 float *kernel; 15 16 void swapRow(int i, int j) { 17 for (int k = 0; k < D*D; ++k) { 18 swap(matrix[i][k], matrix[j][k]); 19 } 20 } 21 22 void print() { 23 for (int i = 0; i < H-D+1; ++i) { 24 for (int j = 0; j < W-D+1; ++j) { 25 for (int s = 0; s < D; ++s) { 26 for (int t = 0; t < D; ++t) { 27 printf("%.1f ", matrix[i*(W-D+1)+j][s*D+t]); 28 } 29 } 30 printf("= %.1f\n", Y[i*(W-D+1)+j]); 31 } 32 } 33 printf("\n"); 34 35 } 36 37 int ftoi(float f) { 38 return floor(f+0.01); 39 } 40 41 void sol() { 42 Y = new float[(H-D+1)*(W-D+1)]; 43 matrix = new float*[(H-D+1)*(W-D+1)]; 44 for (int i = 0; i < H-D+1; ++i) { 45 for (int j = 0; j < W-D+1; ++j) { 46 Y[i*(W-D+1)+j] = fimg[i][j]; 47 matrix[i*(W-D+1)+j] = new float[D*D]; 48 for (int s = 0; s < D; ++s) { 49 for (int t = 0; t < D; ++t) { 50 matrix[i*(W-D+1)+j][s*D+t] = img[i+s][j+t]; 51 //printf("%d ", (int)matrix[i*(W-D+1)+j][s*D+t]); 52 } 53 } 54 //printf("= %d\n", (int)Y[i*(W-D+1)+j]); 55 } 56 } 57 //print(); 58 int len = (H-D+1)*(W-D+1); 59 for (int i = 0; i < len; ++i) { 60 int t = i; 61 for (; t < len; ++t) { 62 if (matrix[t][i] != 0) { 63 break; 64 } 65 } 66 if (t < len) { 67 if (i != t) swapRow(i, t); 68 } 69 else { 70 continue; 71 } 72 float d = matrix[i][i]; 73 for (int j = 0; j < D*D; ++j) { 74 matrix[i][j] /= d; 75 } 76 Y[i] /= d; 77 78 for (int k = i+1; k < len; ++k) { 79 d = matrix[k][i]; 80 for (int s = i; s < D*D; ++s) { 81 matrix[k][s] -= d * matrix[i][s]; 82 } 83 Y[k] -= d*Y[i]; 84 } 85 //print(); 86 } 87 88 kernel = new float[D*D]; 89 90 for (int i = D*D-1; i >= 0; --i) { 91 float f = 0; 92 for (int j = D*D-1; j > i; --j) { 93 f += kernel[j]*matrix[i][j]; 94 } 95 kernel[i] = Y[i]-f; 96 } 97 98 for (int i = 0; i < D*D; ++i) { 99 printf("%d%c", ftoi(kernel[i]), i%D == D-1 ? '\n' : ' '); 100 } 101 } 102 103 int main(int argc, char *argv[]) { 104 scanf("%d%d%d", &H, &W, &D); 105 img = new int*[H]; 106 for (int i = 0; i < H; ++i) { 107 img[i] = new int[W]; 108 for (int j = 0; j < W; ++j) { 109 scanf("%d", img[i] + j); 110 } 111 } 112 fimg = new int*[H-D+1]; 113 for (int i = 0; i < H-D+1; ++i) { 114 fimg[i] = new int[W-D+1]; 115 for (int j = 0; j < W-D+1; ++j) { 116 scanf("%d", fimg[i] + j); 117 } 118 } 119 120 sol(); 121 }