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

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. [LeetCode] 137. 只出现一次的数字,其余三次 II ☆☆☆

    描述 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? 示例 1: 输 ...

  2. JetBrains 系列开发工具 汉化(中文化)教程

    项目地址:(* ̄3 ̄)╭ 操作流程: 拷贝内容 将下载的包改名为resources_cn.jar,拷贝到 $IDEA_HOME$/lib/ 目录下 重启IDEA 打开或者重新启动IDEA

  3. Codeforces Round #519 D - Mysterious Crime

    题目 题意: 在m组数,每组有n个数(数的范围1-n)中,找到某些序列 使它是每组数的一个公共子序列,问这样的某些序列的个数? 思路: 不难想出答案ans是≥n的. 创立一个next数组,使每组中第i ...

  4. 锁、threading.local、线程池

    一.锁 Lock(1次放1个) 什么时候用到锁: 线程安全,多线程操作时,内部会让所有线程排队处理.如:list.dict.queue 线程不安全, import threading import t ...

  5. Ajax的简单例子——PHP

    PHP PHP是一种创建动态交互性站点的服务器端脚本语言 PHP能够生成动态页面内容 PHP能够创建.打开.读取.写入.删除以及关闭服务器上的文件 PHP能够接收表单数据 PHP能够发送并取回cook ...

  6. Vue 获取dom元素中的自定义属性值

    方法一: HTML <div id="app"> <button @click="getData($event,'100')">点我&l ...

  7. BZOJ1209 最佳包裹 (三维凸包 增量法)

    题意 求三维凸包的表面积. N≤100N\le100N≤100 题解 暴力往当前的凸包里加点.O(n2)O(n^2)O(n2).题解详见大佬博客 扰动函数shakeshakeshake是为了避免四点共 ...

  8. 39、扩展原理-BeanFactoryPostProcessor

    39.扩展原理-BeanFactoryPostProcessor BeanPostProcessor:bean后置处理器,bean创建对象初始化前后进行拦截工作的 BeanFactoryPostPro ...

  9. 使用Costura.Fody插件将自己写的程序打包成一个可以独立运行的EXE文件

    我们在开发程序的时候会引用很多DLL文件,在程序完成编写后,如果不把这些引用的DLL打包,不能在其他电脑运行,那么很多同学可能在想了,能不能把我们编写好的程序打包成一个EXE文件,最好双击就能运行,当 ...

  10. How to Fix a Frozen Mac When Updating macOS

    How to Fix a Frozen Mac When Updating macOS By Mike Tee – Posted on Sep 1, 2019 in Mac   While macOS ...