转载请注明出处:http://xiahouzuoxin.github.io/notes


腐蚀与膨胀

腐蚀和膨胀是图像的形态学处理中最主要的操作,之后遇见的开操作和闭操作都是腐蚀和膨胀操作的结合运算。

腐蚀和膨胀的应用非常广泛,并且效果还非常好:

  1. 腐蚀能够切割(isolate)独立的图像元素,膨胀用于连接(join)相邻的元素,这也是腐蚀和膨胀后图像最直观的展现
  2. 去噪:通过低尺寸结构元素的腐蚀操作非常easy去掉分散的椒盐噪声点
  3. 图像轮廓提取:腐蚀操作
  4. 图像切割
  5. 等等...(在文后给出一则简单有用膨胀操作提取车牌数字区域的样例)

结构元素是形态学操作中最重要的概念,

 

如上图,B为结构元素。

腐蚀操作描写叙述为:扫描图像的每个像素,用结构元素与其覆盖的二值图像做“与”操作:假设都为1,结果图像的该像素为1,否则为0。

膨胀操作描写叙述为:扫描图像的每个像素,用结构元素与其覆盖的二值图像做“与”操作:假设都为0,结果图像的该像素为0,否则为1。

以上都是关于二值图像的形态学操作,对于灰度图像:

  1. 腐蚀操作

    当中。g(x,y)为腐蚀后的灰度图像,f(x,y)为原灰度图像。B为结构元素。

    腐蚀运算是由结构元素确定的邻域块中选取图像值与结构元素值的差的最小值。

  2. 膨胀操作

    当中,g(x,y)为腐蚀后的灰度图像,f(x,y)为原灰度图像,B为结构元素。 膨胀运算是由结构元素确定的邻域块中选取图像值与结构元素值的和的最大值。

在灰度图的形态学操作中。一般选择“平摊”的结构元素,即结构元素B的值为0。则上面对灰度图的形态学操作可简化例如以下:

好了,这就是主要的形态学操作——腐蚀和膨胀,以下是使用OpenCV对图像进行腐蚀和膨胀的程序,还是秉承我们一贯的原则:搁下理论,先直观地感觉图像处理算法的效果,实际项目须要时再深入挖掘!

程序分析

/*
* FileName : eroding_and_dilating.cpp
* Author : xiahouzuoxin @163.com
* Version : v1.0
* Date : Fri 19 Sep 2014 07:42:12 PM CST
* Brief :
*
* Copyright (C) MICL,USTB
*/
#include "cv.h"
#include "highgui.h"
#include "opencv2/imgproc/imgproc.hpp" using namespace std;
using namespace cv; #define TYPE_MORPH_RECT (0)
#define TYPE_MORPH_CROSS (1)
#define TYPE_MORPH_ELLIPSE (2) #define MAX_ELE_TYPE (2)
#define MAX_ELE_SIZE (20) Mat src, erode_dst, dilate_dst; const char *erode_wn = "eroding demo";
const char *dilate_wn = "dilating demo"; int erode_ele_type;
int dilate_ele_type;
int erode_ele_size;
int dilate_ele_size; static void Erosion(int, void *);
static void Dilation(int, void *); /*
* @brief
* @inputs
* @outputs
* @retval
*/
int main(int argc, char *argv[])
{
if (argc < 2) {
cout<<"Usage: ./eroding_and_dilating [file name]"<<endl;
return -1;
} src = imread(argv[1]);
if (!src.data) {
cout<<"Read image failure."<<endl;
return -1;
} // Windows
namedWindow(erode_wn, WINDOW_AUTOSIZE);
namedWindow(dilate_wn, WINDOW_AUTOSIZE); // Track Bar for Erosion
createTrackbar("Element Type\n0:Rect\n1:Cross\n2:Ellipse", erode_wn,
&erode_ele_type, MAX_ELE_TYPE, Erosion); // callback @Erosion
createTrackbar("Element Size: 2n+1", erode_wn,
&erode_ele_size, MAX_ELE_SIZE, Erosion); // Track Bar for Dilation
createTrackbar("Element Type\n0:Rect\n1:Cross\n2:Ellipse", dilate_wn,
&dilate_ele_type, MAX_ELE_TYPE, Dilation); // callback @Erosion
createTrackbar("Element Size: 2n+1", dilate_wn,
&dilate_ele_size, MAX_ELE_SIZE, Dilation); // Default start
Erosion(0, 0);
Dilation(0, 0); waitKey(0); return 0;
} /*
* @brief 腐蚀操作的回调函数
* @inputs
* @outputs
* @retval
*/
static void Erosion(int, void *)
{
int erode_type; switch (erode_ele_type) {
case TYPE_MORPH_RECT:
erode_type = MORPH_RECT;
break;
case TYPE_MORPH_CROSS:
erode_type = MORPH_CROSS;
break;
case TYPE_MORPH_ELLIPSE:
erode_type = MORPH_ELLIPSE;
break;
default:
erode_type = MORPH_RECT;
break;
} Mat ele = getStructuringElement(erode_type, Size(2*erode_ele_size+1, 2*erode_ele_size+1),
Point(erode_ele_size, erode_ele_size)); erode(src, erode_dst, ele); imshow(erode_wn, erode_dst);
} /*
* @brief 膨胀操作的回调函数
* @inputs
* @outputs
* @retval
*/
static void Dilation(int, void *)
{
int dilate_type; switch (dilate_ele_type) {
case TYPE_MORPH_RECT:
dilate_type = MORPH_RECT;
break;
case TYPE_MORPH_CROSS:
dilate_type = MORPH_CROSS;
break;
case TYPE_MORPH_ELLIPSE:
dilate_type = MORPH_ELLIPSE;
break;
default:
dilate_type = MORPH_RECT;
break;
} Mat ele = getStructuringElement(dilate_type, Size(2*dilate_ele_size+1, 2*dilate_ele_size+1),
Point(dilate_ele_size, dilate_ele_size)); dilate(src, dilate_dst, ele); imshow(dilate_wn, dilate_dst);
}
  1. 膨胀和腐蚀操作的函数各自是erodedilate,传递给他们的參数也都依次是原图像、形态学操作后的图像、结构元素ele。

    本程序中给出了3种结构元素类型。各自是

    #define TYPE_MORPH_RECT      (0)  // 矩形
    #define TYPE_MORPH_CROSS (1) // 十字交叉型
    #define TYPE_MORPH_ELLIPSE (2) // 椭圆型

    再通过OpenCV提供的getStructuringElement函数创建Mat类型的结构元素。

    getStructuringElement的參数依次是结构元素类型(OpenCV中提供了宏定义MORPH_RECT、MORPH_CROSS和MORPH_ELLIPSE表示)、结构元素大小。

  2. 这里我们首次接触了createTrackbar函数(声明在highgui.hpp中)。该函数的功能是给窗体加入滑动条。其原型是:

    CV_EXPORTS int createTrackbar( const string& trackbarname, const string& winname,
    int* value, int count,
    TrackbarCallback onChange=0,
    void* userdata=0);

    trackbarname为滑动条的名称,将会显示在滑动条的前面。參见结果中的图片显示; winname为窗体名; value为滑动条关联的变量。如上面程序中第一个滑动条关联到erode_ele_type。表示——当滑动条滑动变化时,erode_ele_type的值发生响应的变化; count表示滑动条能滑动到的最大值; TrackbarCallback onChange事实上是这个函数的关键,是滑动条变化时调用的回调函数。当滑动条滑动时,value值发生变化,系统立马调用onChange函数,运行相关的操作,回调函数的定义形式是固定的:

    void onChange(int, void *)

    程序中的回调函数ErosionDilation函数的定义都遵循该形式:

    static void Erosion(int, void *);
    static void Dilation(int, void *);

结果及实际应用

对“黑白小猪”进行膨胀操作的变化(随着结构元素大小的变化)例如以下图:

对“黑白小猪”进行腐蚀操作的变化(随着结构元素大小的变化)例如以下图:

膨胀与腐蚀在图像处理中具有广泛的用途,比方提取车牌过程中,能够通过膨胀运算确定车牌的区域。例如以下图为通过sobel算子提取边缘后的车牌,

为去掉边界,确定车牌在图中的位置。能够通过膨胀操作。结果例如以下:

上图中的红线区域就是膨胀后能用于确定车牌的连通区域,再通过对连通区域的搜索及“车牌的矩形特性”就可以确定含有车牌数字在图片中的位置。

OpenCV图像处理篇之腐蚀与膨胀的更多相关文章

  1. OpenCV图像处理篇之边缘检测算子

    OpenCV图像处理篇之边缘检测算子 转载: http://xiahouzuoxin.github.io/notes/ 3种边缘检测算子 一阶导数的梯度算子 高斯拉普拉斯算子 Canny算子 Open ...

  2. opencv —— erode、dilate 腐蚀与膨胀

    腐蚀与膨胀是形态学滤波.其中,腐蚀是最小值滤波,膨胀是最大值滤波,即分别选取内核中的最小值与最大值赋值给锚点.若内核为 N×1 或 1×N 形状,可用于横纵方向直线检测. 膨胀:dilate 函数 v ...

  3. opencv:形态学操作-腐蚀与膨胀

    #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...

  4. OpenCV图像处理篇之阈值操作函数

    阈值操作类型 这5种阈值操作类型保留opencv tutorials中的英文名称.依次为: Threshold Binary:即二值化,将大于阈值的灰度值设为最大灰度值.小于阈值的值设为0. Thre ...

  5. OpenCV图像处理篇之图像平滑

    图像平滑算法 图像平滑与图像模糊是同一概念,主要用于图像的去噪.平滑要使用滤波器.为不改变图像的相位信息,一般使用线性滤波器,其统一形式例如以下: %20\Large%20g(i,j)=\sum_{k ...

  6. OpenCV图像处理篇之边缘检測算子

    3种边缘检測算子 灰度或结构等信息的突变位置是图像的边缘,图像的边缘有幅度和方向属性.沿边缘方向像素变化缓慢,垂直边缘方向像素变化剧烈.因此,边缘上的变化能通过梯度计算出来. 一阶导数的梯度算子 对于 ...

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

    腐蚀与膨胀 膨胀(求局部最大值)(dilate函数) #include <opencv2/core/core.hpp> #include <opencv2/highgui/highg ...

  8. 学习 opencv---(9)形态学图像处理(一):膨胀和腐蚀

    本篇文章中,我们一起探究了图像处理中,最基本的形态学运算--膨胀与腐蚀.浅墨在文章开头友情提醒,用人物照片做腐蚀和膨胀的素材图片得到的效果会比较惊悚,毁三观的,不建议尝试.......... 一.理论 ...

  9. Python图像处理丨图像腐蚀与图像膨胀

    摘要:本篇文章主要讲解Python调用OpenCV实现图像腐蚀和图像膨胀的算法. 本文分享自华为云社区<[Python图像处理] 八.图像腐蚀与图像膨胀>,作者: eastmount . ...

随机推荐

  1. 6、DRN-----深度强化学习在新闻推荐上的应用

    1.摘要: 提出了一种新的深度强化学习框架的新闻推荐.由于新闻特征和用户喜好的动态特性,在线个性化新闻推荐是一个极具挑战性的问题. 虽然已经提出了一些在线推荐模型来解决新闻推荐的动态特性,但是这些方法 ...

  2. UVA-12186 Another Crisis 树形dp

    题目链接:https://cn.vjudge.net/problem/UVA-12186 题意 给出n, T和一棵树,树上每个节点需要选择T%个直属子节点. 问根节点一共需要选择几个节点. 思路 思路 ...

  3. execlp(3) - Linux手册

    名称: execl, execlp, execle, execv, execvp, execvpe:执行文件 总览: #include <unistd.h> extern char **e ...

  4. Unity Microphone 无限时长录制

    原创文章:转载请标明出处--博客园 Jason_c Unity可以很方便的通过 Microphone.Start()方法来调用麦克风,但是有一个弊端是,必须传入时长,这就很尴尬了,因为大多数时间,我们 ...

  5. 程序员之---C语言细节12(指针和数组细节,&quot;//&quot;的可移植性说明)

    主要内容:指针和数组细节,"//"的可移植性说明 #include <stdio.h> int main(int argc, char **argv) { int a[ ...

  6. 4、java变量、函数、基本类型的值传递、分支、循环、流程控制

    一.全局变量(global).局部变量(local).动态变量(dynamic).静态变量(static) 在类中的变量为全局变量,在方法函数中为局部变量,局部变量必须有人为赋的初值,全局变量的初值是 ...

  7. nyoj--311--完全背包(动态规划,完全背包)

    完全背包 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 直接说题意,完全背包定义有N种物品和一个容量为V的背包,每种物品都有无限件可用.第i种物品的体积是c,价值是w. ...

  8. rest_framework 认证功能

    from django.views import View from rest_framework.views import APIView from rest_framework.authentic ...

  9. Redis的好处知识

    参考文章 http://www.cnblogs.com/wupeiqi/articles/5132791.html 使用Redis有哪些好处? () 速度快,因为数据存在内存中,类似于HashMap, ...

  10. springboot actuator shutdown正确的关闭操作

    今天整合ehcache时发现一个很重要的问题,就是程序关闭(硬关闭)之后,持久化到磁盘的缓存数据没能正确写入加载,问题还是硬关闭的问题,所以就使用actuator 进行监听 <dependenc ...