当前位置: 首页 > news >正文

15_01_opencv_形态学滤波

基本概念

数学形态学(Mathematical morphology):是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论。其基本的运算包括:
二值腐蚀和膨胀、二值开闭运算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、Top-hat 变换、颗粒分析、流域变换、灰值腐蚀和膨胀、灰值开闭运算、灰值形态学梯度等。

腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。
膨胀是图像中的高亮部分进行膨胀,类似于“领域扩张”,效果图拥有比原图更大的高亮区域;
腐蚀是原图中的高亮部分被腐蚀,类似于“领域被蚕食”,效果图拥有比原图更小的高亮区域。

膨胀

求局部最大值的操作。
将图像(或图像的一部分区域,称之为 A)与核(称之为 B)进行卷积。
核可以是任何形状和大小,它拥有一个单独定义出来的参考点,我们称其为锚点(anchorpoint)。多数情况下,核是一个小的,中间带有参考点和实心正方形或者圆盘。其实,可以把核视为模板或者掩码。
而膨胀就是求局部最大值的操作。核B与图形卷积,即计算核B覆盖的区域的像素点的最大值,并把这个最大值赋值给参考点指定的像素。这样就会使图像中的高亮区域逐渐增长,这就是膨胀操作的初衷。
在这里插入图片描述

腐蚀

求局部最小值的操作。
在这里插入图片描述

开运算

其实就是先腐蚀后膨胀的过程。
其数学表达式如下:
dst=open(src,element)=dilate(erode(src,element))dst=open(src,element)=dilate(erode (src,element))dst=open(src,element)=dilate(erode(src,element))
开运算可以用来消除小物体,在纤细点处分离物体,并且在平滑较大物体的边界的同时不明显改变其面积。

闭运算

先膨胀后腐蚀的过程称为闭运算(Closing Operation),
其数学表达式如下:
dst=clese(src,element)=erode(dilate(src,element))dst=clese(src,element)= erode (dilate(src,element))dst=clese(src,element)=erode(dilate(src,element))
闭运算能够排除小型黑洞(黑色区域)。

形态学梯度

形态学梯度(Morphological Gradient)是膨胀图与腐蚀图之差,
数学表达式如下:
dst=morph−grad(src,element)=dilate(src,element)−erode(src,element)dst=morph-grad(src,element)= dilate(src,element)- erode(src,element)dst=morphgrad(src,element)=dilate(src,element)erode(src,element)
对二值图像进行这一操作可以将团块(blob)的边缘突出出来。我们可以用形态学梯度来保留物体的边缘轮廓.

顶帽

顶帽运算(Top Hat)又常常被译为”礼帽“运算,是原图像与“开运算”的结果图之差,
数学表达式如下:
dst=tophat(src,element)=src−open(src,element)dst=tophat(src,element)=src-open(src,element)dst=tophat(src,element)=srcopen(src,element)
因为开运算带来的结果是放大了裂缝或者局部低亮度的区域。因此,从原图中减去开运算后的图,得到的效果图突出了比原图轮廓周围的区域更明亮的区域,且这一操作与选择的核的大小相关。
顶帽运算往往用来分离比邻近点亮一些的斑块。在一幅图像具有大幅的背景,而微小物品比较有规律的情况下,可以使用顶帽运算进行背景提取。

黑帽

黑帽(Black Hat)运算是闭运算的结果图与原图像之差。
数学表达式为:
dst=blackhat(src,element)=close(src,element)−srcdst=blackhat(src,element)=close(src,element)-srcdst=blackhat(src,element)=close(src,element)src

黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关。
所以,黑帽运算用来分离比邻近点暗一些的斑块,效果图有着非常完美的轮廓。

形态学滤波

膨胀 dilate()

void cv::dilate(	InputArray 	src,OutputArray 	dst,InputArray 	kernel,Point 	anchor = Point(-1,-1),int 	iterations = 1,int 	borderType = BORDER_CONSTANT,const Scalar & 	borderValue = morphologyDefaultBorderValue())	
  • 第一个参数,InputArray 类型的 src,输入图像,即源图像,填Mat 类的对象即可。图像通道的数量可以是任意的,但图像深度应为 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F 其中之一。
  • 第二个参数,OutputAmay 类型的 dst,即目标图像,需要和源图片有一样的尺寸和类型。
  • 第三个参数,InputArray 类型的 kemel,膨胀操作的核。当为 NULL 时,表示的是使用参考点位于中心 3x3 的核。
  • 第四个参数,Point 类型的 anchor,锚的位置,其有默认值(-1,-1),表示锚位于中心。
  • 第五个参数,int 类型的 iterations,迭代使用 erodeO函数的次数,默认值为1
  • 第六个参数,int 类型的 borderType,用于推断图像外部像素的某种边界模式。注意它有默认值 BORDER_DEFAULT。
  • 第七个参数,const Scalar&类型的 borderValue,当边界为常数时的边界值,有默认值 morphologyDefaultBorderValue(),一般不用去管它。需要用到它时,可以看官方文档中的createMorphologyFilte()函数,以得到更详细的解释。

在这里插入图片描述

#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("38.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()

void cv::erode(	InputArray 	src,OutputArray 	dst,InputArray 	kernel,Point 	anchor = Point(-1,-1),int 	iterations = 1,int 	borderType = BORDER_CONSTANT,const Scalar & 	borderValue = morphologyDefaultBorderValue())	
  • 第一个参数,InputArray 类型的 src,输入图像,即源图像,填Mat 类的对象即可。图像通道的数量可以是任意的,但图像深度应为 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F 其中之一。
  • 第二个参数,OutputAmay 类型的 dst,即目标图像,需要和源图片有一样的尺寸和类型。
  • 第三个参数,InputArray 类型的 kernel,腐蚀操作的内核。为 NULL 时,表示的是使用参考点位于中心 3x3 的核。一般使用函数 getStructuringElement()配合这个参数的使用。getStructuringElement 函数会返回指定形状和尺寸的结构元素(内核矩阵)
  • 第四个参数,Point 类型的 anchor,锚的位置。其有默认值(-1,-1),表示锚位于单位(element)的中心,一般不用管它。
  • 第五个参数,int 类型的 iterations,迭代使用 erode()函数的次数,默认值为1
    第六个参数,int 类型的 borderType,用于推断图像外部像素的某种边界模式。注意它有默认值 BORDER DEFAULT。
    第七个参数,const Scalar&类型的 borderValue,当边界为常数时的边界值,有默认值 morphologyDefaultBorderValueO,一般不用去管它。需要用到它时,可以看官方文档中的 createMorphologyFilterO)函数以得到更详细的解释。

在这里插入图片描述

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;//-----------------------------------【main( )函数】--------------------------------------------
//	描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main()
{//载入原图  Mat srcImage = imread("38.jpg");//显示原图imshow("【原图】腐蚀操作", srcImage);//进行腐蚀操作 Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));Mat dstImage;erode(srcImage, dstImage, element);//显示效果图 imshow("【效果图】腐蚀操作", dstImage);waitKey(0);return 0;
}

在这里插入图片描述
在这里插入图片描述

getStructuringElement() 内核矩阵

返回指定形状和尺寸的结构元素(内核矩阵)

Mat cv::getStructuringElement(int 	shape,Size 	ksize,Point 	anchor = Point(-1,-1) )	
  • 第一个参数表示内核的形状,有如下三种形状可以选择。
    矩形: MORPH RECT、交叉形: MORPH CROSS、椭圆形: MORPH ELLIPSE
  • 第二参数表示内核的尺寸
  • 第三个参数锚点的位置

在这里插入图片描述
在这里插入图片描述

综合示例

#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*);//回调函数
//-----------------------------------【main( )函数】--------------------------------------------
//		描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main()
{//改变console字体颜色system("color 2F");//载入原图g_srcImage = imread("40.jpg");if (!g_srcImage.data) { printf("读取srcImage错误~! \n"); return false; }//显示原始图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();
}

在这里插入图片描述
在这里插入图片描述

形态学滤波进阶morphologyEx()

void cv::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())	
  • 第一个参数,InputArray 类型的 src,输入图像,即源图像,填 Mat 类的对象即可。图像位深应该为以下5种之一:CV_8U、CV_16U、CV_16S、CV_32F和 CV_64F。
  • 第二个参数,OutputAray 类型的 dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
  • 第三个参数,int 类型的 op,表示形态学运算的类型
标识符含义
MORPH_OPEN开运算
MORPH_CLOSE闭运算
MORPH_GRADIENT形态学梯度
MORPH_TOPHAT顶帽
MORPH_BLACKHAT黑帽
MORPH_ERODE腐蚀
MORPH_DILATE膨胀
  • 第四个参数,InputAray 类型的 kemmel,形态学运算的内核。若为 NULL, 表示的是使用参考点位于中心3x3的核。一般使用函数 getStructuringElement 配合这个参数的使用。getStructuringElement 函数会返回指定形状和尺寸的结构元素(内核矩阵)。
  • 第五个参数,Point 类型的 anchor,锚的位置,其有默认值(-1,-1),表示锚位于中心。
  • 第六个参数,int 类型的 iterations,迭代使用函数的次数,默认值为1。
  • 第七个参数,int 类型的 borderType,用于推断图像外部像素的某种边界模式。注意它有默认值 BORDER CONSTANT。
  • 第八个参数,const Scalar& 类型的 borderValue,当边界为常数时的边界值,有默认值 morphologyDefaultBorderValue(),一般不用去管它。需要用到它时,可以看官方文档中的 createMorphologyFilter0函数得到更详细的解释。其中的这些操作都可以进行就地(in-place)操作,且对于多通道图像,每一个通道都单独进行操作。

在这里插入图片描述
在这里插入图片描述

MORPH_DILATE 膨胀操作

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;//-----------------------------------【main( )函数】--------------------------------------------
//		描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main()
{//载入原始图   Mat image = imread("41.jpg");  //工程目录下应该有一张名为1.jpg的素材图//创建窗口   namedWindow("【原始图】膨胀");namedWindow("【效果图】膨胀");//显示原始图  imshow("【原始图】膨胀", image);//定义核Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));//进行形态学操作morphologyEx(image, image, MORPH_DILATE, element);//显示效果图  imshow("【效果图】膨胀", image);waitKey(0);return 0;
}

在这里插入图片描述
在这里插入图片描述

MORPH_ERODE腐蚀操作

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>using namespace cv;int main()
{//载入原始图   Mat image = imread("41.jpg");  //工程目录下应该有一张名为1.jpg的素材图//创建窗口   namedWindow("【原始图】腐蚀");namedWindow("【效果图】腐蚀");//显示原始图  imshow("【原始图】腐蚀", image);//定义核Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));//进行形态学操作morphologyEx(image, image, MORPH_ERODE, element);//显示效果图  imshow("【效果图】腐蚀", image);waitKey(0);return 0;
}

在这里插入图片描述
在这里插入图片描述

MORPH_OPEN 开运算

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{//载入原始图   Mat image = imread("41.jpg");  //工程目录下应该有一张名为1.jpg的素材图//创建窗口   namedWindow("【原始图】开运算");namedWindow("【效果图】开运算");//显示原始图  imshow("【原始图】开运算", image);//定义核Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));//进行形态学操作morphologyEx(image, image, MORPH_OPEN, element);//显示效果图  imshow("【效果图】开运算", image);waitKey(0);return 0;
}

在这里插入图片描述
在这里插入图片描述

MORPH_CLOSE闭运算

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{//载入原始图   Mat image = imread("41.jpg");  //工程目录下应该有一张名为1.jpg的素材图//创建窗口   namedWindow("【原始图】闭运算");namedWindow("【效果图】闭运算");//显示原始图  imshow("【原始图】闭运算", image);//定义核Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));//进行形态学操作morphologyEx(image, image, MORPH_CLOSE, element);//显示效果图  imshow("【效果图】闭运算", image);waitKey(0);return 0;
}

在这里插入图片描述

在这里插入图片描述

MORPH_GRADIENT形态学梯度

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{//载入原始图   Mat image = imread("41.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;
}

在这里插入图片描述

在这里插入图片描述

MORPH_TOPHAT顶帽

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{//载入原始图   Mat image = imread("41.jpg");  //工程目录下应该有一张名为1.jpg的素材图//创建窗口   namedWindow("【原始图】顶帽运算");namedWindow("【效果图】顶帽运算");//显示原始图  imshow("【原始图】顶帽运算", image);//定义核Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));//进行形态学操作morphologyEx(image, image, MORPH_TOPHAT, element);//显示效果图  imshow("【效果图】顶帽运算", image);waitKey(0);return 0;
}

在这里插入图片描述

在这里插入图片描述

MORPH_BLACKHAT黑帽

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{//载入原始图   Mat image = imread("41.jpg");  //工程目录下应该有一张名为1.jpg的素材图//创建窗口   namedWindow("【原始图】黑帽运算");namedWindow("【效果图】黑帽运算");//显示原始图  imshow("【原始图】黑帽运算", image);//定义核Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));//进行形态学操作morphologyEx(image, image, MORPH_BLACKHAT, 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("48.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_ELLIPSEif ((char)c == 49)//键盘按键1的ASII码为49g_nElementShape = MORPH_ELLIPSE;//按下键盘按键2,使用矩形(Rectangle)结构元素MORPH_RECTelse if ((char)c == 50)//键盘按键2的ASII码为50g_nElementShape = MORPH_RECT;//按下键盘按键3,使用十字形(Cross-shaped)结构元素MORPH_CROSSelse if ((char)c == 51)//键盘按键3的ASII码为51g_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);elsedilate(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);elsemorphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);//显示图像imshow("【顶帽/黑帽】", g_dstImage);
}//-----------------------------------【ShowHelpText( )函数】----------------------------------
//		描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{//输出一些帮助信息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");
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

http://www.lryc.cn/news/609162.html

相关文章:

  • 35.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--数据缓存
  • Android 之 RxJava2
  • Kali基础知识点【1】
  • 基于图像识别与分类的中国蛇类识别系统
  • gitee使用教程
  • 电路原理图绘制专业实战教程2
  • 生成式人工智能展望报告-欧盟-04-社会影响与挑战
  • Java中手动床架一个线程池
  • [硬件电路-134]:模拟电路 - 运算放大器常见运算:两模拟信号相加、相减、单模拟信号的积分、微分...
  • template<typename R = void> 意义
  • 【Python练习】075. 编写一个函数,实现简单的语音识别功能
  • golang的包和闭包
  • slice() 和 splice()
  • 决策树模型知识点整理:从原理到实战(含可视化与调参)
  • Corrosion2靶机练习笔记
  • 【图像处理基石】如何使用deepseek进行图像质量的分析?
  • 【Django】-9- 单元测试和集成测试(上)
  • Day23--回溯--39. 组合总和,40. 组合总和 II,131. 分割回文串
  • 机器人抓取流程介绍与实现——机器人抓取系统基础系列(七)
  • 深度学习中卷积与互相关
  • [ java Thread 线程 ] 由“一对一“到“一对多“
  • 【Linux网络编程基础--socket地址API】
  • 使用 Vuepress + GitHub Pages 搭建项目文档
  • GraphRAG:基于知识图谱的检索增强生成技术解析
  • 微分方程模型:用“变化率”的语言,描绘世间万物的动态演化
  • async/await和Promise之间的关系是什么?(补充)
  • 图像识别区分指定物品与其他物体
  • SelectDB数据库,新一代实时数据仓库的全面解析与应用
  • Kubernetes滚动更新、蓝绿部署与金丝雀发布方案对比分析及选型建议
  • 延迟任务方案-DelayQueue