我正在尝试使用Sobel掩模在彩色图像中寻找边缘,我实现了Sobel函数,但Opencv Sobel和我的输出是不同的。
void Sobel(const Mat &image, Mat &new_image) {
int gx[3][3] = { -1,0,1,
-2,0,2,
-1,0,1 };
int gy[3][3] = { 1,2,1,
0,0,0,
-1,-2,-1 };
for (int i = 1; i < image.rows - 1; i++)
for (int j = 1; j < image.cols - 1; j++) {
int XR = 0, XG = 0, XB = 0, YR = 0, YG = 0, YB = 0;
for (int r = -1; r < 2; ++r) {
for (int c = -1; c < 2; ++c) {
XR += gx[r + 1][c + 1] * image.at<Vec3b>(i + r, j + c)[0];
YR += gy[r + 1][c + 1] * image.at<Vec3b>(i + r, j + c)[0];
XG += gx[r + 1][c + 1] * image.at<Vec3b>(i + r, j + c)[1];
YG += gy[r + 1][c + 1] * image.at<Vec3b>(i + r, j + c)[1];
XB += gx[r + 1][c + 1] * image.at<Vec3b>(i + r, j + c)[2];
YB += gy[r + 1][c + 1] * image.at<Vec3b>(i + r, j + c)[2];
}
}
int sumR = std::abs(XR) + std::abs(YR);
int sumG = std::abs(XG) + std::abs(YG);
int sumB = std::abs(XB) + std::abs(YB);
new_image.at<Vec3b>(i, j)[0] = (sumR < 255 ? sumR>0 ? sumR : 0 : 255);
new_image.at<Vec3b>(i, j)[1] = (sumG < 255 ? sumG>0 ? sumG : 0 : 255);
new_image.at<Vec3b>(i, j)[2] = (sumB < 255 ? sumB>0 ? sumB : 0 : 255);
}
}
int main()
{
Mat image = imread("valve.png");
Mat new_image = image.clone();
//Sobel(image, new_image);
cv::Sobel(image, new_image, -1, 1, 1);
namedWindow("Original", WINDOW_NORMAL);
imshow("Original", image);
namedWindow("Sobel", WINDOW_NORMAL);
imshow("Sobel", new_image);
waitKey();
return 0;
}



发布于 2019-07-26 21:33:58
cv::Sobel使用getDerivKernels在内部创建滤波器系数,它为两个方向的导数创建一维滤波器掩码。一阶导数的形式为- 1,0,1。随后,它们通过outer product相乘,形成一个矩阵:
`1 0 -1
0 0 0
-1 0 1如果你将这个矩阵应用于你的Sobel函数并在你的梯度计算中去掉abs函数,你将得到与OpenCV相同的结果。
void Sobel2(const Mat &image, Mat &new_image) {
double gy[3][3] = { 1,0,-1,
0,0,0,
-1,0,1 };
for (int i = 1; i < image.rows - 1; i++)
for (int j = 1; j < image.cols - 1; j++) {
double XR = 0, XG = 0, XB = 0, YR = 0, YG = 0, YB = 0;
for (int r = -1; r < 2; ++r) {
for (int c = -1; c < 2; ++c) {
YR += gy[r + 1][c + 1] * image.at<Vec3b>(i + r, j + c)[0];
YG += gy[r + 1][c + 1] * image.at<Vec3b>(i + r, j + c)[1];
YB += gy[r + 1][c + 1] * image.at<Vec3b>(i + r, j + c)[2];
}
}
new_image.at<Vec3b>(i, j)[0] = (YR < 255 ? YR>0 ? YR : 0 : 255);
new_image.at<Vec3b>(i, j)[1] = (YG < 255 ? YG>0 ? YG : 0 : 255);
new_image.at<Vec3b>(i, j)[2] = (YB < 255 ? YB>0 ? YB : 0 : 255);
}
}下面的代码可以帮助您理解过滤器矩阵是如何计算的:
cv::Mat kx, ky;
cv::getDerivKernels(kx, ky, 1, 1, 3);
cv::Mat k = kx * ky.t(); // k is the filter matrix that is used internally in cv::Sobel functionhttps://stackoverflow.com/questions/57219461
复制相似问题