文章目录
一、获得核getStructuringElement()
原型
Mat getStructuringElement(
int shape,
Size ksize,
Point anchor = Point(-1,-1)
)
参数
-
shape:形状
- MORPH_RECT :矩形
- MORPH_CROSS :交叉形
- MORPH_ELLIPSE :椭圆形
-
ksize:结构元素的大小。其两个元素都不能小于1。
-
anchor:锚的位置。默认(-1,-1),表示锚位于中心。
如:
Mat kernel=getStrucutringElement(MORPH_RECT,Size(15,15));
二、膨胀dilate()和腐蚀erode()
1.膨胀dilate()
原型
void dilate(
InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor=Point(-1,-1),
int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar &borderValue=morphologyDefaultBorderValue()
);
参数
- src:输入图像
- dst:输出图像
- kernel:膨胀操作的核,也是Mat类。用getStructuringElement()获得的Mat对象
- anchor:锚的位置。默认(-1,-1),表示锚位于中心
- iterations:迭代使用erode()的次数。默认1次
- borderType:用于推断图像外部像素的某种边界模式。
- borderValue:不管
例子
#include<opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat srcImage=imread("3.jpg");
imshow("srcImage",srcImage);
Mat kernel=getStructuringElement(MORPH_RECT,Size(15,15));
Mat dstImage;
dilate(srcImage,dstImage,kernel);
imshow("Effect",dstImage);
waitKey();
return 0;
}
2.腐蚀erode()
原型
void erode(
InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor=Point(-1,-1),
int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar &borderValue=morphologyDefaultBorderValue()
);
参数
- src:输入图像
- dst:输出图像
- kernel:膨胀操作的核,也是Mat类。用getStructuringElement()获得的Mat对象
- anchor:锚的位置。默认(-1,-1),表示锚位于中心
- iterations:迭代使用erode()的次数。默认1次
- borderType:用于推断图像外部像素的某种边界模式。
- borderValue:不管
例子
#include<opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat srcImage=imread("3.jpg");
imshow("srcImage",srcImage);
Mat kernel=getStructuringElement(MORPH_RECT,Size(15,15));
Mat dstImage;
erode(srcImage,dstImage,kernel);
imshow("Effect",dstImage);
waitKey();
return 0;
}
三、复杂形态学运算
1.形态学梯度Gradient
形态学梯度=膨胀-腐蚀
dst=morph=grad(src,element)=dilate(src,element)-erode(src,element)
2.开运算和闭运算
关系
- 开运算=先腐蚀后膨胀
dst=open(src,element)=dilate(erode(src,element)) - 闭运算=先膨胀后腐蚀
dst=clese(src,element)=erode(dilate(src,element))
3.顶帽和黑帽
关系
- 顶帽=原图-开运算
dst=tophat(src,element)=src-open(src,element) - 黑帽=闭运算-原图
dst=blackhat(src,element)=close(src,element)-src
四、集成函数morphologyEx()
原型
void morphologyEx(
InputArray src,
OutputArray dst,
int op,
InputArray kernel,
Point anchor=Point(-1,-1),
int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar &borderValue=morphologyDefaultBorderValue()
);
参数
-
src:输入图像
-
dst:输出图像
-
op:表示形态学运算类型
- MORPH_DILATE:膨胀
- MORPH_ ERODE:腐蚀
- MORPH_OPEN:开运算
- MORPH_CLOSE:闭运算
- MORPH_GRADIENT:形态学梯度
- MORPH_TOPHAT:顶帽
- MORPH_BLACKHAT:黑帽
-
kernel:膨胀操作的核,也是用getStructuringElement()获得的Mat对象。其两个元素都不能小于1。
-
anchor:锚的位置。默认(-1,-1),表示锚位于中心
-
iterations:迭代使用erode()的次数。默认1次
-
borderType:用于推断图像外部像素的某种边界模式。
-
borderValue:不管
例子:开运算
Mat kernel=getStructuringElement(MORPH_RECT,Size(15,15));
morphologyEx(srcImage,dstImage,MORPH_OPEN,kernel);
五、滑动条调试核的Size
1.效果总结
DILATE:各光点扩散
ERODE:各暗点扩散
OPEN:光点流失(open),更暗【消除细小物体,在纤细点处分离物体,平滑较大物体的边界】
CLOSE:光电保存(close),更亮【排除小型黑洞】
GRADIENT:Size()=1时得到线稿
TOPHAT:保留颜色,Size()=最大就是原图
BLACKHAT:不保留颜色,像是X光,Size()最大=X光图
2.代码
滑动条的数值大小value就是kernel的Size(value,value)
#include<opencv2/opencv.hpp>
using namespace cv;
Mat g_srcImage;
Mat g_dstDILATEImage;
Mat g_dstERODEImage;
Mat g_dstOPENImage;
Mat g_dstCLOSEImage;
Mat g_dstGRADIENTImage;
Mat g_dstTOPHATImage;
Mat g_dstBLACKHATImage;
int g_DILATEValue=1;
int g_ERODEValue=1;
int g_OPENValue=1;
int g_CLOSEValue=1;
int g_GRADIENTValue=1;
int g_TOPHATValue=1;
int g_BLACKHATValue=1;
const int MaxValue=200;
void onChange_DILATE(int,void*)
{
if(g_DILATEValue<=1) g_DILATEValue=1;
Mat kernel=getStructuringElement(MORPH_RECT,Size(g_DILATEValue,g_DILATEValue));
morphologyEx(g_srcImage,g_dstDILATEImage,MORPH_DILATE,kernel);
imshow("DILATEWindow",g_dstDILATEImage);
}
void onChange_ERODE(int,void*)
{
if(g_ERODEValue<=1) g_ERODEValue=1;
Mat kernel=getStructuringElement(MORPH_RECT,Size(g_ERODEValue,g_ERODEValue));
morphologyEx(g_srcImage,g_dstERODEImage,MORPH_ERODE,kernel);
imshow("ERODEWindow",g_dstERODEImage);
}
void onChange_OPEN(int,void*)
{
if(g_OPENValue<=1) g_OPENValue=1;
Mat kernel=getStructuringElement(MORPH_RECT,Size(g_OPENValue,g_OPENValue));
morphologyEx(g_srcImage,g_dstOPENImage,MORPH_OPEN,kernel);
imshow("OPENWindow",g_dstOPENImage);
}
void onChange_CLOSE(int,void*)
{
if(g_CLOSEValue<=1) g_CLOSEValue=1;
Mat kernel=getStructuringElement(MORPH_RECT,Size(g_CLOSEValue,g_CLOSEValue));
morphologyEx(g_srcImage,g_dstCLOSEImage,MORPH_CLOSE,kernel);
imshow("CLOSEWindow",g_dstCLOSEImage);
}
void onChange_GRADIENT(int,void*)
{
if(g_GRADIENTValue<=1) g_GRADIENTValue=1;
Mat kernel=getStructuringElement(MORPH_RECT,Size(g_GRADIENTValue,g_GRADIENTValue));
morphologyEx(g_srcImage,g_dstGRADIENTImage,MORPH_GRADIENT,kernel);
imshow("GRADIENTWindow",g_dstGRADIENTImage);
}
void onChange_TOPHAT(int,void*)
{
if(g_TOPHATValue<=1) g_TOPHATValue=1;
Mat kernel=getStructuringElement(MORPH_RECT,Size(g_TOPHATValue,g_TOPHATValue));
morphologyEx(g_srcImage,g_dstTOPHATImage,MORPH_TOPHAT,kernel);
imshow("TOPHATWindow",g_dstTOPHATImage);
}
void onChange_BLACKHAT(int,void*)
{
if(g_BLACKHATValue<=1) g_BLACKHATValue=1;
Mat kernel=getStructuringElement(MORPH_RECT,Size(g_BLACKHATValue,g_BLACKHATValue));
morphologyEx(g_srcImage,g_dstBLACKHATImage,MORPH_BLACKHAT,kernel);
imshow("BLACKHATWindow",g_dstBLACKHATImage);
}
int main()
{
g_srcImage=imread("M569_989_066.jpg");
//resize(g_srcImage,g_srcImage,Size(),0.3,0.3,INTER_AREA);
//调整原图像大小
imshow("srcImage",g_srcImage);
namedWindow("DILATEWindow",WINDOW_NORMAL);
createTrackbar("DILATE","DILATEWindow",&g_DILATEValue,MaxValue,onChange_DILATE);
onChange_DILATE(0,0);
namedWindow("ERODEWindow",WINDOW_NORMAL);
createTrackbar("ERODE","ERODEWindow",&g_ERODEValue,MaxValue,onChange_ERODE);
onChange_ERODE(0,0);
namedWindow("OPENWindow",WINDOW_NORMAL);
createTrackbar("OPEN","OPENWindow",&g_OPENValue,MaxValue,onChange_OPEN);
onChange_OPEN(0,0);
namedWindow("CLOSEWindow",WINDOW_NORMAL);
createTrackbar("CLOSE","CLOSEWindow",&g_CLOSEValue,MaxValue,onChange_CLOSE);
onChange_CLOSE(0,0);
namedWindow("GRADIENTWindow",WINDOW_NORMAL);
createTrackbar("GRADIENT","GRADIENTWindow",&g_GRADIENTValue,MaxValue,onChange_GRADIENT);
onChange_GRADIENT(0,0);
namedWindow("TOPHATWindow",WINDOW_NORMAL);
createTrackbar("TOPHAT","TOPHATWindow",&g_TOPHATValue,MaxValue,onChange_TOPHAT);
onChange_TOPHAT(0,0);
namedWindow("BLACKHATWindow",WINDOW_NORMAL);
createTrackbar("BLACKHAT","BLACKHATWindow",&g_BLACKHATValue,MaxValue,onChange_BLACKHAT);
onChange_BLACKHAT(0,0);
waitKey();
return 0;
}
3.数码管例子