形态学操作
OpenCV中提供了几个非常有用的图像形态学操作Api,其工作原理与卷积类似,但是不同的是我们称卷积为结构元素,计算方式也是有算术运算改为简单几何运算与逻辑运算,而且可以将结构元素定义为任意结构。最常见的结构元素有矩形、线性、圆形、狮子交叉性等。OpenCV支持的图像形态学操作主要有以下几种:
- 膨胀
- 腐蚀
- 开操作
- 比操作
- 黑帽
- 顶帽
- 形态学梯度
形态学操作方法
morphologyEx(Mat src, Mat dst, int op, Mat kernel)
- src:输入图像
- dst:输出图像
- op:模式
- kernel:卷积核(和上一篇一样的获取方法)
这里的模式(op)有以下几种:
- MORPH_ERODE = 0:腐蚀
- MORPH_DILATE = 1:膨胀
- MORPH_OPEN = 2:开造作
- MORPH_CLOSE = 3:闭操作
- MORPH_GRADIENT = 4:基本梯度
- MORPH_TOPHAT = 5:顶帽
- MORPH_BLACKHAT = 6:黑帽
膨胀与腐蚀
膨胀与腐蚀就是我们前面一篇介绍的 最大值滤波 和 最小值滤波
所以这里就直接略过了
开操作
开操作 就是 先把图像进行腐蚀,然后在进行膨胀
这样做的一样就是去除小的噪点
下面通过代码演示
Mat m1 = Imgcodecs.imread("C:\\test\\bmp.png" );
HighGui.imshow("原图",m1);
//k是一个3x3 的矩形结构元素
Mat k = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT,new Size(3,3));
Mat s1 = new Mat();
Imgproc.erode(m1,s1,k);//这里先腐蚀
Mat s2 = new Mat();
Imgproc.morphologyEx(m1,s2,Imgproc.MORPH_DILATE,k);//形态学操作-膨胀(m1 膨胀原图)
Mat s3 = new Mat();
Imgproc.dilate(s1,s3,k);//这里膨胀s1 (膨胀腐蚀之后的图)
Mat s4 = new Mat();
Imgproc.morphologyEx(m1,s4,Imgproc.MORPH_OPEN,k);//形态学操作-开操作
HighGui.imshow("腐蚀",s1);
HighGui.imshow("形态学操作-膨胀原图",s2);
HighGui.imshow("腐蚀后膨胀",s3);
HighGui.imshow("形态学操作-原图开操作",s4);
不过这里还是推荐使用形态学操作里面的函数,因为这样只需要调用一次jni函数,效率高
闭操作
闭操作与开操作相反
闭操作是先膨胀、后腐蚀
闭操作的作用一般是补缺口作用
下面请看实际操作
Mat m1 = Imgcodecs.imread("C:\\test\\bmp.png" );
HighGui.imshow("原图",m1);
Mat k = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT,new Size(3,3));
Mat s1 = new Mat();
Imgproc.dilate(m1,s1,k);//这里先膨胀
Mat s2 = new Mat();
Imgproc.morphologyEx(m1,s2,Imgproc.MORPH_ERODE,k);//形态学操作-腐蚀(m1 腐蚀原图)
Mat s3 = new Mat();
Imgproc.erode(s1,s3,k);//这里腐蚀s1 (先膨胀后腐蚀的图)
Mat s4 = new Mat();
Imgproc.morphologyEx(m1,s4,Imgproc.MORPH_CLOSE,k);//形态学操作-闭操作
HighGui.imshow("膨胀原图",s1);
HighGui.imshow("形态学操作-腐蚀原图",s2);
HighGui.imshow("膨胀后腐蚀",s3);
HighGui.imshow("形态学操作-闭操作",s4);
顶帽 与 黑帽
顶帽与黑帽是对原图进行开闭操作后再与原图进行运算得到的结果
下面通过代码展示 就明白了
Mat m1 = Imgcodecs.imread("C:\\test\\bmp.png" );
HighGui.imshow("原图",m1);
//k是一个3x3 的矩形结构元素
Mat k = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT,new Size(5,5));
Mat s1 = new Mat();
Imgproc.morphologyEx(m1,s1,Imgproc.MORPH_OPEN,k);//开
Mat s2 = new Mat();
Imgproc.morphologyEx(m1,s2,Imgproc.MORPH_TOPHAT,k);//顶
Mat s3 = new Mat();
Imgproc.morphologyEx(m1,s3,Imgproc.MORPH_CLOSE,k);//闭
Mat s4 = new Mat();
Imgproc.morphologyEx(m1,s4,Imgproc.MORPH_BLACKHAT,k);//黑
HighGui.imshow("开操作",s1);
HighGui.imshow("顶帽",s2);
HighGui.imshow("闭操作",s3);
HighGui.imshow("黑帽",s4);
由此可看出:
- 开操作和顶帽 : 开操作有的顶帽没有,顶帽有的开操作没有
- 闭操作和黑帽 : 闭操作有的黑帽没有,黑帽有的闭操作没有
从这里 你能看出来他们的关系吗
梯度
梯度可以看做出 膨胀 减去 腐蚀 得到的
下面通过代码演示
Mat m1 = Imgcodecs.imread("C:\\test\\bmp.png" );
HighGui.imshow("原图",m1);
//k是一个3x3 的矩形结构元素
Mat k = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT,new Size(3,3));
Mat s1 = new Mat();
Imgproc.morphologyEx(m1,s1,Imgproc.MORPH_DILATE,k);//膨胀
Mat s2 = new Mat();
Imgproc.morphologyEx(m1,s2,Imgproc.MORPH_ERODE,k);//腐蚀
Mat s3 = new Mat();
Imgproc.morphologyEx(m1,s3,Imgproc.MORPH_GRADIENT,k);//梯度
HighGui.imshow("膨胀",s1);
HighGui.imshow("腐蚀",s2);
HighGui.imshow("梯度",s3);