形态学操作——开闭运算、顶帽底(黑)帽变换

膨胀和腐蚀运算的问题:

边缘形状发生了变化,膨胀发生了扩张,腐蚀发生了收缩
目标物体变形,对识别时的特征提取会造成影响

解决方法:

开操作:

gongshi
B对A的开操作就是先B对A腐蚀,紧接着用B对结果进行膨胀
效果
先腐蚀再膨胀的结果并不是恢复原状,而是会消除黏连部分,同时不影响其他部分的形状.
平滑物体的轮廓,断开较窄的狭颈并消除较细的突出。
效果:
效果

闭操作:

公式
B对A的闭操作就是先B对A膨胀,紧接着用B对结果进行腐蚀
效果
先膨胀再腐蚀的结果并不是恢复原状,而是填充小的裂缝、孔隙,且不影响形状.
平滑物体的轮廓,弥合较窄的间断和细小的沟壑,消除小的孔洞,填充轮廓中的断痕。
效果:
效果
更加详细的过程如下:
详细过程
除了开闭运算,黑帽顶帽运算也是形态学操作比较重要的操作。

顶帽变换:原图-灰度开运算(灰度腐蚀+灰度膨胀)

效果:
1、保留比结构元素小的部分
2、保留比周围环境亮的像素

底帽变换:灰度闭运算(灰度膨胀+灰度腐蚀)-原图 效果:

1、保留比结构元素小的部分
2、保留比周围环境暗的像素

解释:
顶帽处理使背景变得趋于一致了,前景和背景的对比度加深了
这是因为,在顶帽处理中当结构元素比前景目标物的大小
大的时候,腐蚀的步骤会选择周围比较暗的值代替比较亮的值
所以背景变暗了,同时前景被去掉了。再用原图和结果相减,就可以把背景去掉,把开运算中去掉的前景给保留下来
1
2

代码实现

#include <opencv2/opencv.hpp>
#include <iostream>
#include "windows.h"
#include <stdio.h>using namespace cv;
using namespace std;//*--------------------------【练习】形态学操作morphology大练习------------------------------------*/
//请调整滚动条观察图像效果
//按键操作说明 :
//键盘按键【空格SPACE】- 在矩形、椭圆、十字形结构元素中循环
//键盘按键【1】- 使用椭圆结构元素
//键盘按键【2】- 使用矩形结构元素
//键盘按键【3】- 使用十字形结构元素
Mat g_secImage, g_dstImage;	//原图和效果图
int g_nElementShape = MORPH_RECT;	//初始化元素结构形状//变量接受的Trackbar值
int  g_nMaxIterationMun = 10;
int g_nOpenCloseNum = 0;
int g_nErodeDilateNum = 0;
int g_nTopBlackHatNum = 0;//*--------------------------【全局函数声明】-----------------------------------*/
static void on_OpenClose(int, void*);		//回调函数
static void on_ErodeDilate(int, void*);		//回调函数
static void on_TopBlakHat(int, void*);		//回调函数
void ShowHelpText1();
void ShowHelpText2();
int main()
{SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);		//字体为绿色//载入原图g_secImage = imread("D:\\opencv_picture_test\\形态学操作\\黑白.jpg");//判断图像是否加载成功if (g_secImage.empty()){cout << "图像加载失败!" << endl;return -1;}elsecout << "图像加载成功!" << endl << endl;//显示原图像namedWindow("原图像", WINDOW_NORMAL);     //定义窗口显示属性imshow("原图像", g_secImage);//创建三个窗口namedWindow("【开运算/闭运算】", WINDOW_NORMAL);    namedWindow("【腐蚀/膨胀】", WINDOW_NORMAL);namedWindow("【顶帽/黑帽】", WINDOW_NORMAL);//参数赋值g_nOpenCloseNum = 9;g_nErodeDilateNum =9;g_nTopBlackHatNum =2;//分别为三个窗口建立滑动条createTrackbar("迭代值", "【开运算/闭运算】", &g_nOpenCloseNum, g_nMaxIterationMun*2+1,on_OpenClose);createTrackbar("迭代值", "【腐蚀/膨胀】", &g_nErodeDilateNum, g_nMaxIterationMun * 2 + 1, on_ErodeDilate);createTrackbar("迭代值", "【顶帽/黑帽】", &g_nTopBlackHatNum, g_nMaxIterationMun * 2 + 1, on_TopBlakHat);//show帮助信息ShowHelpText1();//轮询获取按键信息while (1){int c;//执行回调函数on_OpenClose(g_nOpenCloseNum,0);on_ErodeDilate(g_nErodeDilateNum,0);on_TopBlakHat(g_nTopBlackHatNum,0);//获取按键c = waitKey(0);//按下按键ESC程序退出if ((char)c == 27){break;}//按键1,使用椭圆结构元素if ((char)c == 49){g_nElementShape = MORPH_ELLIPSE;}//按键2,使用矩形结构元素else if ((char)c == 50){g_nElementShape = MORPH_RECT;}//按键3,使用十字形结构元素else if ((char)c == 51){g_nElementShape = MORPH_CROSS;}//按键空格,换一种结构元素else if ((char)c == ' '){g_nElementShape = (g_nElementShape+1)%3;}}
}
//*--------------------------【回调函数】-----------------------------------*/static void on_OpenClose(int, void*)
{//偏移量定义int offset = g_nOpenCloseNum - g_nMaxIterationMun;	//偏移量int Abs_offset = offset > 0 ? offset : -offset;	//偏移量的绝对值//自定义核Mat element = getStructuringElement(g_nElementShape,Size(Abs_offset*2+1, Abs_offset*2+1),Point(Abs_offset, Abs_offset));	//返回的是内核矩阵//进行操作if (offset < 0){morphologyEx(g_secImage, g_dstImage, MORPH_OPEN, element);}else{morphologyEx(g_secImage, g_dstImage, MORPH_CLOSE, element);}//显示效果图imshow("【开运算/闭运算】", g_dstImage);
}
static void on_ErodeDilate(int, void*)
{//偏移量定义int offset = g_nErodeDilateNum - g_nMaxIterationMun;	//偏移量int Abs_offset = offset > 0 ? offset : -offset;	//偏移量的绝对值//自定义核Mat element = getStructuringElement(g_nElementShape, Size(Abs_offset * 2 + 1, Abs_offset * 2 + 1), Point(Abs_offset, Abs_offset));	//返回的是内核矩阵//进行操作if (offset < 0){morphologyEx(g_secImage, g_dstImage, MORPH_ERODE, element);}else{morphologyEx(g_secImage, g_dstImage, MORPH_DILATE, element);}//显示效果图imshow("【腐蚀/膨胀】", g_dstImage);
}
static void on_TopBlakHat(int, void*)
{//偏移量定义int offset = g_nTopBlackHatNum - g_nMaxIterationMun;	//偏移量int Abs_offset = offset > 0 ? offset : -offset;	//偏移量的绝对值//自定义核Mat element = getStructuringElement(g_nElementShape, Size(Abs_offset * 2 + 1, Abs_offset * 2 + 1), Point(Abs_offset, Abs_offset));	//返回的是内核矩阵//进行操作if (offset < 0){morphologyEx(g_secImage, g_dstImage, MORPH_TOPHAT, element);}else{morphologyEx(g_secImage, g_dstImage, MORPH_BLACKHAT, element);}//显示效果图imshow("【顶帽/黑帽】", g_dstImage);
}//-----------------------------------【ShowHelpText( )函数】-----------------------------
//          描述:输出一些帮助信息//关于morphologyEx参数的问题://MORPH_BLACKHAT:黑帽运算//MORPH_TOPHAT:顶帽运算//MORPH_CLOSE:闭运算//MORPH_OPEN:开运算//MORPH_GRADIENT:形态学梯度//MORPH_ERODE:腐蚀运算//MORPH_DILATE:膨胀运算//关于getStructuringElement参数的问题://MORPH_RECT:矩形内核//MORPH_CROSS:交叉型内核//MORPH_ELLIPSE:椭圆形矩阵
//请调整滚动条观察图像效果
//按键操作说明 :
//键盘按键【空格SPACE】- 在矩形、椭圆、十字形结构元素中循环
//键盘按键【1】- 使用椭圆结构元素
//键盘按键【2】- 使用矩形结构元素
//键盘按键【3】- 使用十字形结构元素
//----------------------------------------------------------------------------------------------
void ShowHelpText1()
{//输出一些帮助信息printf("\n\n\n请调整滚动条观察图像效果\n");printf("\n\n\t按键操作说明\n");printf("\n\n\t键盘按键【空格SPACE】- 在矩形、椭圆、十字形结构元素中循环\n");printf("\n\n\t键盘按键【1】- 使用椭圆结构元素\n");printf("\n\n\t键盘按键【2】- 使用矩形结构元素\n");printf("\n\n\t键盘按键【3】- 使用十字形结构元素\n");
}
void ShowHelpText2()
{//输出一些帮助信息printf("\n\n\n\morphologyEx 参数有以下几种类型\n");printf("\n\n\tMORPH_BLACKHAT:黑帽运算\n");printf("\n\n\tMORPH_TOPHAT:顶帽运算\n");printf("\n\n\tMORPH_CLOSE:闭运算\n");printf("\n\n\tMORPH_OPEN:开运算\n");printf("\n\n\t//MORPH_GRADIENT:形态学梯度\n");printf("\n\n\tMORPH_ERODE:腐蚀运算\n");printf("\n\n\tMORPH_DILATE:膨胀运算\n");printf("\n\n\n\getStructuringElement参数的问题:\n");printf("\n\n\tMORPH_RECT:矩形内核\n");printf("\n\n\tMORPH_CROSS:交叉型内核\n");printf("\n\n\tMORPH_ELLIPSE:椭圆形矩阵\n");
}

代码实现效果:
321

代码解释

调用opencv库函数morphologyEx,通过调整参数就可以实现不同的形态学操作。
其中回调函数中要求得变量:偏移量(当前迭代值和预置最大迭代值之差),用它的正负来判断是进行哪种对偶操作。用它的绝对值来决定矩阵核的大小(边长为奇数),以及结构元素锚点的位置。
另外需要注意:十字形的element形状唯一依赖于锚点的位置。
而在其他情况下,锚点只是影响形态学运算结果的偏移。

相关链接:[https://www.cnblogs.com/zsb517/archive/2012/06/08/2541193.html(https://www.cnblogs.com/zsb517/archive/2012/06/08/2541193.html)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/378727.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 基础实战_Java基础实战(三)

是否是否是否是否获取字符串字符数组大写?小写?数字?非字母与数字大写字母小写字母数字i结束ii1第一步 拆分字符串为字符数组&#xff1a;static void count(String str) {// 将字符串拆分为字符数组char[] charArray str.toCharArray();}第二步 定义相关变量记录结果&…

11-图像梯度-Sobel算子

图像梯度是指图像某像素在x和y两个方向上的变化率&#xff08;与相邻像素比较&#xff09;&#xff0c;是一个二维向量&#xff0c;由2个分量组成&#xff0c;X轴的变化、Y轴的变化 。 其中X轴的变化是指当前像素右侧&#xff08;X加1&#xff09;的像素值减去当前像素左侧&…

给IE有效指定编码

<title>下一站</title> <meta http-equiv"Content-Type" content"text/html; charsetutf-8" /> IE每次打开&#xff0c;均是一片空白&#xff0c;查看右键&#xff0d;编码&#xff0c;显示是GB2312。要手功改为UTF-8后才能正常显示页面…

形态学操作——击中击不中变换

操作目的 HitMiss变换是形态检测的一个工具&#xff0c;通过定义形状模板可以在图像中获取同一形状物体的位置坐标。 算法讲解 1、用击中结构去腐蚀原始图像得到击中结果X&#xff08;这个过程可以理解为在原始图像中寻找和击中结构完全匹配的模块&#xff0c;匹配上了之后&…

stack.pop()方法_C.示例中的Stack.Pop()方法

stack.pop()方法C&#xff03;Stack.Pop()方法 (C# Stack.Pop() method) Stack.Pop() method is used to remove an object from the top of the stack. The method removes and returns the object from the top. Stack.Pop()方法用于从堆栈顶部删除对象。 该方法从顶部删除并…

java list的作用_集合框架(List集合的特有功能概述和测试)

package cn.itcast_03;import java.util.ArrayList;import java.util.List;/** List集合的特有功能&#xff1a;* A:添加功能* void add(int index,Object element):在指定位置添加元素* B:获取功能* Object get(int index):获取指定位置的元素* C:列表迭代器* ListIterator li…

12-图像梯度-Scharr算子和laplacian算子

Scharr算子 cv2.Scharr(img,cv2.CV_64F,1,0) 第一个参数&#xff1a;当前的图像对象名称 第二个参数&#xff1a;当前图像的深度&#xff0c;通常情况下指定为-1&#xff0c;表示输出和输入的深度是一样的&#xff1b;cv2.CV_64F可以存6字节的大小&#xff0c;为了方便后面的取…

新的一年新希望,百忙中继续学习

公司来了一批新同事&#xff0c;我又忙于购买设备&#xff0c;布置办公桌了。 小林建议我找一份更合适的工作&#xff0c;目前的我其实是在混日子&#xff0c;因为我并不擅长沟通与销售。 暂时还是保持这样吧&#xff0c;我还需要一定时间来积蓄力量。 转载于:https://www.cnbl…

Oracle Internal Event:10200 Consistent Read诊断事件

10200(consistent read buffer status)内部诊断事件可以用于探测一致性读CR(consistent read)块的访问情况&#xff0c;虽然cr读的统计信息可以从v$sysstat或AWR/statspack中获取&#xff0c;但是10200 event还是我们研究Consistent Read一致性读的有力工具。该事件可以通过在会…

多线程循环输出abcc++_C ++循环| 查找输出程序| 套装4

多线程循环输出abccProgram 1: 程序1&#xff1a; #include <iostream>using namespace std;int A 5;int fun(){return A--;}int main(){int A 5;while (fun()) {cout << A ::A << " ";}return 0;}Output: 输出&#xff1a; 9 8 7 6 5Explana…

Opencv——图像金字塔与图像尺寸缩放

主要讲解 1、resize()函数调用 函数定义&#xff1a; 调用方式&#xff1a; resize(srcImage, dstImage, Size(64, 128)); //对图片进行修改 resize(srcImage, dstImage, Size(), 0.5, 0.5);第6个参数的含义&#xff1a; INTER_NEAREST:最邻近插值 (放大好用) INTER_ARE…

java nature_Java中BufferedReader和scanner的对比 - nature

原地址&#xff1a;http://blog.sina.com.cn/s/blog_5fd837410100rtwk.html Scanner 和BufferedReader同样能实现将键盘输入的数据送入程序&#xff0c; import java.io.*; import java.util.Scanner; public class C { public static void main(String []args) throws IOExcep…

13-Canny边缘检测

Canny边缘检测主要思路步骤如下&#xff1a; 1&#xff0c;使用高斯滤波器&#xff0c;以平滑图像&#xff0c;滤除噪声 2&#xff0c;计算图像中每个像素点的梯度强度和方向 3&#xff0c;应用非极大值抑制&#xff0c;以消除边缘检测带来的杂散响应 4&#xff0c;应用双阈值检…

c# uri.host_C#| Uri.IsHexEncoding()方法与示例

c# uri.hostUri.IsHexEncoding()方法 (Uri.IsHexEncoding() Method) Uri.IsHexEncoding() method is a static method or Uri class. Which is used to return that given string is hex-encoded or not? If the given string is hex coded then it returns true otherwise it…

一位老鸟对 23 种设计模式的有趣见解(转)

在网络上流畅很广的一篇旧文&#xff0c;暂时没找到原作者&#xff0c;目前所看到的最早转载时间是 2005 年 2 月 28 日。作者用轻松的语言&#xff0c;形象解释了 23 种模式&#xff0c;有很好的启发作用。创建型模式 1、FACTORY—追MM少不了请吃饭了&#xff0c;麦当劳的鸡翅…

微机原理——移位指令

例题 思路 选择移位语句&#xff0c;右移&#xff0c;将AL移出的送入DX左端&#xff0c;将BL移出的送入DX左端。循环八次 MOV AL,01100101B; MOV BL,11011010B; XOR DX,DX;两个值相同&#xff0c;异或结果为0。等效&#xff1a;MOV DX,0 MOV CX,8;count L1: SHR AL,1;逻辑右…

14-图像金字塔

由第一个图可知&#xff0c;图像金字塔这无非就是对图像进行放大和缩小罢了 1&#xff0c;高斯金字塔 向下采样方法(缩小)&#xff0c;越采样越小&#xff0c;即从金字塔底部向上采样 cv2.pyrDown(img) 向上采样方法(放大)&#xff0c;越采样越大&#xff0c;即从金字塔顶…

JAVA和javascrito_JAVA 和JavaScript的split方法异同

Split的方法很常用&#xff0c;除了str.split("regex")&#xff0c;其实还可以多传一个参数&#xff1a;str.split("regex", limit)。但是要注意&#xff0c;JavaScript和java的split中limit参数作用是不同的。简单说&#xff0c;JavaScript中&#xff0c;…

如果__name__ =='__main__':在Python中怎么办?

In order to understand the details of __name__ variable and the if condition, let us go through a simple exercise. Run a simple python file with just the following lines and run the file as python3 code, 为了了解__name__变量和if条件的详细信息&#xff0c;让…

Eclipse C/C++开发环境搭建

1 Eclipse的安装 到http://java.sun.com/j2se/1.5.0/download.jsp 下载JRE安装&#xff1b; 到http://eclipse.org下载Eclipse安装。&#xff08;这儿可以下载Java版本的&#xff0c;也可以下载C/C 版本的&#xff09; 2 对于下载的Java版本或着只下载Eclipse IDE的&#xff0c…