原理:

形态学运算是结构元素与图像进行逻辑运算,产生新的图像的图像处理方法。二值图像B和结构元素S是定义在笛卡儿网格上的集合,网格中值为1的点是集合的元素。

  1. 腐蚀
    定义:

    算法:
    a) 用3x3的结构元素,扫描图像的每一个像素。
    b) 用结构元素与其覆盖的二值图像做“与”操作。
    c) 如果都为1,结果图像的该像素为1,否则为0。

  2. 膨胀
    定义:

    算法:
    a) 用3x3的结构元素,扫描图像的每一个像素。
    b) 用结构元素与其覆盖的二值图像做“与”操作。
    c) 如果都为0,结果图像的该像素为0,否则为1。

  3. 开运算

    定义: 即先腐蚀,再膨胀。
    算法:
    a) 用3x3的结构元素,对图像做腐蚀操作。
    b) 再用3x3的结构元素,对图像做膨胀操作。

  4. 闭运算

    定义: 即先膨胀,再腐蚀。
    算法:
    a) 用3x3的结构元素,对图像做膨胀操作。
    b) 再用3x3的结构元素,对图像做腐蚀操作。

代码以及算法设计:

一、首先使用OSTU算法进行计算最适合的阈值,ostu算法的原理如下:

  1. 先计算图像的直方图,即将图像所有的像素点按照0~255共256个bin,统计落在每个bin的像素点数量
  2. 归一化直方图,也即将每个bin中像素点数量除以总的像素点
  3. i表示分类的阈值,也即一个灰度级,从0开始迭代
  4. 通过归一化的直方图,统计0~i 灰度级的像素(假设像素值在此范围的像素叫做前景像素) 所占整幅图像的比例w0,并统计前景像素的平均灰度u0;统计i~255灰度级的像素(假设像素值在此范围的像素叫做背景像素) 所占整幅图像的比例w1,并统计背景像素的平均灰度u1;
  5. 计算前景像素和背景像素的方差 g = w0w1(u0-u1) (u0-u1)
  6. i++;转到 4 ,直到i为256时结束迭代
  7. 将最大g相应的i值作为图像的全局阈值
#使用otsu算法思维求出阈值并对图像进行二值化处理
def myotsu(gray):countdown = 0countup = 0hist_new = []num = []hist_countresult = []hist_key = []hist_proresult = []#处理后最终输出矩阵将齐大小设置为与原图一样gray2=np.array([[0 for i in range(gray.shape[1])] for i in range(gray.shape[0])], dtype='float') #gray1 用于统计每哥灰度级所有的个数 ,因为是列表不是矩阵,#所以要先将gray的灰度级矩阵变成一维列表gray1 = list(gray.ravel())#以字典的形式保存,统计出来的灰度级及其个数obj = dict(collections.Counter(gray1))obj = sorted(obj.items(),key=lambda item:item[0])#将统计出来的灰度级的值与他的个数分开用列表保存for each in obj :key = list(each)[0]num =list(each)[1]hist_key.append(key)hist_new.append(num)#检查从0-255每个灰度级是否都有个数,没有的话添加并将值设为0for i in range (0,256) :if i in hist_key :num = hist_key.index(i)hist_countresult.append(hist_new[num])else :hist_countresult.append(0)if len(hist_countresult) < 256 :for i in range (0,256-len(hist_countresult)) :hist_new.append(0)#计算整幅图的像素数目hist_sum = gray.shape[0] * gray.shape[1]#计算每个灰度级的像素数目占整个数目的比重for each in hist_countresult :result = float(each / hist_sum)hist_proresult.append(result)#遍历灰度级[0,255],寻找合适的thresholdw0 = w1 = u0tmp = u1tmp = u0 = u1 = deltaTmp = deltaMax = float(0)for i in range (256) :w0 = w1 = u0tmp = u1tmp = u0 = u1 = deltaTmp = float(0)for j in range (256) :if j <= i : #背景部分w0 = float(w0 + hist_proresult[j])u0tmp += j * hist_proresult[j]else :  #前景部分w1 += float(hist_proresult[j])u1tmp += j * hist_proresult[j]if w0 == 0.0 or w1 == 0.0:passelse :u0 = float(u0tmp / w0)u1 = float(u1tmp / w1)deltaTmp = (float)(w0 *w1* pow((u0 - u1), 2)) if deltaTmp > deltaMax : deltaMax = deltaTmpthreshold = i#用ostu大津算法得出最适当的阈值后,将图片进行二值化for i in range(gray.shape[0]) :for j in range(gray.shape[1]) :#对大于阈值的显示为255白色,小于阈值的显示为0黑色if gray[i][j] <= threshold :gray2[i][j] = 0countdown += 1else :gray2[i][j] = 255countup += 1return gray2

二、使用numpy模块的函数生成一个3 * 3 的矩阵

三、腐蚀:

  • a) 用3x3的结构元素,扫描图像的每一个像素。
  • b) 用结构元素与其覆盖的二值图像做“与”操作。
  • c) 如果都为1,结果图像的该像素为1,否则为0。
#腐蚀
def corrode(twovalue_img) :#处理后最终输出矩阵将齐大小设置为与原图一样gray2=np.array([[0 for i in range(twovalue_img.shape[1])] for i in range(twovalue_img.shape[0])], dtype='float') #生成 3*3的结构元素structuralelement = np.array([[1 for i in range (3)]for i in range (3)],dtype='int')#使用结构元素去与原二值图像中为1的值进行与操作for i in range (1,twovalue_img.shape[0]-1) :for j in range (1,twovalue_img.shape[1]-1) :#添加每次处理后的元素到集合中list1 = []count1 = 0 #保存进行于操作后图中到底有几个1list1.append(twovalue_img[i-1][j-1] and structuralelement[0][0])list1.append(twovalue_img[i-1][j] and structuralelement[0][1])list1.append(twovalue_img[i-1][j+1] and structuralelement[0][2])list1.append(twovalue_img[i][j-1] and structuralelement[1][0])list1.append(twovalue_img[i][j] and structuralelement[1][1])list1.append(twovalue_img[i][j+1] and structuralelement[1][2])list1.append(twovalue_img[i+1][j-1] and structuralelement[2][0])list1.append(twovalue_img[i+1][j] and structuralelement[2][1])list1.append(twovalue_img[i+1][j+1] and structuralelement[2][2])#如果都为1,结果图像的该像素为1,否则为0。for each in list1 :if each == 1 :count1 += 1if count1 == 9 :gray2[i][j] = 255else :gray2[i][j] = 0        return gray2

四、膨胀:

  • a) 用3x3的结构元素,扫描图像的每一个像素。
  • b) 用结构元素与其覆盖的二值图像做“与”操作。
  • c) 如果都为0,结果图像的该像素为0,否则为1。
#膨胀
def swell(twovalue_img):#处理后最终输出矩阵将齐大小设置为与原图一样gray2=np.array([[0 for i in range(twovalue_img.shape[1])] for i in range(twovalue_img.shape[0])], dtype='float') #生成 3*3的结构元素structuralelement = np.array([[1 for i in range (3)]for i in range (3)],dtype='int')#使用结构元素去与原二值图像中为1的值进行与操作for i in range (1,twovalue_img.shape[0]-1) :for j in range (1,twovalue_img.shape[1]-1) :#添加每次处理后的元素到集合中list1 = []count1 = 0 #保存进行于操作后图中到底有几个1list1.append(twovalue_img[i-1][j-1] and structuralelement[0][0])list1.append(twovalue_img[i-1][j] and structuralelement[0][1])list1.append(twovalue_img[i-1][j+1] and structuralelement[0][2])list1.append(twovalue_img[i][j-1] and structuralelement[1][0])list1.append(twovalue_img[i][j] and structuralelement[1][1])list1.append(twovalue_img[i][j+1] and structuralelement[1][2])list1.append(twovalue_img[i+1][j-1] and structuralelement[2][0])list1.append(twovalue_img[i+1][j] and structuralelement[2][1])list1.append(twovalue_img[i+1][j+1] and structuralelement[2][2])#如果都为0,结果图像的该像素为0,否则为1。for each in list1 :if each == 1 :count1 += 1if count1 > 0 :gray2[i][j] = 255else :gray2[i][j] = 0        return gray2

五、开运算:先腐蚀,后膨胀(直接调用两次函数即可)

  • a) 用3x3的结构元素,对图像做腐蚀操作。
  • b) 再用3x3的结构元素,对图像做膨胀操作。
#开运算
def opencalc(twovalue_img) :#先腐蚀,再膨胀corrode_pic = corrode(twovalue_img)open_img = swell(corrode_pic)return open_img

六、闭运算:先膨胀,后腐蚀(直接调用两次函数即可)

  • a) 用3x3的结构元素,对图像做膨胀操作。
  • b) 再用3x3的结构元素,对图像做腐蚀操作。
#闭运算
def closecalc(twovalue_img) :#先膨胀,再腐蚀swell_pic = swell(twovalue_img)close_img = corrode(swell_pic)return close_img

完整代码:

import matplotlib.pyplot as plt
from scipy import signal
import numpy as np
import copy as cp
import random
import math
import cv2
import collections#使用otsu算法思维求出阈值并对图像进行二值化处理
def myotsu(gray):countdown = 0countup = 0hist_new = []num = []hist_countresult = []hist_key = []hist_proresult = []#处理后最终输出矩阵将齐大小设置为与原图一样gray2=np.array([[0 for i in range(gray.shape[1])] for i in range(gray.shape[0])], dtype='float') #gray1 用于统计每哥灰度级所有的个数 ,因为是列表不是矩阵,#所以要先将gray的灰度级矩阵变成一维列表gray1 = list(gray.ravel())#以字典的形式保存,统计出来的灰度级及其个数obj = dict(collections.Counter(gray1))obj = sorted(obj.items(),key=lambda item:item[0])#将统计出来的灰度级的值与他的个数分开用列表保存for each in obj :key = list(each)[0]num =list(each)[1]hist_key.append(key)hist_new.append(num)#检查从0-255每个灰度级是否都有个数,没有的话添加并将值设为0for i in range (0,256) :if i in hist_key :num = hist_key.index(i)hist_countresult.append(hist_new[num])else :hist_countresult.append(0)if len(hist_countresult) < 256 :for i in range (0,256-len(hist_countresult)) :hist_new.append(0)#计算整幅图的像素数目hist_sum = gray.shape[0] * gray.shape[1]#计算每个灰度级的像素数目占整个数目的比重for each in hist_countresult :result = float(each / hist_sum)hist_proresult.append(result)#遍历灰度级[0,255],寻找合适的thresholdw0 = w1 = u0tmp = u1tmp = u0 = u1 = deltaTmp = deltaMax = float(0)for i in range (256) :w0 = w1 = u0tmp = u1tmp = u0 = u1 = deltaTmp = float(0)for j in range (256) :if j <= i : #背景部分w0 = float(w0 + hist_proresult[j])u0tmp += j * hist_proresult[j]else :  #前景部分w1 += float(hist_proresult[j])u1tmp += j * hist_proresult[j]if w0 == 0.0 or w1 == 0.0:passelse :u0 = float(u0tmp / w0)u1 = float(u1tmp / w1)deltaTmp = (float)(w0 *w1* pow((u0 - u1), 2)) if deltaTmp > deltaMax : deltaMax = deltaTmpthreshold = i#用ostu大津算法得出最适当的阈值后,将图片进行二值化for i in range(gray.shape[0]) :for j in range(gray.shape[1]) :#对大于阈值的显示为255白色,小于阈值的显示为0黑色if gray[i][j] <= threshold :gray2[i][j] = 0countdown += 1else :gray2[i][j] = 255countup += 1return gray2#腐蚀
def corrode(twovalue_img) :#处理后最终输出矩阵将齐大小设置为与原图一样gray2=np.array([[0 for i in range(twovalue_img.shape[1])] for i in range(twovalue_img.shape[0])], dtype='float') #生成 3*3的结构元素structuralelement = np.array([[1 for i in range (3)]for i in range (3)],dtype='int')#使用结构元素去与原二值图像中为1的值进行与操作for i in range (1,twovalue_img.shape[0]-1) :for j in range (1,twovalue_img.shape[1]-1) :#添加每次处理后的元素到集合中list1 = []count1 = 0 #保存进行于操作后图中到底有几个1list1.append(twovalue_img[i-1][j-1] and structuralelement[0][0])list1.append(twovalue_img[i-1][j] and structuralelement[0][1])list1.append(twovalue_img[i-1][j+1] and structuralelement[0][2])list1.append(twovalue_img[i][j-1] and structuralelement[1][0])list1.append(twovalue_img[i][j] and structuralelement[1][1])list1.append(twovalue_img[i][j+1] and structuralelement[1][2])list1.append(twovalue_img[i+1][j-1] and structuralelement[2][0])list1.append(twovalue_img[i+1][j] and structuralelement[2][1])list1.append(twovalue_img[i+1][j+1] and structuralelement[2][2])#如果都为1,结果图像的该像素为1,否则为0。for each in list1 :if each == 1 :count1 += 1if count1 == 9 :gray2[i][j] = 255else :gray2[i][j] = 0        return gray2#膨胀
def swell(twovalue_img):#处理后最终输出矩阵将齐大小设置为与原图一样gray2=np.array([[0 for i in range(twovalue_img.shape[1])] for i in range(twovalue_img.shape[0])], dtype='float') #生成 3*3的结构元素structuralelement = np.array([[1 for i in range (3)]for i in range (3)],dtype='int')#使用结构元素去与原二值图像中为1的值进行与操作for i in range (1,twovalue_img.shape[0]-1) :for j in range (1,twovalue_img.shape[1]-1) :#添加每次处理后的元素到集合中list1 = []count1 = 0 #保存进行于操作后图中到底有几个1list1.append(twovalue_img[i-1][j-1] and structuralelement[0][0])list1.append(twovalue_img[i-1][j] and structuralelement[0][1])list1.append(twovalue_img[i-1][j+1] and structuralelement[0][2])list1.append(twovalue_img[i][j-1] and structuralelement[1][0])list1.append(twovalue_img[i][j] and structuralelement[1][1])list1.append(twovalue_img[i][j+1] and structuralelement[1][2])list1.append(twovalue_img[i+1][j-1] and structuralelement[2][0])list1.append(twovalue_img[i+1][j] and structuralelement[2][1])list1.append(twovalue_img[i+1][j+1] and structuralelement[2][2])#如果都为0,结果图像的该像素为0,否则为1。for each in list1 :if each == 1 :count1 += 1if count1 > 0 :gray2[i][j] = 255else :gray2[i][j] = 0        return gray2#开运算
def opencalc(twovalue_img) :#先腐蚀,再膨胀corrode_pic = corrode(twovalue_img)open_img = swell(corrode_pic)return open_img#闭运算
def closecalc(twovalue_img) :#先膨胀,再腐蚀swell_pic = swell(twovalue_img)close_img = corrode(swell_pic)return close_imgdef MAIN():image = cv2.imread(r"D:/Code/Python/2.png")cv2.imshow("old_img",image)gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)#调用自己写的otsu算法,并将处理后的二值化图像输出twovalue_img = myotsu(gray)cv2.imshow("twovalue_img",twovalue_img)#腐蚀操作corrode_img = corrode(twovalue_img)cv2.imshow("corrode_img",corrode_img)#膨胀操作swell_img = swell(twovalue_img)cv2.imshow("swell_img",swell_img)#开运算open_img = opencalc(twovalue_img)cv2.imshow("open_img",open_img)#闭运算close_img = closecalc(twovalue_img)cv2.imshow("close_img",close_img)cv2.waitKey(0)if __name__ == "__main__":MAIN()

原始图片:

二值化图像:

腐蚀:

膨胀:

开运算:

闭运算:

(自己编写函数)Python + Opencv 图像形态学处理(腐蚀、膨胀、开运算、闭运算)相关推荐

  1. Halcon中的基于区域的形态学处理(腐蚀膨胀开闭预算顶底帽运算)

    形态学处理的作用: 用于提取有意义的局部图像细节,通过改变局部区域的像素形态,对图像进行增强,为后续分割.特征提取.边缘检测做准备. 在开始之前,我们先了解一下:结构元素:StructElement ...

  2. 图像形态学操作—腐蚀膨胀深入

    博客原创出处:http://blog.csdn.net/lu597203933/article/details/36222277 这里我们主要想讲解冈萨雷斯的数字图像处理这本书上膨胀腐蚀的定义及用op ...

  3. pythonopencv图像形态_python+opencv图像形态学处理详细解释(膨胀、腐蚀、开闭运算、礼帽和黑猫)...

    python+opencv图像形态学处理 本篇博客主要是关于形态学中的腐蚀.膨胀.开运算.闭运算.礼帽和黑帽的函数用法. 内容会比较,为方便查阅.代码的解释会写在代码中. 用于测试的图像原图: 一.腐 ...

  4. 图像形态学概要-腐蚀、膨胀、开运算、闭运算、形态学梯度(形态学边缘提取)、顶帽操作、黑帽操作

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 图像形态学中两种最基本的操作就是对图形的腐蚀和膨 ...

  5. 《OpenCv视觉之眼》Python图像处理十 :Opencv图像形态学处理之开运算、闭运算和梯度运算原理及方法

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  6. python opencv图像二值化函数_python opencv 二值化 计算白色像素点的实例

    python opencv 二值化 计算白色像素点的实例 贴部分代码 #! /usr/bin/env python # -*- coding: utf-8 -*- import cv2 import ...

  7. 【学习笔记】opencv的python接口 形态学操作 腐蚀 膨胀 通用形态学函数

    腐蚀 img=np.zeros((5,5),np.uint8) img[1:4,1:4]=1 kernel=np.ones((3,1),np.uint8) erosion=cv2.erode(img, ...

  8. 【Python+OpenCV 图像透视变换 warpPerspective函数】

    Python+OpenCV 图像透视变换 warpPerspective函数 1.函数介绍 2.代码实例 3.实现效果 1.函数介绍 warpPerspective():对图像进行透视变换.简单来说, ...

  9. 基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)

    腐蚀与膨胀 图像的腐蚀与膨胀互为逆向操作,通常用于处理二值图像(黑白图,以黑色为底面背景),因此需要先进行二值化处理,腐蚀和膨胀通俗的理解就是,在指定大小的卷积核内,如果该卷积核内全为黑色或全为白色, ...

最新文章

  1. The constructor JedisPool(GenericObjectPoolConfig, String, int, int, String) refers to the missing t
  2. 如何在Kubernetes集群动态使用 NAS 持久卷
  3. java实现注销登录
  4. matlab gui打开fig文件,求助gui打开word文件及打开fig格式图片
  5. spring boot环境准备及搭建
  6. 未经处理的异常:System.Net.Sockets.SocketException: 以一种访问权限不允许的方式做了一个访问套接字的尝试...
  7. python数据结构-链表
  8. 词频统计及其效能分析
  9. PHP的面向对象模型(转贴)
  10. k3cloud新建简单帐表教程
  11. DAC,模数转换,使用Python,Matlab生产正弦码表(整型和浮点型)
  12. SSM框架客户管理系统
  13. 怎样解题:写题解思考问题的原则
  14. MS17-010 永恒之蓝漏洞利用方式
  15. MathType编辑的公式与文字不对齐
  16. 微信表情包小程序源码
  17. html加密文件怎么解密,加密文件如何解密?原理是什么?
  18. UE5 WebUI 5.0.1插件下载
  19. Assuming drive cache: write through 因为硬盘内存不足VM虚拟机开不了机的问题
  20. 使用Encoder-Decoder模型自动生成对联的思路

热门文章

  1. 开发APP必须知道的API集合
  2. 如何在雷电模拟器里使用YiLu代理的动态ip?
  3. 河北经贸大学计算机学院宿舍,河北经贸大学经济管理学院宿舍条件,宿舍环境图片(10篇)...
  4. 资金管理系统(带权限)
  5. QQ支持微信登录,手机QQ与微信联手!
  6. 关于amazon的aws云服务
  7. Pr 入门教程之如何创建序列?
  8. excel中vlookup函数的使用方法_Excel函数大全:工作中最常用的函数汇总
  9. android应用教程试题,ANDROID应用开发试题
  10. No EntityManager with actual transaction available for current thread - cannot reliably process ‘rem