一、图像的形态学操作(Morphological Image Processing)
形态学一般指生物学中研究动物和植物结构的一个分支。用数学形态学(也称图像代数)表示以形态为基础对图像进行分析的数学工具。基本思想是用具有一定形态的结构元素去度量和提取图像中的对应形状以达到对图像分析和识别的目的。形态学图像处理的数学基础和所用语言是集合论。形态学图像处理的应用可以简化图像数据,保持它们基本的形状特性,并除去不相干的结构。
形态学图像处理的基本运算有:膨胀、腐蚀、开操作和闭操作,击中与击不中变换,TOP-HAT变换,黑帽变换等
形态学的应用:消除噪声、边界提取、区域填充、连通分量提取、凸壳、细化、粗化等;分割出独立的图像元素,或者图像中相邻的元素;求取图像中明显的极大值区域和极小值区域;求取图像梯度
在讲各种形态学操作之前,先来看看结构元素:
膨胀和腐蚀操作的核心内容是结构元素。(后面的开闭运算等重要的也是结构元素的设计,一个合适的结构元素的设计可以带来很好的处理效果)一般来说结构元素是由元素为1或者0的矩阵组成。结构元素为1的区域定义了图像的领域,领域内的像素在进行膨胀和腐蚀等形态学操作时要进行考虑。
一般来说,二维或者平面结构的结构元素要比处理的图像小得多。结构元素的中心像素,即结构元素的原点,与输入图像中感兴趣的像素值(即要处理的像素值)相对应。三维的结构元素使用0和1来定义x-y平面中结构元素的范围,使用高度值定义第三维。
OpenCV里面的API介绍:
Mat kernel = getStructuringElement(int shape,Size ksize,Point anchor);
//结构元素的定义:形状 (MORPH_RECT \MORPH_CROSS(交叉形) \MORPH_ELLIPSE);结构元素大小;锚点 默认是Point(-1, -1)意思就是中心像素,也可以自己指定
结构元素的选取,依据具体项目问题对象而定,远不止这几种大可自己设计。
1.1 膨胀(Dilate)
膨胀是腐蚀运算的对偶运算,其作用是在结构元素的约束下将与目标区域相接触的背景合并到该目标物中,使目标边界向外部扩张,物体的面积增大了相应数量的点。
集合论思想:
原理步骤:
OpenCV里面的API介绍:
void dilate( const Mat& src, Mat& dst, const Mat& element,Point anchor=Point(-1,-1), int iterations=1,int borderType=BORDER_CONSTANT,const Scalar& borderValue=morphologyDefaultBorderValue() );
参数解释:
1.2 腐蚀(Erode)
腐蚀是一种在结构元素约束下消除目标图形的部分边界点,使其边界向内部收缩的的算法,具有收缩目标区域的作用。
集合论思想:
原理步骤:
void erode( const Mat& src, Mat& dst, const Mat& element,Point anchor=Point(-1,-1), int iterations=1,int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue() );
参数和膨胀一模一样;
1.3 开运算(Open)
作用:用来消除图像中细小对象,在纤细点处分离物体和平滑较大物体的边界而有不明显改变其面积和形状。
集合论思想:
开运算的几何解释:
Opencv里面的API介绍:——见最后总结
1.4 闭运算(Close)
作用:用来填充目标内部的细小孔洞(fill hole),将断开的邻近目标连接,在不明显改变物体面积和形状的情况下平滑其边界。
集合论思想:
闭运算的几何解释:
Opencv里面的API介绍:——见最后总结
1.5 形态学梯度、顶帽、黑帽
(1)形态学梯度(Morphological gradient)
形态学梯度操作能描述图像亮度变化的剧烈程度;当我们想要突出高亮区域的外围时,则可以选用形态学梯度来突出边缘,可以保留物体的边缘轮廓。。
常见的几种梯度:
基本梯度,膨胀减去腐蚀:
Opencv里面的API介绍:——见最后总结
(2)礼/顶帽(Top hat)
顶帽是原图与原图的开运算的差值图像。开运算放大了裂缝或者局部低亮度的区域,所以,从原图中减去开运算后的图,得到的结果突出了比原图轮廓周围的区域更明亮的区域,这个操作与选择的核的大小有关。TopHat运算一般用来分离比邻近点亮一些的斑块,可以使用这个运算提取背景。
Opencv里面的API介绍:——见最后总结
(3) 黑帽(Black hat)
黑帽是闭运算结果与原图的差值图像。黑帽运算的结果突出了比原图轮廓周围区域更暗的区域,所以黑帽运算用来分离比邻近点暗一些的斑块。
Opencv里面的API介绍:——见最后总结
1.6 总结:
//形态学操作(开、闭、形态学梯度、顶帽、黑帽)
morphologyEx(src, dst, MORPH_BLACKHAT, kernel);
//第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像位深应该为以下五种之一:CV_8U, CV_16U,CV_16S, CV_32F 或CV_64F。
//第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
//第三个参数,int类型的op,表示形态学运算的类型,可以是如下之一的标识符:
//MORPH_OPEN – 开运算(Opening operation):先腐蚀后膨胀,去掉小对象
//MORPH_CLOSE – 闭运算(Closing operation):先膨胀后腐蚀,可以填充一些小的空洞(fill hole)
//MORPH_GRADIENT - 形态学梯度(Morphological gradient):膨胀后的图减去腐蚀后的图(设置恰当的参数可以得到目标的大致边缘)
//MORPH_TOPHAT - “顶帽”(“Top hat”):原图像与开操作之间的差值图像(可以用来观察开运算除去了哪些小目标)
//MORPH_BLACKHAT - “黑帽”(“Black hat“):闭操作图像与源图像的差值图像(可以观察闭运算的效果)
//第四个参数:结构元素即形态学运算的内核
//第五个参数,Point类型的anchor,锚的位置,其有默认值( - 1, - 1),表示锚位于中心。
//第六个参数,int类型的iterations,迭代使用函数的次数,默认值为1。
//第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_ CONSTANT。
//第八个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档
示例程序:
//形态学的操作的学习
#include "stdafx.h"
#include
#include
using namespace cv;
char output[] = "Morphlogy_image";
Mat dst, src;
void Morphlogy_Operators(int, void*);
int element_size = 3;
int max_size = 21;
int main(int argc, char**argv)
{
Mat src = imread("C:/Users/59235/Desktop/工作/异常1/temp1.bmp");
if (!src.data)
{
printf("could not load image...\n");
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
namedWindow(output, CV_WINDOW_AUTOSIZE);
//轨迹条或滑动条(Trackbar)的控件工具
createTrackbar("elementSIZE:", output, &element_size, max_size, Morphlogy_Operators);
//参数一、trackbarname:滑动空间的名称;参数二、winname:滑动空间用于依附的图像窗口的名称;数三、value:初始化阈值;参数四、count:滑动控件的刻度范围;参数五、TrackbarCallback是回调函数
Morphlogy_Operators(0, 0);
waitKey(0);
return 0;
}
//各种形态学操作
void Morphlogy_Operators(int, void*)
{
int s = element_size + 1;
Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));
//结构元素的定义:形状 (MORPH_RECT \MORPH_CROSS(交叉形) \MORPH_ELLIPSE);结构元素大小;锚点 默认是Point(-1, -1)意思就是中心像素
//膨胀
//dilate(src,dst,kernel);
//腐蚀
//erode(src, dst, kernel);
//形态学操作(开、闭、形态学梯度、顶帽、黑帽)
morphologyEx(src, dst, MORPH_BLACKHAT, kernel);
//第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像位深应该为以下五种之一:CV_8U, CV_16U,CV_16S, CV_32F 或CV_64F。
//第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
//第三个参数,int类型的op,表示形态学运算的类型,可以是如下之一的标识符:
//MORPH_OPEN – 开运算(Opening operation):先腐蚀后膨胀,去掉小对象
//MORPH_CLOSE – 闭运算(Closing operation):先膨胀后腐蚀,可以填充一些小的空洞(fill hole)
//MORPH_GRADIENT - 形态学梯度(Morphological gradient):膨胀后的图减去腐蚀后的图(设置恰当的参数可以得到目标的大致边缘)
//MORPH_TOPHAT - “顶帽”(“Top hat”):原图像与开操作之间的差值图像(可以用来观察开运算除去了哪些小目标)
//MORPH_BLACKHAT - “黑帽”(“Black hat“):闭操作图像与源图像的差值图像(可以观察闭运算的效果)
//第四个参数:结构元素即形态学运算的内核
//第五个参数,Point类型的anchor,锚的位置,其有默认值( - 1, - 1),表示锚位于中心。
//第六个参数,int类型的iterations,迭代使用函数的次数,默认值为1。
//第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_ CONSTANT。
//第八个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档
imshow(output, dst);
return;
}
总之,形态学操作的灵活运用,可以起到消除噪声,分割出独立的图像元素以及在图像中连接起相邻的区域。