You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无噪声场景下2D反卷积的C++实现方法(小矩阵适用)

针对小整数矩阵的C++反卷积实现(暴力/直接求解法)

前提:保证卷积可逆

要从卷积输出还原原始矩阵,必须确保卷积操作无信息丢失,满足以下条件:

  • 步长 stride = 1
  • 使用Same Padding:输入矩阵周围补零,让卷积输出矩阵尺寸和输入完全一致(比如3x3卷积核处理10x10输入,输出仍为10x10)
  • 卷积核尺寸为奇数(如3x3、5x5),确保每个输入元素都对应输出的有效计算

核心思路

卷积本质是线性变换:把输入矩阵元素按行优先展开为向量,卷积核对应一个变换矩阵,输出矩阵展开后是变换矩阵乘以输入向量。反卷积就是已知输出向量和变换矩阵,求解输入向量——这是一个线性方程组求解问题。

由于矩阵最大10x10(最多100个变量),直接用高斯消元法解方程组完全可行,属于暴力但高效的方案。

伪代码实现

1. 基础卷积函数(用于生成测试输出)

// 输入:原始矩阵I(MxM),卷积核K(NxN, N为奇数)
// 输出:Same Padding后的卷积矩阵O(MxM)
vector<vector<int>> convolution(vector<vector<int>>& I, int M, vector<vector<int>>& K, int N) {
    int k = (N - 1) / 2; // 卷积核半宽
    vector<vector<int>> O(M, vector<int>(M, 0));
    
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < M; j++) {
            int sum = 0;
            for (int dx = -k; dx <= k; dx++) {
                for (int dy = -k; dy <= k; dy++) {
                    int x = i + dx;
                    int y = j + dy;
                    if (x >= 0 && x < M && y >= 0 && y < M) {
                        sum += I[x][y] * K[dx + k][dy + k];
                    }
                }
            }
            O[i][j] = sum;
        }
    }
    return O;
}

2. 反卷积函数(高斯消元解线性方程组)

步骤1:构建线性方程组

把输入矩阵I的所有元素按行优先展开为向量 x(共M²个变量),输出矩阵O的元素展开为向量 b(共M²个方程),构建变换矩阵A(M²×M²),其中A[p][q]表示第p个方程中第q个变量的系数(即卷积核对应位置的值,若变量参与该方程计算则赋值,否则为0)。

// 输入:卷积输出O(MxM),卷积核K(NxN, N为奇数)
// 输出:还原的原始矩阵I(MxM)
vector<vector<int>> deconvolution(vector<vector<int>>& O, int M, vector<vector<int>>& K, int N) {
    int k = (N - 1) / 2;
    int var_count = M * M;
    int eq_count = M * M;
    
    // 构建增广矩阵:每行格式为 [A的一行] + [b的对应值]
    vector<vector<double>> aug(eq_count, vector<double>(var_count + 1, 0.0));
    
    for (int p = 0; p < eq_count; p++) {
        int i = p / M;
        int j = p % M;
        aug[p][var_count] = O[i][j]; // 方程右侧的值
        
        for (int dx = -k; dx <= k; dx++) {
            for (int dy = -k; dy <= k; dy++) {
                int x = i + dx;
                int y = j + dy;
                if (x >= 0 && x < M && y >= 0 && y < M) {
                    int q = x * M + y; // 变量对应的索引
                    aug[p][q] = K[dx + k][dy + k]; // 系数为卷积核对应值
                }
            }
        }
    }
    
    // 执行高斯消元求解
    gauss_jordan(aug, var_count, eq_count);
    
    // 将解向量还原为矩阵
    vector<vector<int>> I(M, vector<int>(M, 0));
    for (int q = 0; q < var_count; q++) {
        int x = q / M;
        int y = q % M;
        I[x][y] = round(aug[q][var_count]); // 四舍五入还原整数
    }
    return I;
}

3. 高斯-约旦消元法(适配整数场景)

void gauss_jordan(vector<vector<double>>& aug, int var_count, int eq_count) {
    for (int col = 0; col < var_count; col++) {
        // 找到当前列绝对值最大的主元行
        int pivot_row = col;
        for (int row = col; row < eq_count; row++) {
            if (abs(aug[row][col]) > abs(aug[pivot_row][col])) {
                pivot_row = row;
            }
        }
        
        // 交换主元行与当前行
        swap(aug[col], aug[pivot_row]);
        
        // 归一化主元行,使主元为1
        double pivot_val = aug[col][col];
        if (fabs(pivot_val) < 1e-6) continue; // 主元为0,跳过(无解或无穷多解)
        for (int c = col; c <= var_count; c++) {
            aug[col][c] /= pivot_val;
        }
        
        // 消去其他行的当前列
        for (int row = 0; row < eq_count; row++) {
            if (row != col && fabs(aug[row][col]) > 1e-6) {
                double factor = aug[row][col];
                for (int c = col; c <= var_count; c++) {
                    aug[row][c] -= factor * aug[col][c];
                }
            }
        }
    }
}

注意事项

  • 只有卷积核对应的变换矩阵可逆时,才能得到唯一解。若变换矩阵不可逆,可能有无穷多解或无解(比如卷积核全零、存在线性相关行)。
  • 由于处理整数矩阵,高斯消元后需四舍五入还原整数,若出现非整数解,说明卷积操作存在信息丢失或原始矩阵非整数。
  • 极小矩阵(如3x3)可尝试暴力枚举:遍历原始矩阵元素的可能整数值,验证卷积结果是否匹配输出,但10x10矩阵不适用该方法。

内容的提问来源于stack exchange,提问作者oxheron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 15:25:23