看上面的源码可以发现,其实函数其实就是内部一个大而已 。根据不同的标识符取不同的操作 。(对于,看小嗷文章各位,代码简单)
比如开运算,按我们上文中讲解的数学表达式,就是先腐蚀后膨胀,即依次调用erode和函数,为非常简明干净的代码 。
3.3 函数运用示例
void usage_high_level_erode_dilate(char* which){Matimage = imread("./smimage/1.jpg");Matele = getStructuringElement(MORPH_RECT, Size(5, 5));Matres;//which//open close gradient tophat blackhat//o c g t bswitch (which[0]){case 'o':morphologyEx(image, res, MORPH_OPEN, ele);break;case 'c':morphologyEx(image, res, MORPH_CLOSE, ele);break;case 'g':morphologyEx(image, res, MORPH_GRADIENT, ele);break;case 't':morphologyEx(image, res, MORPH_TOPHAT, ele);break;case 'b':morphologyEx(image, res, MORPH_BLACKHAT, ele);break;}//show the imageimshow("SRC", image);imshow(which, res);waitKey(0);}
任务:
简单调用API函数就OK(估计以后实战中,经常使用形态学图像处理问题)
代码如下:
/*功能:综合示例——形态学滤波一共包含11中操作:腐蚀、膨胀、开运算、闭运算、顶帽、黑帽形态学梯度(又为基本梯度)、内部梯度、外部梯度、X方向梯度、Y方向梯度*/#include #include #include #include using namespace cv;using namespace std;#define WINDOWNAME "【形态学滤波-效果图】"//-------------------【全局变量声明部分】------------------------Mat g_srcImage; //源图像Mat g_dstImage; //得到的效果图int g_nElementShape = MORPH_RECT;//元素结构的形状int g_nStructElementSize = 3;//结构元素(内核矩阵)的尺寸int g_nMaxNum = 21; //内核最大值int g_nTypeChoice = 0; //形态学操作类型选择//-------------------【全局函数声明部分】------------------------void on_TrackbarNumChange(int, void*); //类型选择-回调函数void on_ElementSizeChange(int, void*); //内核大小变换-回调函数void ShowHelpText();//帮助文字显示void Process(); //对应的形态学操作void ErodeProcess();//腐蚀操作void DilateProcess();//膨胀操作void OpenProcess(); //开运算操作void CloseProcess();//闭运算操作void TopHatProcess();//顶帽操作void BlackHatProcess(); //黑帽操作void GradienteProcess();//形态学梯度操作-即基本梯度void InternalGradientProcess(); //内部梯度操作void ExternalGradientProcess(); //外部操作void xDirectGradientProcess();//X方向梯度操作void yDirectGradientProcess();//Y方向梯度操作//--------------------------------【主函数】------------------------------int main(){//载入图像g_srcImage = imread("D:/8.jpg");if (!g_srcImage.data){cout << "读取图片错误,请重新输入正确路径!\n";system("pause");return -1;}namedWindow("【原始图】", WINDOW_AUTOSIZE);namedWindow(WINDOWNAME, WINDOW_AUTOSIZE);imshow("【原始图】", g_srcImage);//显示原始图ShowHelpText();//创建轨迹条createTrackbar("类型选择", WINDOWNAME, &g_nTypeChoice, 10, on_TrackbarNumChange);createTrackbar("内核", WINDOWNAME, &g_nStructElementSize, g_nMaxNum, on_ElementSizeChange);//轮询获取按键信息while (1){//执行回调函数on_TrackbarNumChange(g_nTypeChoice, 0);on_ElementSizeChange(g_nStructElementSize, 0);//获取按键int c;c = waitKey(0);//按下键盘Q键或者ESC,程序退出if ((char)c == 'q' || (char)c == 27 || (char)c == 'Q')break;//按下键盘按键1,使用矩形(Rectangle)结构元素MORPH_RECTif ((char)c == 49)//键盘按键1的ASII码为49g_nElementShape = MORPH_RECT;//按下键盘按键2,使用十字形(Cross)结构元素MORPH_CROSSelse if ((char)c == 50)//键盘按键2的ASII码为50g_nElementShape = MORPH_CROSS;//按下键盘按键3,使用椭圆(Elliptic)结构元素MORPH_ELLIPSEelse if ((char)c == 51)//键盘按键3的ASII码为51g_nElementShape = MORPH_ELLIPSE;}return 0;}//------------【on_TrackbarNumChange()函数】-------------void on_TrackbarNumChange(int, void*){//类型之间效果已经切换,回调函数体内需调用一次对应的操作函数,使改变后的效果立即生效并显示出来Process();}//------------【on_ElementSizeChange()函数】--------------void on_ElementSizeChange(int, void*){//内核尺寸已改变,回调函数体内需调用一次Process函数,使改变后的效果立即生效并显示出来Process();}//------------【进行对应的形态学操作】--------------void Process(){switch (g_nTypeChoice){case 0:ErodeProcess(); break;case 1:DilateProcess(); break;case 2:OpenProcess(); break;case 3:CloseProcess(); break;case 4:TopHatProcess(); break;case 5:BlackHatProcess(); break;case 6:GradienteProcess(); break;case 7:InternalGradientProcess(); break;case 8:ExternalGradientProcess(); break;case 9:xDirectGradientProcess(); break;case 10:yDirectGradientProcess(); break;}}//-----------【描述:进行腐蚀操作】-----------void ErodeProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1)); //获取自定义核erode(g_srcImage, g_dstImage, element); //进行腐蚀或膨胀操作imshow(WINDOWNAME, g_dstImage); //显示效果图}//-----------【描述:进行膨胀操作】-----------void DilateProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1));//获取自定义核dilate(g_srcImage, g_dstImage, element);//进行膨胀操作imshow(WINDOWNAME, g_dstImage); //显示效果图}//-----------【描述:进行开运算操作】-----------void OpenProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1)); //获取自定义核morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);//进行开运算操作:先腐蚀后膨胀imshow(WINDOWNAME, g_dstImage); //显示效果图}//-----------【描述:进行闭运算操作】-----------void CloseProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1));//获取自定义核morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);//进行闭运算操作:先膨胀再腐蚀imshow(WINDOWNAME, g_dstImage); //显示效果图}//-----------【描述:进行顶帽操作】-----------void TopHatProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1)); //获取自定义核morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);//进行顶帽操作:原图像与开运算结果图之差imshow(WINDOWNAME, g_dstImage); //显示效果图}//-----------【描述:进行黑帽操作】-----------void BlackHatProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1)); //获取自定义核morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);//进行黑帽操作:闭运算结果图与原图像之差imshow(WINDOWNAME, g_dstImage); //显示效果图}//-----------【描述:进行形态学梯度操作】-----------void GradienteProcess(){Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1)); //获取自定义核morphologyEx(g_srcImage, g_dstImage, MORPH_GRADIENT, element);//进行形态学梯度操作:膨胀图像与腐蚀图像的之差imshow(WINDOWNAME, g_dstImage); //显示效果图}//-----------【描述:进行内部梯度操作】-----------void InternalGradientProcess(){Mat erode_ouput;Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1)); //获取自定义核morphologyEx(g_srcImage, erode_ouput, MORPH_ERODE, element);//进行腐蚀操作subtract(g_srcImage, erode_ouput, g_dstImage, Mat());//计算内部梯度:原图像减去腐蚀之后的图像imshow(WINDOWNAME, g_dstImage); //显示效果图}//-----------【描述:进行外部梯度操作】-----------void ExternalGradientProcess(){Mat dilate_output;Mat element = getStructuringElement(g_nElementShape, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1)); //获取自定义核morphologyEx(g_srcImage, dilate_output, MORPH_DILATE, element);//进行膨胀操作subtract(dilate_output, g_srcImage, g_dstImage, Mat());//计算外部梯度:膨胀后的图像减去原图像imshow(WINDOWNAME, g_dstImage); //显示效果图}//-----------【描述:进行X方向梯度操作】-----------void xDirectGradientProcess(){if (g_nStructElementSize == 0){imshow(WINDOWNAME, g_srcImage); //显示原图}else{Mat hse = getStructuringElement(g_nElementShape, Size(g_srcImage.cols / g_nStructElementSize, 1));Mat erode_direct, dilate_direct;erode(g_srcImage, erode_direct, hse);dilate(g_srcImage, dilate_direct, hse);subtract(dilate_direct, erode_direct, g_dstImage, Mat()); // X 方向梯度:膨胀与腐蚀之后得到图像求差值imshow(WINDOWNAME, g_dstImage); //显示效果图}}//-----------【描述:进行Y方向梯度操作】-----------void yDirectGradientProcess(){if (g_nStructElementSize == 0){imshow(WINDOWNAME, g_srcImage); //显示原图}else{Mat vse = getStructuringElement(g_nElementShape, Size(1, g_srcImage.rows / g_nStructElementSize));Mat erode_direct, dilate_direct;erode(g_srcImage, erode_direct, vse);dilate(g_srcImage, dilate_direct, vse);subtract(dilate_direct, erode_direct, g_dstImage, Mat()); // Y 方向梯度:膨胀与腐蚀之后得到图像求差值imshow(WINDOWNAME, g_dstImage); //显示效果图}}//------------------【程序一些提示操作信息】-----------------void ShowHelpText(){cout