一.形态学操作(morphology operators)
#图像形态学操作 – 基于形状的一系列图像处理操作的合集,主要是基于集合论基础上的形态学数学
#形态学有四个基本操作:腐蚀、膨胀、开、闭
#膨胀与腐蚀是图像处理中最常用的形态学操作手段
1.膨胀
#跟卷积操作类似,假设有图像A和结构元素B,结构元素B在A上面移动,其中B定义其中心为锚点,计算B覆盖下A的最大像素值用来替换锚点的像素,其中B作为结构体可以是任意形状。
2.腐蚀
#腐蚀跟膨胀操作的过程类似,唯一不同的是以最小值替换锚点重叠下图像的像素值。
3.相关API
#getStructuringElement(int shape, Size ksize, Point anchor)
– 形状 (MORPH_RECT \MORPH_CROSS \MORPH_ELLIPSE)
– 大小
– 锚点 默认是Point(-1, -1)意思就是中心像素
#dilate(src, dst, kernel)
#erode(src, dst, kernel)
4.动态调整结构元素大小(方便测试使用)
#TrackBar – createTrackbar(const String & trackbarname, const String winName, int* value, int count, Trackbarcallback func, void* userdata=0)
其中最中要的是 callback 函数功能。如果设置为NULL就是说只有值update,但是不会调用callback的函数。
5.腐蚀和膨胀代码
/*
OpenCV 形态学操作学习
Michael Jiang<sencom1997@outlook.com>
2019年7月25日09:14:49
*/
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
int main()
{
//读取图像
Mat src = imread("D:/test10.png", IMREAD_COLOR);
//判断读取是否成功
if (src.empty()) {
printf("pic load failed!\n");
return -1;
}
//先腐蚀后膨胀
Mat dst;
Mat temp;
Mat kernel = getStructuringElement(MORPH_RECT, Size(9, 9));
erode(src, temp, kernel);
dilate(temp, dst, kernel);
//显示窗口
imshow("src", src);
imshow("dst", dst);
waitKey(0);
return 0;
}
二.具体形态学操作
#开操作- open
#闭操作- close
#形态学梯度- Morphological Gradient
#顶帽 – top hat
#黑帽 – black hat
1.开操作
就是先腐蚀后膨胀(如上面的演示)
可以去掉小的对象,假设对象是前景色,背景是黑色
2.闭操作
先膨胀后腐蚀
可以填充小的洞(fill hole),假设对象是前景色,背景是黑色
3.形态学梯度
膨胀减去腐蚀
又称为基本梯度(其它还包括-内部梯度、方向梯度)
4.顶帽
顶帽 是原图像与开操作之间的差值图像
5.黑帽
黑帽是闭操作图像与源图像的差值图像
#############################
相关API
morphologyEx(src, dest, CV_MOP_BLACKHAT, kernel);
– Mat src – 输入图像
– Mat dest – 输出结果
– int OPT – CV_MOP_OPEN/ CV_MOP_CLOSE/ CV_MOP_GRADIENT / CV_MOP_TOPHAT/ CV_MOP_BLACKHAT 形态学操作类型
-Mat kernel 结构元素
-int Iteration 迭代次数,默认是1
############################
代码演示
1.开操作,上面的先腐蚀后膨胀就可以改写为
//先腐蚀后膨胀
Mat dst;
Mat temp;
Mat kernel = getStructuringElement(MORPH_RECT, Size(9, 9));
//erode(src, temp, kernel);
//dilate(temp, dst, kernel);
morphologyEx(src, dst, MORPH_OPEN, kernel);
2.闭操作
//先腐蚀后膨胀
Mat dst;
Mat temp;
Mat kernel = getStructuringElement(MORPH_RECT, Size(9, 9));
//erode(src, temp, kernel);
//dilate(temp, dst, kernel);
morphologyEx(src, dst, MORPH_CLOSE, kernel);
… …以此类推
三.提取水平和垂直直线
1.提取步骤
1.输入图像彩色图像 imread
2.转换为灰度图像 – cvtColor
3.转换为二值图像 – adaptiveThreshold
4.定义结构元素
5.开操作 (腐蚀+膨胀)提取 水平与垂直线
转换为二值图像
adaptiveThreshold(
Mat src, // 输入的灰度图像
Mat dest, // 二值图像
double maxValue, // 二值图像最大值
int adaptiveMethod // 自适应方法,只能其中之一
// ADAPTIVE_THRESH_MEAN_C , ADAPTIVE_THRESH_GAUSSIAN_C
int thresholdType,// 阈值类型
int blockSize, // 块大小
double C // 常量C 可以是正数,0,负数
)
2.代码实现
/*
OpenCV 形态学操作-提取水平和垂直直线学习
Michael Jiang<sencom1997@outlook.com>
2019年7月25日09:55:00
*/
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
int main()
{
//读取图像
Mat src = imread("D:/test10.png", IMREAD_COLOR);
//判断读取是否成功
if (src.empty()) {
printf("pic load failed!\n");
return -1;
}
Mat dst;
Mat temp;
//BGR转灰度
cvtColor(src, temp, COLOR_BGR2GRAY);
//转换为二值图像
adaptiveThreshold(~temp, dst, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 23, -2);
//定义结构元素
int xsize = dst.cols / 30;
int ysize = dst.rows / 30;
Mat xKernel = getStructuringElement(MORPH_RECT, Size(xsize, 1));
Mat yKernel = getStructuringElement(MORPH_RECT, Size(1, ysize));
//开操作
Mat xfin;
Mat yfin;
morphologyEx(dst, xfin, MORPH_OPEN, xKernel);
morphologyEx(dst, yfin, MORPH_OPEN, yKernel);
//显示窗口
imshow("src", src);
imshow("dst", dst);
imshow("xfin", xfin);
imshow("yfin", yfin);
waitKey(0);
return 0;
}
四.去除图片中的干扰项
代码实现
/*
OpenCV 形态学操作-去除干扰项学习
Michael Jiang<sencom1997@outlook.com>
2019年7月25日10:37:23
*/
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
int main()
{
//读取图像
Mat src = imread("D:/test10.png", IMREAD_COLOR);
//判断读取是否成功
if (src.empty()) {
printf("pic load failed!\n");
return -1;
}
Mat dst;
Mat temp;
//BGR转灰度
cvtColor(src, temp, COLOR_BGR2GRAY);
//转换为二值图像
adaptiveThreshold(~temp, dst, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
//定义矩形结构元素
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
//进行开操作
Mat fin;
morphologyEx(dst, fin, MORPH_OPEN, kernel);
//显示窗口
imshow("src", src);
imshow("dst", dst);
imshow("fin", fin);
waitKey(0);
return 0;
}