You can use getDerivKernels
to determine the kernel coefficients for the Sobel filter if you really want to see what OpenCV uses. What you need to do is specify which direction you want and the size of the mask you want. As such, there are two directions per size of the kernel, so we need to call this four times.
However, what is returned are the horizontal, x
, and vertical, y
, 1D kernels that represent the Sobel filter which you can use to perform separable 2D filtering via sepFilter2D
. If you actually want to see the kernels themselves, you simply take the outer product between the x
and y
kernels that are returned from getDerivKernels
.
Here's something quick using Python's OpenCV interface to show the 5 x 5 x
, y
and 7 x 7 x
and y
kernels:
In [1]: import numpy as np
In [2]: import cv2
In [3]: sobel5x = cv2.getDerivKernels(1, 0, 5)
In [4]: np.outer(sobel5x[0], sobel5x[1])
Out[4]:
array([[ -1., -4., -6., -4., -1.],
[ -2., -8., -12., -8., -2.],
[ 0., 0., 0., 0., 0.],
[ 2., 8., 12., 8., 2.],
[ 1., 4., 6., 4., 1.]], dtype=float32)
In [5]: sobel5y = cv2.getDerivKernels(0, 1, 5)
In [6]: np.outer(sobel5y[0], sobel5y[1])
Out[6]:
array([[ -1., -2., 0., 2., 1.],
[ -4., -8., 0., 8., 4.],
[ -6., -12., 0., 12., 6.],
[ -4., -8., 0., 8., 4.],
[ -1., -2., 0., 2., 1.]], dtype=float32)
In [7]: sobel7x = cv2.getDerivKernels(1, 0, 7)
In [8]: np.outer(sobel7x[0], sobel7x[1])
Out[8]:
array([[ -1., -6., -15., -20., -15., -6., -1.],
[ -4., -24., -60., -80., -60., -24., -4.],
[ -5., -30., -75., -100., -75., -30., -5.],
[ 0., 0., 0., 0., 0., 0., 0.],
[ 5., 30., 75., 100., 75., 30., 5.],
[ 4., 24., 60., 80., 60., 24., 4.],
[ 1., 6., 15., 20., 15., 6., 1.]], dtype=float32)
In [9]: sobel7y = cv2.getDerivKernels(0, 1, 7)
In [10]: np.outer(sobel7y[0], sobel7y[1])
Out[10]:
array([[ -1., -4., -5., 0., 5., 4., 1.],
[ -6., -24., -30., 0., 30., 24., 6.],
[ -15., -60., -75., 0., 75., 60., 15.],
[ -20., -80., -100., 0., 100., 80., 20.],
[ -15., -60., -75., 0., 75., 60., 15.],
[ -6., -24., -30., 0., 30., 24., 6.],
[ -1., -4., -5., 0., 5., 4., 1.]], dtype=float32)
Note that the kernels are not normalized. If you want to use these for filtering, you should probably normalize the kernels. There's a flag in getDerivKernels
that will allow you to normalize the mask.
Also notice that one mask for a given size is the transpose of the other, which makes sense if you want to detect edges for a particular orientation.
For completeness, here's the C++ version of the above Python code. To compile the code, place this into a file... call it test.cpp
, then do this in the terminal:
g++ -Wall -g -o test test.cpp `pkg-config --cflags --libs opencv`
Once compiled, run the program using ./test
.
#include <cv.h>
using namespace std;
using namespace cv;
int main() {
// For the kernels
Mat sobelX, sobelY;
// 5 x 5 - x direction
getDerivKernels(sobelX, sobelY, 1, 0, 5, false, CV_32F);
cout << "sobel5x = " << endl << " " << sobelX*sobelY.t() << endl << endl;
// 5 x 5 - y direction
getDerivKernels(sobelX, sobelY, 0, 1, 5, false, CV_32F);
cout << "sobel5y = " << endl << " " << sobelX*sobelY.t() << endl << endl;
// 7 x 7 - x direction
getDerivKernels(sobelX, sobelY, 1, 0, 7, false, CV_32F);
cout << "sobel7x = " << endl << " " << sobelX*sobelY.t() << endl << endl;
// 7 x 7 - y direction
getDerivKernels(sobelX, sobelY, 0, 1, 7, false, CV_32F);
cout << "sobel7y = " << endl << " " << sobelX*sobelY.t() << endl << endl;
return 0;
}
Note that the x
and y
kernels are both column vectors, so you need transpose the y
vector so that it becomes a row vector to compute the outer product.