我正在尝试在OpenCV中编写用于图像分割的代码。作为图像处理的一部分,我尝试使用Sobel滤波器检测测试图像的边缘。
为了在 dX 和 dY 方向上找到梯度的大小,我计算两个梯度的欧氏距离。但是当我运行代码时,我得到了上述错误。我知道上面的错误发生在我正在尝试的时候" ACCESS"内存中的不可用位置,但我确信我已在代码中定义了所有Mat
。
这是我的代码的一部分。
//Blur the raw image to remove noise
GaussianBlur(src, src, kernel, 2);
//Run sobel edge detector
Sobel(src, edgeX, src.depth(), 1, 0);
Sobel(src, edgeY, src.depth(), 0, 1);
edge = Mat::zeros(317,554,CV_8UC1);
for (int r = 0; r < edgeX.rows; r++)
{
for (int c = 0; c < edgeY.cols; c++)
{
edge.at<double>(r,c) = sqrt((edgeX.at<double>(r,c)*edgeX.at<double>(r,c)) + (edgeY.at<double>(r,c)*edgeY.at<double>(r,c)));
}
}
其中:
src
:RGB测试图片edgeX
:带 dX 渐变的sobel输出edgeY
:sobel输出 dY edge
:是具有欧氏距离的Mat
。 我在此行收到错误
edge.at<double>(r,c) = sqrt((edgeX.at<double>(r,c)*edgeX.at<double>(r,c)) + (edgeY.at<double>(r,c)*edgeY.at<double>(r,c)));
尝试访问edge.at<double>(316,395)
我该如何调试? 我做错了什么?
答案 0 :(得分:1)
edge
是CV_8UC1
类型的矩阵,表示uchar
的矩阵,而不是double
的矩阵。
您需要使用at<uchar>
edge.at<uchar>(r,c) = sqrt((edgeX.at<uchar>(r,c)*edgeX.at<uchar>(r,c)) + (edgeY.at<uchar>(r,c)*edgeY.at<uchar>(r,c)));
您可以使用Mat_<Tp>
来避免此类问题,这样可以在不使用.at
功能的情况下更轻松地进行访问:
Mat1b edge(317,554,uchar(0));
for (int r = 0; r < edgeX.rows; r++) {
for (int c = 0; c < edgeY.cols; c++) {
edge(r,c) = sqrt((edgeX(r,c)*edgeX(r,c)) + (edgeY(r,c)*edgeY(r,c)));
}
}
在这种情况下,您还可以使用cv::magnitude
执行与for
循环相同的操作(但它需要float
的矩阵):
Sobel(src, edgeX, CV_32F, 1, 0);
Sobel(src, edgeY, CV_32F, 0, 1);
Mat edge;
magnitude(edgeX, edgeY, edge);
// Convert to CV_8UC1
edge.convertTo(edge, CV_8UC1);