通过阈值化分割可以得到二值图,但往往会出现图像中物体形态不完整,变的残缺,可以通过形态学处理,使其变得丰满,或者去除掉多余的像素。常用的形态学处理算法包括:腐蚀,膨胀,开运算,闭运算,形态学梯度,顶帽运算和底帽运算。

1. 腐蚀

   腐蚀操作类似于中值平滑,也有一个核,但不进行卷积运算,而是取核中像素值的最小值代替锚点位置的像素值,这样就会使图像中较暗的区域面积增大,较亮的的区域面积减小。如果是一张黑底,白色前景的二值图,就会使白色的前景物体颜色变小,就像被腐蚀了一样。

   进行腐蚀操作的核,不仅可以是矩形,还可以是十字形和椭圆形,opencv提供getStructuringElement()函数来获得核,其参数如下:

kernel=cv2.getStructuringElement(shape,ksize,anchor)
shape:核的形状
cv2.MORPH_RECT: 矩形
cv2.MORPH_CROSS: 十字形(以矩形的锚点为中心的十字架)
cv2.MORPH_ELLIPSE:椭圆(矩形的内切椭圆) ksize: 核的大小,矩形的宽,高格式为(width,height)
anchor: 核的锚点,默认值为(-,-),即核的中心点

   opencv提供erode()函数进行腐蚀操作,其对应参数如下:

dst=cv2.erode(src,kernel,anchor,iterations,borderType,borderValue):
src: 输入图像对象矩阵,为二值化图像
kernel:进行腐蚀操作的核,可以通过函数getStructuringElement()获得
anchor:锚点,默认为(-,-)
iterations:腐蚀操作的次数,默认为1
borderType: 边界种类,有默认值
borderValue:边界值,有默认值

   腐蚀操作的代码和效果如下:

   可以看到二值化图像中白色的opencv字体面积变小了,就像被腐蚀了。注意这是黑底白字,如果是白底黑字,效果会相反,字体反而会膨胀。

#coding:utf-

import cv2 as cv

img = cv.imread(r"C:\Users\Administrator\Desktop\logo.png")
img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,img_thr = cv.threshold(img_cvt,,,cv.THRESH_BINARY_INV)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(,))
dst = cv.erode(img_thr,kernel,iterations=) cv.imshow("img",img)
cv.imshow("img_thr",img_thr)
cv.imshow("dst",dst)
cv.waitKey()
cv.destroyAllWindows()

cv2.erode()

2.膨胀

  膨胀操作和腐蚀操作正好相反,是取核中像素值的最大值代替锚点位置的像素值,这样会使图像中较亮的区域增大,较暗的区域减小。如果是一张黑底,白色前景的二值图,就会使白色的前景物体颜色面积变大,就像膨胀了一样

    opencv提供dilate()函数进行膨胀操作,其对应参数如下:

dst = cv2.dilate(src,kernel,anchor,iterations,borderType,borderValue)
src: 输入图像对象矩阵,为二值化图像
kernel:进行腐蚀操作的核,可以通过函数getStructuringElement()获得
anchor:锚点,默认为(-,-)
iterations:腐蚀操作的次数,默认为1
borderType: 边界种类
borderValue:边界值

    膨胀操作的代码和效果如下:

    可以看到二值化图像中白色的opencv字体面积变大了,就像膨胀了

#coding:utf-

import cv2 as cv

img = cv.imread(r"C:\Users\Administrator\Desktop\logo.png")
img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,img_thr = cv.threshold(img_cvt,,,cv.THRESH_BINARY_INV)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(,))
dst = cv.dilate(img_thr,kernel,iterations=) cv.imshow("img",img)
cv.imshow("img_thr",img_thr)
cv.imshow("dst",dst)
cv.waitKey()
cv.destroyAllWindows()

cv2.dilate()

3.开运算,闭运算,顶帽,顶帽

  开运算:先进行腐蚀操作,后进行膨胀操作,主要用来去除一些较亮的部分,即先腐蚀掉不要的部分,再进行膨胀。

  闭运算:先进行膨胀操作,后进行腐蚀操作,主要用来去除一些较暗的部分。

  形态学梯度:膨胀运算结果减去腐蚀运算结果,可以拿到轮廓信息。

  顶帽运算:原图像减去开运算结果。

  底帽运算:原图像减去闭运算结果。  

  进行开运算,闭运算,顶帽运算,底帽运算,形态学梯度,opencv提供了一个统一的函数cv2.morphologyEx(),其对应参数如下:

dst = cv2.morphologyEx(src,op,kernel,anchor,iterations,borderType,borderValue)
src: 输入图像对象矩阵,为二值化图像
op: 形态学操作类型
cv2.MORPH_OPEN 开运算
cv2.MORPH_CLOSE 闭运算
cv2.MORPH_GRADIENT 形态梯度
cv2.MORPH_TOPHAT 顶帽运算
cv2.MORPH_BLACKHAT 底帽运算 kernel:进行腐蚀操作的核,可以通过函数getStructuringElement()获得
anchor:锚点,默认为(-,-)
iterations:腐蚀操作的次数,默认为1
borderType: 边界种类
borderValue:边界值

  使用代码和对应效果如下:

#coding:utf-

import cv2 as cv
import matplotlib.pyplot as plt img = cv.imread(r"C:\Users\Administrator\Desktop\logo.png")
img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,img_thr = cv.threshold(img_cvt,,,cv.THRESH_BINARY_INV)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(,))
open = cv.morphologyEx(img_thr,cv.MORPH_OPEN,kernel,iterations=)
close = cv.morphologyEx(img_thr,cv.MORPH_CLOSE,kernel,iterations=)
gradient = cv.morphologyEx(img_thr,cv.MORPH_GRADIENT,kernel,iterations=)
tophat = cv.morphologyEx(img_thr,cv.MORPH_TOPHAT,kernel,iterations=)
blackhat = cv.morphologyEx(img_thr,cv.MORPH_BLACKHAT,kernel,iterations=) images=[img_thr,open,close,gradient,tophat,blackhat]
titles=["img_thr","open","close","gradient","tophat","blackhat"]
for i in range():
plt.subplot(,,i+),plt.imshow(images[i],"gray")
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()

cv2.morphologyEx()

 

4.应用实例

  有如下一张中文图片,当我们进行字符切割时,常需要知道其中的汉字是否带下划线,方便进行后续处理。

  我们首先想到的可能是使用霍夫直线检测算法,但是直接检测时,会有很多干扰。我们可以通过采用一个横向的矩阵核,来腐蚀字体,使图片中只剩下下划线,然后再进行霍夫直线检测,这样干扰小,准确度会高很多。具体实现代码和效果如下:

#coding:utf-

import cv2 as cv

img = cv.imread(r"C:\Users\Administrator\Desktop\chinese.png")
img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,img_thr = cv.threshold(img_cvt,,,cv.THRESH_BINARY)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(,)) #由于是1*30的矩阵,字体会被横向空隙的白色腐蚀掉,而下划线横向都是黑色,不会腐蚀
dst = cv.dilate(img_thr,kernel,iterations=) #由于是白底黑字,所有进行膨胀操作来去除黑色字体
cv.imshow("img_thr",img_thr)
cv.imshow("dst",dst)
cv.waitKey()
cv.destroyAllWindows()

  

(四)OpenCV-Python学习—形态学处理的更多相关文章

  1. 四、python学习-正则表达式

    正则表达式 import re lst = re.findall(正则表达式,需要匹配的字符串) findall 把所有匹配到的字符串都搜出来,返回列表 不能把分组内容和匹配内容同时显示出来 sear ...

  2. OpenCV之Python学习笔记

    OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书< ...

  3. python学习心得第四章

     python 学习心得第四章 1.lambda表达式 1:什么是lambda表达式 为了简化简单函数的代码,选择使用lambda表达式 上面两个函数的表达式虽然不一样,但是本质是一样的,并且lamb ...

  4. Python之路【第二十四篇】:Python学习路径及练手项目合集

      Python学习路径及练手项目合集 Wayne Shi· 2 个月前 参照:https://zhuanlan.zhihu.com/p/23561159 更多文章欢迎关注专栏:学习编程. 本系列Py ...

  5. python学习笔记--Django入门四 管理站点--二

    接上一节  python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...

  6. [Python学习笔记][第四章Python字符串]

    2016/1/28学习内容 第四章 Python字符串与正则表达式之字符串 编码规则 UTF-8 以1个字节表示英语字符(兼容ASCII),以3个字节表示中文及其他语言,UTF-8对全世界所有国家需要 ...

  7. Python学习笔记(十四)

    Python学习笔记(十四): Json and Pickle模块 shelve模块 1. Json and Pickle模块 之前我们学习过用eval内置方法可以将一个字符串转成python对象,不 ...

  8. Python学习笔记(四)

    Python学习笔记(四) 作业讲解 编码和解码 1. 作业讲解 重复代码瘦身 # 定义地图 nav = {'省略'} # 现在所处的层 current_layer = nav # 记录你去过的地方 ...

  9. python学习之路网络编程篇(第四篇)

    python学习之路网络编程篇(第四篇) 内容待补充

  10. python学习第四讲,python基础语法之判断语句,循环语句

    目录 python学习第四讲,python基础语法之判断语句,选择语句,循环语句 一丶判断语句 if 1.if 语法 2. if else 语法 3. if 进阶 if elif else 二丶运算符 ...

随机推荐

  1. 从零开始搭建vue移动端项目到上线

    先来看一波效果图 初始化项目 1.在安装了node.js的前提下,使用以下命令 npm install --g vue-cli 2.在将要构建项目的目录下 vue init webpack mypro ...

  2. 后台对象转JSON字符串传到前台,前台JSON字符串转对象绑定标签赋值

    /// <summary> /// 创建换货单-自动获取对应的数据(后端) /// </summary> [HttpGet] public ActionResult GetPr ...

  3. Mysql语句练习记录

    使用的sql图形软件:SQLyogEnt 使用的数据库:MYSQL5.7 软件地址: 链接:https://pan.baidu.com/s/1lajyXaSnmrO1v5v987NOoA 提取码:i3 ...

  4. python中read()、readline()、readlines()区别

    1.read([size])方法 read([size])方法从文件当前位置读取size个字节,若无参数size,则表示读取至文件结束位置,它范围为字符串对象   2.readline()方法 从字面 ...

  5. JAVA 多线程(一)

    进程和线程 进程:是一个正在执行中的程序.每一个进程执行都有一个执行顺序,该执行顺序是一个执行路径,或者叫一个控制单元. 线程:就是进程中的一个独立的控制单元. 线程在控制着进程的执行. 在计算机中多 ...

  6. Sql Server 2017 安装问题记录

    记录了我在虚拟机中安装Sql server 2017遇到的一些问题. 安装环境: Sql server 2017 + Windows Server 2012 R2 提供两个网上的下载链接: https ...

  7. python 多分类任务中按照类别分层采样

    在机器学习多分类任务中有时候需要针对类别进行分层采样,比如说类别不均衡的数据,这时候随机采样会造成训练集.验证集.测试集中不同类别的数据比例不一样,这是会在一定程度上影响分类器的性能的,这时候就需要进 ...

  8. springMvc--接受请求参数

    作者:liuconglin 接收基本类型 表单: <h1>接受基本类型参数到Controller</h1> <form action="/param/test& ...

  9. concat以及group_concat的用法

    concat()函数 1.功能:将多个字符串连接成一个字符串. 2.语法:concat(str1, str2,...) 返回结果为连接参数产生的字符串,如果有任何一个参数为null,则返回值为null ...

  10. javascript权威指南第11章 DOM扩展

    //javascript 权威指南 第三版 第11章 DOM扩展 //取得body元素 var body = document.querySelector("body"); //取 ...