Skip to content

19942: 二维矩阵上的卷积运算

matrices, OOP, http://cs101.openjudge.cn/practice/19942/

描述

二维矩阵上的卷积,是卷积神经网络中经常需要进行的一种运算。该运算在输入的二维矩阵上滑动不同的卷积核,并在每一个滑动的位置上将卷积核与输入图像对应位置的元素进行相乘并逐个求和的运算。下图很好地说明了运算的结果矩阵的每一个位置是如何计算得来的。本题中在行列方向的滑动均以1为步长进行,且输入输出均为整数。

如对第1行第1列,12 = 3*0+3*1+2*2+0*2+0*2+1*0+3*0+1*1+2*2。

img

输入

第一行4个整数,分别代表二维矩阵的行数和列数m和n以及卷积核的行数和列数p和q (1 <= p <= m; 1 <= q <= n) 接下来m行,每行为空格分隔的n个整数,代表二维数组中每行的数据。 接下来p行,每行为空格分隔的q个整数,代表卷积核中每行的数据。

输出

易知,p*q的卷积核在m*n的矩阵上以1为步长滑动,横向一共有m+1-p个位置,纵向一共有n+1-q个位置。 因此输出共m+1-p行,每行为以空格分隔的n+1-q个整数,代表卷积运算后的结果。

样例输入

Sample1 Input:
5 5 3 3
3 3 2 1 0
0 0 1 3 1
3 1 2 2 3
2 0 0 2 2
2 0 0 0 1
0 1 2
2 2 0
0 1 2

Sample1 Output:
12 12 17
10 17 19
9 6 14

样例输出

Sample2 Input:
5 4 4 4
10 -8 6 9
7 -9 1 0
1 -9 2 -5
-3 6 -1 2
-10 -2 -1 -2
-9 -1 -6 10
3 -2 -5 9
-10 -3 -10 7
3 -2 -7 0 

Sample2 Output:
-46
-77

来源:cs101-2019 Final Exam

思路:按照输入构造两个矩阵,再用for loop进行卷积运算。

python
m,n,p,q = map(int, input().split())
yuan=[[int(x) for x in input().split()] for _ in range(m)]
juan=[[int(x) for x in input().split()] for _ in range(p)]
answer=[[None]*(n-q+1)  for _ in range(m-p+1)]
def j(x,y):
    s=0
    for i in range(p):
        for j in range(q):
            s += juan[i][j]*yuan[i+x][j+y]
    return s

for a in range(m-p+1):
    for b in  range(n-q+1):
        answer[a][b] = str(j(a,b))
        
for i in range(m-p+1):
    print(' '.join(answer[i]))

OOP

python
class Matrix():
    def __init__(self, row, col, val):
        self.row = row
        self.col = col
        self.val = val

    def __add__(self, other):
        if self.row != other.row or self.col != other.col:
            raise ValueError
        ans = [[self.val[i][j] + other.val[i][j] for j in range(self.col)] for i in range(self.row)]
        return Matrix(self.row, self.col, ans)

    def __str__(self):
        ans = []
        for r in self.val:
            ans.append(" ".join(map(str, r)))
        return "\n".join(ans)

    def __mul__(self, other):
        if self.col != other.row:
            raise ValueError
        ans = [[0 for i in range(other.col)] for j in range(self.row)]
        for i in range(self.row):
            for j in range(other.col):
                for k in range(self.col):
                    ans[i][j] += self.val[i][k] * other.val[k][j]
        return Matrix(self.row, other.col, ans)


class ConvMatrix(Matrix):
    def __init__(self, row, col, val):
        super().__init__(row, col, val)

    def conv2d(self, kernel):
        # 获取卷积核的尺寸
        k_row, k_col = len(kernel), len(kernel[0])

        # 计算输出矩阵的尺寸
        out_row = self.row - k_row + 1
        out_col = self.col - k_col + 1

        # 初始化输出矩阵
        output_val = [[0] * out_col for _ in range(out_row)]

        # 进行卷积运算
        for i in range(out_row):
            for j in range(out_col):
                for ki in range(k_row):
                    for kj in range(k_col):
                        output_val[i][j] += self.val[i + ki][j + kj] * kernel[ki][kj]

        return Matrix(out_row, out_col, output_val)


if __name__ == "__main__":
    m, n, p, q = map(int, input().split())
    M = ConvMatrix(m, n, [list(map(int, input().split())) for _ in range(m)])

    kernel = []
    for _ in range(p):
        kernel.append(list(map(int, input().split())))

    result = M.conv2d(kernel)
    for row in result.val:
        print(" ".join(map(str, row)))

2020fall-cs101,顾臻宜。思路:依题意,个人习惯先将一行的各列相加,再将各行相加。想清楚即可。

python
m,n,p,q = map(int, input().split())
A = [[0 for x in range(n)] for i in range(m)]   #二维矩阵
B = [[0 for x in range(q)] for i in range(p)]   #卷积核
C = [[0 for x in range(n+1-q)] for i in range(m+1-p)]   #二维矩阵上的卷积运算
for i in range(m):
    A[i] = [int(x) for x in input().split()]
for i in range(p):
    B[i] = [int(x) for x in input().split()]

for i in range(m+1-p):
    for j in range(n+1-q):
        for s in range(p):
            for t in range(q):
                C[i][j] = C[i][j] + A[i+s][j+t] * B[s][t]

for i in range(m + 1 - p):
    print(' '.join(map(str, C[i])))