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



我是opencv的新手。我正在尝试使用和opencv c++中的图像大小相同的内核对图像进行卷积。我收到一个错误"分割错误(核心转储)"。我检查了变量的初始化和循环。但我无法准确地找出问题的根源。有谁能帮我找出问题吗。我的代码如下:

#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;
}

创建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<>()的效率非常低。查看的有效方式

最新更新