Каковы коэффициенты ядра для фильтра Sobel для OpenCV размером более 3 х 3?

Я использую фильтр Sobel OpenCV размером 5×5 и 7×7 для вычисления производной изображения.

Может кто-нибудь, пожалуйста, дайте мне знать значения ядра для фильтра Sobel размером 5×5 и 7×7 в OpenCV? Когда вы выполняете поиск Google, он показывает мне много разных ядер.

Вот несколько примеров для 5 x 5:

1. Отделимый

2 1 0 -1 -2 4 8 0 -4 -8 6 12 0 -12 -6 4 8 0 -4 -8 2 1 0 -1 -2 

2. Неразделимый

 2 1 0 -1 -2 4 10 0 -4 -10 7 17 0 -17 -7 4 10 0 -4 -10 2 1 0 -1 -2 

3. Странный несепарабельный

 2 1 0 -1 -2 3 2 0 -2 -3 4 3 0 -3 -4 3 2 0 -2 -3 2 1 0 -1 -2 

Вы можете использовать getDerivKernels для определения коэффициентов ядра для фильтра Sobel, если вы действительно хотите увидеть, что использует OpenCV. Что вам нужно сделать, это указать, какое направление вы хотите, и размер маски, которую вы хотите. Таким образом, есть два направления на размер ядра, поэтому нам нужно называть это четыре раза.

Однако возвращаются горизонтальные, x и вертикальные, y , 1D ядра, которые представляют фильтр Sobel, который вы можете использовать для выполнения разделяемой 2D-фильтрации через sepFilter2D . Если вы действительно хотите сами увидеть ядра, вы просто берете внешний продукт между ядрами x и y , которые возвращаются из getDerivKernels .

Вот что-то быстрое, используя интерфейс OpenCV от Python, чтобы показать 5 x 5 x , y и 7 x 7 x и y ядер:

 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) 

Обратите внимание, что ядра не нормированы . Если вы хотите использовать их для фильтрации, вы должны, вероятно, нормализовать ядра. В getDerivKernels есть флаг, который позволит вам нормализовать маску.

Также обратите внимание, что одна маска для заданного размера является транспонированием другого, что имеет смысл, если вы хотите обнаружить края для определенной ориентации.


Для полноты, вот версия C ++ вышеуказанного кода Python. Чтобы скомпилировать код, поместите его в файл … назовите его test.cpp , а затем сделайте это в терминале:

 g++ -Wall -g -o test test.cpp `pkg-config --cflags --libs opencv` 

После компиляции запустите программу, используя ./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; } 

Обратите внимание, что ядра x и y являются обоими столбцами, поэтому вам нужно транспонировать вектор y так, чтобы он стал вектором строки для вычисления внешнего продукта.

Вы также можете взглянуть на мой вывод для ядер Sobel произвольных размеров и углов здесь https://stackoverflow.com/a/41065243/2424669