opencv-069-图像形态学(图像梯度)

知识点

图像形态学的梯度跟我们前面介绍的图像卷积计算出来的梯度有本质不同,形态学梯度可以帮助我们获得连通组件的边缘与轮廓,实现图像轮廓或者边缘提取。根据使用的形态学操作不同,形态学梯度又分为

  • 基本梯度:图像膨胀与腐蚀操作之间的差值
  • 内梯度:输入图像与腐蚀之间的差值
  • 外梯度:膨胀与输入图像之间的差值

API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void cv::morphologyEx(
InputArray src,
OutputArray dst,
int op,
InputArray kernel,
Point anchor = Point(-1,-1),
int iterations = 1,
int borderType = BORDER_CONSTANT,
)
src 输入图像
dst 输出图像
op 形态学操作
kernel 结构元素
anchor 中心位置锚定
iterations 循环次数
borderType 边缘填充类型
其中op指定为MORPH_GRADIEN即表示使用基本梯度操作

代码(c++,python)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

/*
* 图像形态学(图像梯度)
*/
int main() {
Mat src = imread("../images/master.jpg", IMREAD_GRAYSCALE);
if (src.empty()) {
cout << "could not load image.." << endl;
}
imshow("input", src);

//定义结构元素
Mat se = getStructuringElement(MORPH_RECT, Size(3, 3));

Mat basic, exter, inter;
// 基本梯度
morphologyEx(src, basic, MORPH_GRADIENT, se);
imshow("basic_gradient", basic);

// 外梯度
morphologyEx(src, exter, MORPH_DILATE, se);
subtract(exter, src, exter);
imshow("exter_gradient", exter);

// 内梯度
morphologyEx(src, inter, MORPH_ERODE, se);
subtract(src, inter, inter);
imshow("inter_gradient", inter);

waitKey(0);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import cv2 as cv

src = cv.imread("D:/images/dannis2.jpg")
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)

# 形态学梯度 - 基本梯度
se = cv.getStructuringElement(cv.MORPH_RECT, (3, 3), (-1, -1))
basic = cv.morphologyEx(src, cv.MORPH_GRADIENT, se)
cv.imshow("basic gradient", basic)

# 外梯度
dilate = cv.morphologyEx(src, cv.MORPH_DILATE, se)
exteral = cv.subtract(dilate, src)
cv.imshow("external gradient", exteral)

# 内梯度
erode = cv.morphologyEx(src, cv.MORPH_ERODE, se)
interal = cv.subtract(src, erode)
cv.imshow("interal gradient", interal)

cv.imwrite("D:/gradient.png", basic)
cv.imwrite("D:/external.png", exteral)
cv.imwrite("D:/interal.png", interal)
cv.waitKey(0)
cv.destroyAllWindows()

结果

代码地址

github