将总和分配给矩阵时大小为 4 的无效写入

invalid write of size 4 when assigning sum to a matrix

您好,我正在尝试实现 2d ryconvolution,我相信我所有的计算和 for 循环都是正确的。但是,当我尝试将 sum 分配给 copy_output.at(y,x) 时,出现大小错误写入 使用 valgrind 调试时出现 4 错误。 我已经检查了所有可能导致这种情况的因素。我也初始化了 copy_output.

Valgrind 错误:

 Process terminating with default action of signal 11 (SIGSEGV)
==30604==  Access not within mapped region at address 0x10
==30604==    at 0x413594: algorithms::manual_filter_2d(cv::Mat const&, cv::Mat&, cv::Mat const&) (algorithms.cpp:137)

代码:

void algorithms::manual_filter_2d(const Mat &input, Mat &output, const Mat &kernel) {

    int top;
    int bottom;
    top =  round(kernel.cols/2);
    bottom = top;
    int left;
    int right;
    left =  round(kernel.rows/2);
    right = left;

    Mat copy_output;
    Mat copy_input(input.rows,input.cols,input.type());
   cv::copyMakeBorder(input, copy_input, top, bottom,left,right, cv::BORDER_REPLICATE);

    for(int y=round(kernel.rows/2); y<copy_input.rows-round(kernel.rows/2); y++)
    {

        for(int x=round(kernel.cols/2); x<copy_input.cols-round(kernel.cols/2); x++)
        {
            float sum = 0.0f;
            for(int ky=0;ky<kernel.rows;ky++)
            {

                for(int kx=0;kx<kernel.cols;kx++)
                {

                  sum +=    input.at<float>(y+ky-((kernel.rows-1)/2) , x+kx-((kernel.cols-1)/2))*kernel.at<float>(ky,kx);


                }

            }
            copy_output.at<float>(y,x) = sum;  //line 137 that causes the segfault
        }

    }
    copy_output.copyTo(output);
    // TODO put your code here

}

你有“垫子 copy_output;”它正在使用可能具有 0 行和 0 列的默认构造函数构造 Mat。当您致电 copy_output.at(y,x) = sum 时。它正在尝试放入不存在的内存。

Mat copy_output(input.rows,input.cols,input.type()); 

或与上面类似的内容。

该代码是为奇数内核设计的,如果不对偶数内核进行大的修改将无法运行。这可能是您越界读取的原因。我建议您根据需要添加一行 and/or 列零来使内核大小为奇数。

发生越界写入是因为 copy_outputcopy_input 的大小不同。假设您按照其他答案中的指示对其进行了初始化 (Mat copy_output(input.rows,input.cols,input.type()),然后

copy_output.at<float>(y,x) = sum;

写越界,因为 xy 变得比 input.rowsinput.cols 大。要么将 copy_output 初始化为填充输入图像的大小(cv::copyMakeBorder 的结果),要么写入:

copy_output.at<float>(y-kernel.rows/2,x-kernel.cols/2) = sum;

请注意,您的代码中的 round 是多余的,kernel.rows/2 是一个整数除法,产生一个整数。 round 对整数不执行任何操作。