我是 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);
您正在使用浮点指针。由于 float 是 4 个字节,而不是 3 个字节,因此您最终会访问图像之外的内存,甚至是您的程序。后者正在发生,如分段违规所示。
最好的办法可能是在 Debug模式下编译您的代码。那么您可能会从 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<>()
效率很低。参见 the efficient way
关于c++ - 在 opencv c++ 中查找图像卷积时出现段错误(核心转储)错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20093529/