c++ - c++中的卷积实现

标签 c++ opencv filter convolution

想自己用C++实现二维卷积函数,不使用filter2D()。我正在尝试迭代输入图像和内核的所有像素,然后为 dst 的每个像素分配新值。 但是,我收到了这个错误。

Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)

我发现这个错误告诉我正在访问 nullptr,但我无法解决问题。这是我的 C++ 代码。

cv::Mat_<float> spatialConvolution(const cv::Mat_<float>& src, const cv::Mat_<float>& kernel)
{
//    declare variables
    Mat_<float> dst;
    Mat_<float> flipped_kernel;
    float tmp = 0.0;

//    flip kernel
    flip(kernel, flipped_kernel, -1);

//    multiply and integrate
// input rows
    for(int i=0;i<src.rows;i++){
// input columns
        for(int j=0;j<src.cols;j++){
// kernel rows
            for(int k=0;k<flipped_kernel.rows;k++){
// kernel columns
                for(int l=0;l<flipped_kernel.cols;l++){
                    tmp += src.at<float>(i,j) * flipped_kernel.at<float>(k,l);
                }
            }
            dst.at<float>(i,j) = tmp;
        }
    }
       return dst.clone();
} 

最佳答案

为简化起见,我们假设您有 3x3 内核

k(0,0) k(0,1) k(0,2)
k(1,0) k(1,1) k(1,2)
k(2,0) k(2,1) k(2,2)

要计算卷积,您正在从左到右、从上到下扫描输入图像(标记为 I) 并为输入图像的每个像素分配一个根据以下公式计算的值:

newValue(y,x) = I(y-1,x-1) * k(0,0) + I(y-1,x) * k(0,1) + I(y-1,x+1) * k(0,2)
              + I(y,x-1) * k(1,0) + I(y,x) * k(1,1) + I(y,x+1) * k(1,2) + 
              + I(y+1,x-1) * k(2,0) + I(y+1,x) * k(2,1) + I(y+1,x+1) * k(2,2)


 ------------------x------------>
 |
 |
 |      [k(0,0) k(0,1) k(0,2)]
 y      [k(1,0) k(1,1) k(1,2)] 
 |      [k(2,0) k(2,1) k(2,2)]
 |

(y,x)输入图像的 ( I ) 是内核的 anchor ,为 I(y,x) 分配新值 你需要乘以每个 k I对应点的系数- 你的代码不这样做。

首先你需要创建dst矩阵与原始图像的维度和相同类型的像素。 然后您需要重写循环以反射(reflect)上述公式:

cv::Mat_<float> spatialConvolution(const cv::Mat_<float>& src, const cv::Mat_<float>& kernel)
{
    Mat dst(src.rows,src.cols,src.type());

    Mat_<float> flipped_kernel; 
    flip(kernel, flipped_kernel, -1);

    const int dx = kernel.cols / 2;
    const int dy = kernel.rows / 2;

    for (int i = 0; i<src.rows; i++) 
    {
        for (int j = 0; j<src.cols; j++) 
        {
            float tmp = 0.0f;
            for (int k = 0; k<flipped_kernel.rows; k++) 
            {
              for (int l = 0; l<flipped_kernel.cols; l++) 
              {
                int x = j - dx + l;
                int y = i - dy + k;
                if (x >= 0 && x < src.cols && y >= 0 && y < src.rows)
                    tmp += src.at<float>(y, x) * flipped_kernel.at<float>(k, l);
              }
            }
            dst.at<float>(i, j) = saturate_cast<float>(tmp);
        }
    }
    return dst.clone();
}

关于c++ - c++中的卷积实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58774408/

相关文章:

c++ - 如何克服C++头文件的命名空间之恶?

c++ - 在没有 WndProc 的情况下运行 win32 事件循环的不同方式的想法?

python - 使用 OpenCV 读取图像并使用 Tkinter 显示它

python - 使用傅里叶变换做卷积?

swift - 将对象(自身)传递给扩展

c++ - CRT终端(VC)

包含另一个类数组的 C++ 类

java - 如何使用 opencv 或 javacv 识别多边形?

python - 如何将 12 位 DICOM 图像转换为 8 位 jpeg?

c - 这个过滤器实现是否产生正确的输出?