在opencv c ++中查找图像卷积时出现分段错误(核心转储)错误

Posted

技术标签:

【中文标题】在opencv c ++中查找图像卷积时出现分段错误(核心转储)错误【英文标题】:Segmentation fault (core dumped) error while finding convolution of images in opencv c++ 【发布时间】:2013-11-20 10:36:29 【问题描述】:

我是opencv的新手。我正在尝试使用与 opencv c++ 中的图像大小相同的内核对图像进行卷积。我收到错误“分段错误(核心转储)”。我检查了变量和for循环的初始化。但我无法准确找出问题出在哪里。任何人都可以帮我找出问题所在。我的代码如下:

#include<opencv2/highgui/highgui.hpp>
#include "opencv2/imgproc/imgproc.hpp"
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<cv.hpp>

using namespace cv;
using namespace std;

Mat img;
Mat kernel, gd, dest;
int c = 120;
double mysum = 0.0, mysum1 = 0.0, k = 0;
int cent=0,radius=0;
enum ConvolutionType    
    /* Return the full convolution, including border */
    CONVOLUTION_FULL, 

    /* Return only the part that corresponds to the original image */
    CONVOLUTION_SAME,

    /* Return only the submatrix containing elements that were not influenced by the       
    border       
    */
    CONVOLUTION_VALID
;

void conv2(const Mat &img, const Mat& kernel, ConvolutionType type,Mat& dest)


    Mat source = img;
    if(CONVOLUTION_FULL == type) 
    
        source = Mat();
        const int additionalRows = kernel.rows - 1, additionalCols = kernel.cols - 1;
        copyMakeBorder(img, source, (additionalRows + 1) / 2, additionalRows / 2, 
            (additionalCols + 1) / 2, additionalCols / 2, BORDER_CONSTANT, Scalar(0));
    

    flip(kernel, kernel, -1);
    Point anchor(kernel.cols - kernel.cols / 2 - 1, kernel.rows - kernel.rows / 2 - 1);
    int borderMode = BORDER_CONSTANT;
    filter2D(source, dest, img.depth(), kernel, anchor, 0, borderMode);

    if(CONVOLUTION_VALID == type)
    
        dest = dest.colRange((kernel.cols - 1) / 2, dest.cols - kernel.cols / 2).rowRange((kernel.rows - 1) / 2, dest.rows - kernel.rows / 2);
    
 

int main()
  
    img = imread("building1.jpg", CV_LOAD_IMAGE_COLOR);
    dest.create(img.size(), img.type());
    gd.create(img.size(), img.type());

    for(int j = 0; j < img.rows; j++)
    
        for(int i = 0; i < img.cols; i++)
        
            radius = ((cent - i)^2 + (cent - j)^2);
            gd.at<float>(j, i) = exp((-(radius) / c^2));

            mysum = mysum + gd.at<float>(j, i);
        
        mysum1 = mysum1 + mysum; 
    

    k=1/mysum1;
    cout<<endl<<k<<"\n"<<endl;

    for(int j = 0; j < img.rows; j++)
    
        for(int i = 0; i < img.cols; i++)
        
            gd.at<float>(j, i) = k * gd.at<float>(j, i);
        
      

    conv2(img, gd, CONVOLUTION_FULL, dest);
    imshow("conv", dest);
    waitKey(0);
    return 0;

【问题讨论】:

格式糟糕的代码 ;( 顺便说一句,a^b 是 xor b ,而不是 pow(a,b) 你检查过这个错误是在什么时候出现的吗?找出这个问题的一个简单方法是注释掉代码的主要部分,看看错误是否仍然存在。 谢谢先生的回复和建议。我整理了一下问题出在哪里。就在这一行:gd.at(j, i) = exp((-(radius ) / c^2));我认为 gd.at(j, i) 超出了界限。你能给我一些修复它的建议吗? 我用 C*C 更正了 C^2 。但同样的问题又出现了。 【参考方案1】:

当你创建img

img = imread("building1.jpg", CV_LOAD_IMAGE_COLOR);

它将是 CV_UC3 类型,即每个像素 3 个字节(蓝色、绿色和红色各一个)。

但是当你访问图片时

gd.at<float>(j, i) = k * gd.at<float>(j, i);

您正在使用浮点指针。由于浮点数是 4 个字节,而不是 3 个字节,因此您最终将访问图像之外的内存,甚至是您的程序。后者正在发生,如分段违规所示。

也许最好的办法是在调试模式下编译您的代码。那么你可能会从 OpenCV 中得到一个异常,而不是分段违规。

看起来你可能想要的是

img = imread("building1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
img.convertTo(img, CV_32FC1); 
...

你们中的一些代码也可以大大简化,例如

for(int j = 0; j < img.rows; j++)

    for(int i = 0; i < img.cols; i++)
    
        gd.at<float>(j, i) = k * gd.at<float>(j, i);
    
  

应该是

gd = gd * k;

如果您按顺序访问像素,则使用at&lt;&gt;() 效率非常低。见the efficient way

【讨论】:

感谢您的回复先生。我试过了,再次显示相同的错误。 @user2943871 不要说谢谢 - 接受并支持答案! (假设你下次需要帮助:)

以上是关于在opencv c ++中查找图像卷积时出现分段错误(核心转储)错误的主要内容,如果未能解决你的问题,请参考以下文章

C++ 分段错误 OpenCV

为啥在访问二级指针时出现分段错误错误? C语言

在 C 中使用 struct 时出现分段错误

在 C 中使用 fgets 时出现“分段错误:11”

在调用函数中取消引用指针时出现分段错误

尝试在 C 中使用 realloc 扩展数组时出现分段错误错误 [关闭]