opencv 4 图像处理(2 形态学滤波:腐蚀与膨胀,开运算、闭运算、形态学梯度、顶帽、黑帽)
腐蚀与膨胀


膨胀(求局部最大值)(dilate函数)





#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
//-----------------------------------【命名空间声明部分】---------------------------------------
// 描述:包含程序所使用的命名空间
//-----------------------------------------------------------------------------------------------
using namespace std;
using namespace cv;
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main()
{
//载入原图
Mat image = imread("1.jpg");
//创建窗口
namedWindow("【原图】膨胀操作");
namedWindow("【效果图】膨胀操作");
//显示原图
imshow("【原图】膨胀操作", image);
//进行膨胀操作
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat out;
dilate(image, out, element);
//显示效果图
imshow("【效果图】膨胀操作", out);
waitKey(0);
return 0;
}
腐蚀(求局部最小值)(erode)




#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main()
{
//载入原图
Mat srcImage = imread("1.jpg");
//显示原图
imshow("【原图】腐蚀操作", srcImage);
//进行腐蚀操作
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat dstImage;
erode(srcImage, dstImage, element);
//显示效果图
imshow("【效果图】腐蚀操作", dstImage);
waitKey(0);
return 0;
}
腐蚀与膨胀滑动条实例
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv;
//-----------------------------------【全局变量声明部分】--------------------------------------
// 描述:全局变量声明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage, g_dstImage;//原始图和效果图
int g_nTrackbarNumer = 0;//0表示腐蚀erode, 1表示膨胀dilate
int g_nStructElementSize = 3; //结构元素(内核矩阵)的尺寸
//-----------------------------------【全局函数声明部分】--------------------------------------
// 描述:全局函数声明
//-----------------------------------------------------------------------------------------------
void Process();//膨胀和腐蚀的处理函数
void on_TrackbarNumChange(int, void *);//回调函数
void on_ElementSizeChange(int, void *);//回调函数
void ShowHelpText();
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main()
{
//改变console字体颜色
system("color 2F");
//载入原图
g_srcImage = imread("1.jpg");
if (!g_srcImage.data) { printf("读取srcImage错误~! \n"); return false; }
ShowHelpText();
//显示原始图
namedWindow("【原始图】");
imshow("【原始图】", g_srcImage);
//进行初次腐蚀操作并显示效果图
namedWindow("【效果图】");
//获取自定义核
Mat element = getStructuringElement(MORPH_RECT, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1), Point(g_nStructElementSize, g_nStructElementSize));
erode(g_srcImage, g_dstImage, element);
imshow("【效果图】", g_dstImage);
//创建轨迹条
createTrackbar("腐蚀/膨胀", "【效果图】", &g_nTrackbarNumer, 1, on_TrackbarNumChange);
createTrackbar("内核尺寸", "【效果图】", &g_nStructElementSize, 21, on_ElementSizeChange);
//输出一些帮助信息
cout << endl << "\t运行成功,请调整滚动条观察图像效果~\n\n"
<< "\t按下“q”键时,程序退出。\n";
//轮询获取按键信息,若下q键,程序退出
while (char(waitKey(1)) != 'q') {}
return 0;
}
//-----------------------------【Process( )函数】------------------------------------
// 描述:进行自定义的腐蚀和膨胀操作
//-----------------------------------------------------------------------------------------
void Process()
{
//获取自定义核
Mat element = getStructuringElement(MORPH_RECT, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1), Point(g_nStructElementSize, g_nStructElementSize));
//进行腐蚀或膨胀操作
if (g_nTrackbarNumer == 0) {
erode(g_srcImage, g_dstImage, element);
}
else {
dilate(g_srcImage, g_dstImage, element);
}
//显示效果图
imshow("【效果图】", g_dstImage);
}
//-----------------------------【on_TrackbarNumChange( )函数】------------------------------------
// 描述:腐蚀和膨胀之间切换开关的回调函数
//-----------------------------------------------------------------------------------------------------
void on_TrackbarNumChange(int, void *)
{
//腐蚀和膨胀之间效果已经切换,回调函数体内需调用一次Process函数,使改变后的效果立即生效并显示出来
Process();
}
//-----------------------------【on_ElementSizeChange( )函数】-------------------------------------
// 描述:腐蚀和膨胀操作内核改变时的回调函数
//-----------------------------------------------------------------------------------------------------
void on_ElementSizeChange(int, void *)
{
//内核尺寸已改变,回调函数体内需调用一次Process函数,使改变后的效果立即生效并显示出来
Process();
}
//-----------------------------------【ShowHelpText( )函数】-----------------------------
// 描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION);
printf("\n\n ----------------------------------------------------------------------------\n");
}
开运算、闭运算、形态学梯度、顶帽、黑帽(morphologyEx函数)

开运算(先腐蚀后膨胀)

闭运算(先膨胀后腐蚀)

形态学梯度(膨胀图与腐蚀图之差)


顶帽(原图像与开运算之差)


黑帽(闭运算与原图像之差)


核心API函数(morphologyEx函数)






范例
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
//-----------------------------------【main( )函数】------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main( )
{
//载入原始图
Mat image = imread("1.jpg"); //工程目录下应该有一张名为1.jpg的素材图
//创建窗口
namedWindow("【原始图】形态学梯度");
namedWindow("【效果图】形态学梯度");
//显示原始图
imshow("【原始图】形态学梯度", image);
//定义核
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
//进行形态学操作
morphologyEx(image, image, MORPH_GRADIENT, element);
//显示效果图
imshow("【效果图】形态学梯度", image);
waitKey(0);
return 0;
}
综合实例
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
//-----------------------------------【全局变量声明部分】-----------------------------------
// 描述:全局变量声明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage, g_dstImage;//原始图和效果图
int g_nElementShape = MORPH_RECT;//元素结构的形状
//变量接收的TrackBar位置参数
int g_nMaxIterationNum = 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_TopBlackHat(int, void*);//回调函数
static void ShowHelpText();
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main()
{
//改变console字体颜色
system("color 2F");
ShowHelpText();
//载入原图
g_srcImage = imread("1.jpg");
if (!g_srcImage.data) { printf("Oh,no,读取srcImage错误~! \n"); return false; }
//显示原始图
namedWindow("【原始图】");
imshow("【原始图】", g_srcImage);
//创建三个窗口
namedWindow("【开运算/闭运算】", 1);
namedWindow("【腐蚀/膨胀】", 1);
namedWindow("【顶帽/黑帽】", 1);
//参数赋值
g_nOpenCloseNum = 9;
g_nErodeDilateNum = 9;
g_nTopBlackHatNum = 2;
//分别为三个窗口创建滚动条
createTrackbar("迭代值", "【开运算/闭运算】", &g_nOpenCloseNum, g_nMaxIterationNum * 2 + 1, on_OpenClose);
createTrackbar("迭代值", "【腐蚀/膨胀】", &g_nErodeDilateNum, g_nMaxIterationNum * 2 + 1, on_ErodeDilate);
createTrackbar("迭代值", "【顶帽/黑帽】", &g_nTopBlackHatNum, g_nMaxIterationNum * 2 + 1, on_TopBlackHat);
//轮询获取按键信息
while (1)
{
int c;
//执行回调函数
on_OpenClose(g_nOpenCloseNum, 0);
on_ErodeDilate(g_nErodeDilateNum, 0);
on_TopBlackHat(g_nTopBlackHatNum, 0);
//获取按键
c = waitKey(0);
//按下键盘按键Q或者ESC,程序退出
if ((char)c == 'q' || (char)c == 27)
break;
//按下键盘按键1,使用椭圆(Elliptic)结构元素结构元素MORPH_ELLIPSE
if ((char)c == 49)//键盘按键1的ASII码为49
g_nElementShape = MORPH_ELLIPSE;
//按下键盘按键2,使用矩形(Rectangle)结构元素MORPH_RECT
else if ((char)c == 50)//键盘按键2的ASII码为50
g_nElementShape = MORPH_RECT;
//按下键盘按键3,使用十字形(Cross-shaped)结构元素MORPH_CROSS
else if ((char)c == 51)//键盘按键3的ASII码为51
g_nElementShape = MORPH_CROSS;
//按下键盘按键space,在矩形、椭圆、十字形结构元素中循环
else if ((char)c == ' ')
g_nElementShape = (g_nElementShape + 1) % 3;
}
return 0;
}
//-----------------------------------【on_OpenClose( )函数】----------------------------------
// 描述:【开运算/闭运算】窗口的回调函数
//-----------------------------------------------------------------------------------------------
static void on_OpenClose(int, void*)
{
//偏移量的定义
int offset = g_nOpenCloseNum - g_nMaxIterationNum;//偏移量
int Absolute_offset = offset > 0 ? offset : -offset;//偏移量绝对值
//自定义核
Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
//进行操作
if (offset < 0)
//此句代码的OpenCV2版为:
//morphologyEx(g_srcImage, g_dstImage, CV_MOP_OPEN, element);
//此句代码的OpenCV3版为:
morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);
else
//此句代码的OpenCV2版为:
//morphologyEx(g_srcImage, g_dstImage, CV_MOP_CLOSE, element);
//此句代码的OpenCV3版为:
morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);
//显示图像
imshow("【开运算/闭运算】", g_dstImage);
}
//-----------------------------------【on_ErodeDilate( )函数】----------------------------------
// 描述:【腐蚀/膨胀】窗口的回调函数
//-----------------------------------------------------------------------------------------------
static void on_ErodeDilate(int, void*)
{
//偏移量的定义
int offset = g_nErodeDilateNum - g_nMaxIterationNum; //偏移量
int Absolute_offset = offset > 0 ? offset : -offset;//偏移量绝对值
//自定义核
Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
//进行操作
if (offset < 0)
erode(g_srcImage, g_dstImage, element);
else
dilate(g_srcImage, g_dstImage, element);
//显示图像
imshow("【腐蚀/膨胀】", g_dstImage);
}
//-----------------------------------【on_TopBlackHat( )函数】--------------------------------
// 描述:【顶帽运算/黑帽运算】窗口的回调函数
//----------------------------------------------------------------------------------------------
static void on_TopBlackHat(int, void*)
{
//偏移量的定义
int offset = g_nTopBlackHatNum - g_nMaxIterationNum;//偏移量
int Absolute_offset = offset > 0 ? offset : -offset;//偏移量绝对值
//自定义核
Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
//进行操作
if (offset < 0)
morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);
else
morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);
//显示图像
imshow("【顶帽/黑帽】", g_dstImage);
}
//-----------------------------------【ShowHelpText( )函数】----------------------------------
// 描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION);
printf("\n\n ----------------------------------------------------------------------------\n");
//输出一些帮助信息
printf("\n\t请调整滚动条观察图像效果\n\n");
printf("\n\t按键操作说明: \n\n"
"\t\t键盘按键【ESC】或者【Q】- 退出程序\n"
"\t\t键盘按键【1】- 使用椭圆(Elliptic)结构元素\n"
"\t\t键盘按键【2】- 使用矩形(Rectangle )结构元素\n"
"\t\t键盘按键【3】- 使用十字型(Cross-shaped)结构元素\n"
"\t\t键盘按键【空格SPACE】- 在矩形、椭圆、十字形结构元素中循环\n");
}
opencv 4 图像处理(2 形态学滤波:腐蚀与膨胀,开运算、闭运算、形态学梯度、顶帽、黑帽)的更多相关文章
- OpenCV学习 7:图像形态学:腐蚀、膨胀
原创文章,欢迎转载,转载请注明出处 首先什么是图像形态学?额,这个抄下百度到的答案.基本思想: 用具有一定形态的结构元素去度量和提取图像中的对应形状已达到对图像分析和识别的目的,形态学图像处理表 ...
- paper 76:膨胀、腐蚀、开、闭运算——数字图像处理中的形态学
膨胀.腐蚀.开.闭运算是数学形态学最基本的变换.本文主要针对二值图像的形态学膨胀:把二值图像各1像素连接成分的边界扩大一层(填充边缘或0像素内部的孔):腐蚀:把二值图像各1像素连接成分的边界点去掉从而 ...
- Java基于opencv实现图像数字识别(五)—腐蚀、膨胀处理
腐蚀:去除图像表面像素,将图像逐步缩小,以达到消去点状图像的效果:作用就是将图像边缘的毛刺剔除掉 膨胀:将图像表面不断扩散以达到去除小孔的效果:作用就是将目标的边缘或者是内部的坑填掉 使用相同次数的腐 ...
- 机器学习进阶-图像形态学变化-礼帽与黑帽 1.cv2.TOPHAT(礼帽-原始图片-开运算后图片) 2.cv2.BLACKHAT(黑帽 闭运算-原始图片)
1.op = cv2.TOPHAT 礼帽:原始图片-开运算后的图片 2. op=cv2.BLACKHAT 黑帽: 闭运算后的图片-原始图片 礼帽:表示的是原始图像-开运算(先腐蚀再膨胀)以后的图像 ...
- opencv:形态学操作-腐蚀与膨胀
#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...
- Python 图像处理 OpenCV (9):图像处理形态学开运算、闭运算以及梯度运算
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- Python 图像处理 OpenCV (10):图像处理形态学之顶帽运算与黑帽运算
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- 【OpenCV新手教程之十一】 形态学图像处理(二):开运算、闭运算、形态学梯度、顶帽、黑帽合辑
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/23184547 作者:毛星云(浅墨) ...
- OpenCV图像处理篇之腐蚀与膨胀
转载请注明出处:http://xiahouzuoxin.github.io/notes 腐蚀与膨胀 腐蚀和膨胀是图像的形态学处理中最主要的操作,之后遇见的开操作和闭操作都是腐蚀和膨胀操作的结合运算. ...
随机推荐
- 图像处理笔记(二十):LAWS纹理滤波应用于缺陷检测
LAWS纹理滤波 texture_laws(Image, 原图像 ImageTexture, 输出值,滤波后图像 FilterType, 过滤器类型 Shift, 灰度值转换,滤波后的灰度值可能会比较 ...
- 12.Linux重定向与管道|
1.重定向概述 1.1什么是重定向 将原本要输出到屏幕的数据信息,重新定向到某个指定的文件中 名称 文件描述符 作用 标准输入(STDIN) 0 默认是键盘,也可以是文件或其他命令的输出. 标准输出( ...
- Cassandra官方介绍及安装
Cassandra官方介绍及安装 这个数据库有很高的伸缩性和可用性,你完全不需要向性能妥协.在硬件或者云设施上做修改 官网:Cassandra官网 一.简介 cassandra这个数据库有很高的伸缩性 ...
- ESP8266开发之旅 网络篇⑥ ESP8266WiFiGeneric——基础库
1. 前言 在前面的博文中,博主介绍到ESP8266WiFi库是包含了很多功能的一个超级库.ESP8266WiFi库不仅仅局限于 ESP8266WiFi.h 和 ESP8266WiFi.cpp ...
- mac本地安装单机hadoop--学习笔记
Mac配置hadoop1.修改 /etc/hosts127.0.0.1 localhost2.下载hadoop2.9.0和jdk并安装配置相应环境 vim /etc/profile export HA ...
- github实用的搜索小技巧
查资源,学习优秀的框架,搜索是一种能力! 作为程序猿开发中最大的同性交友网站,github当之无愧,里面有很多优秀的开源框架,各种技术大佬混迹其中,有他们总结的学习教程,造好的轮子(开发的各种工具,技 ...
- 死磕 java线程系列之线程池深入解析——定时任务执行流程
(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 注:本文基于ScheduledThreadPoolExecutor定时线程池类. 简介 前面我们一起学习了普通 ...
- Spring Boot 使用@Scheduled定时器任务
摘要: Spring Boot之使用@Scheduled定时器任务 假设我们已经搭建好了一个基于Spring Boot项目,首先我们要在Application中设置启用定时任务功能@EnableSch ...
- java 项目时间和服务器时间不一致
今天线上项目关于时间的几个任务都出了问题,查看日志发现日志的时间不对,用的是log4j,日志输出的时间都早了很长时间. 1 首先先登上服务器查看了服务器的系统时间 linux下 date命令 时间正确 ...
- 操作系统实现(一):从Bootloader到ELF内核(转载)
原文链接: http://www.cppblog.com/airtrack/archive/2014/10/30/208729.html Bootloader 我们知道计算机启动是从BIOS开始,再由 ...