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

本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的、不同方法的处理,以达到对图像进行去噪、锐化等一系列的操作。同时,希望观看本专栏的小伙伴可以理解到OpenCv进行图像处理的强大哦,如有转载,请注明出处(原文链接和作者署名),感谢各位小伙伴啦!

前文参考:
《OpenCv视觉之眼》Python图像处理一 :Opencv-python的简介及Python环境搭建
《OpenCv视觉之眼》Python图像处理二 :Opencv图像读取、显示、保存基本函数原型及使用
《OpenCv视觉之眼》Python图像处理三 :Opencv图像属性、ROI区域获取及通道处理
《OpenCv视觉之眼》Python图像处理四 :Opencv图像灰度处理的四种方法及原理
《OpenCv视觉之眼》Python图像处理五 :Opencv图像去噪处理之均值滤波、方框滤波、中值滤波和高斯滤波
《OpenCv视觉之眼》Python图像处理六 :Opencv图像傅里叶变换和傅里叶逆变换原理及实现
《OpenCv视觉之眼》Python图像处理七 :Opencv图像处理之高通滤波和低通滤波原理及构造
《OpenCv视觉之眼》Python图像处理八 :Opencv图像处理之图像阈值化处理原理及函数
《OpenCv视觉之眼》Python图像处理九 :Opencv图像形态学处理之图像腐蚀与膨胀原理及方法

上次博客,讲到图像形态学处理的基本处理方法图像膨胀和腐蚀,这是对简单图像的形态学处理,当我们需要对复杂图像处理时,我们就会用到其他方式的形态学处理,例如本次博客需要讲解的开运算和闭运算。

本次博客,林君学长带大家了解形态学的其他处理方式,针对复制图像的处理,开运算、闭运算、梯度运算,分别讲解原理,然后通过原理编写相关功能函数,实现图像开运算、闭运算和梯度运算功能,并介绍OpenCV库函数的使用方法,一起学习吧!

[Python图像处理十 ]:Opencv图像形态学处理之开运算、闭运算和梯度运算原理及方法

  • 一、开运算
    • 1、开运算原理
    • 2、开运算功能函数构造
    • 3、OpenCV开运算库函数调用
  • 二、闭运算
    • 1、闭运算原理
    • 2、闭运算功能函数构造
    • 3、OpenCV闭运算库函数调用
  • 三、梯度运算
    • 1、梯度运算原理
    • 2、梯度运算功能函数构造
    • 3、OpenCV梯度运算库函数调用

一、开运算

1、开运算原理

1)、原理:图像开运算是图像依次经过腐蚀、膨胀处理后的过程,至于图像腐蚀膨胀原理,上次博客已经介绍并实现了哦,本次便直接使用上次博客编写的图像腐蚀和膨胀算法
2)、特点:图像被腐蚀后,去除了噪声,但是也压缩了图像;接着对腐蚀过的图像进行膨胀处理,可以去除噪声,并保留原有图像

  • 开运算可以消除图像轮廓外部的噪声

2、开运算功能函数构造

1)、定义开运算功能函数

'''
图像开运算
'''
def morphologyEx_open(img,size):
    #获取图像尺寸及通道数
    h,w=img.shape[:2]
    num=int((size-1)/2)
    #自定义空白图像,用于显示腐、膨胀之后的图像
    img1=np.zeros((h,w),dtype=img.dtype)
    #自定义空白图像,用于显示开运算之后的图像
    img2=np.zeros((h,w),dtype=img.dtype)
    #图像灰度处理
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    #图像阈值化
    ret, Binary = cv2.threshold(gray , 127, 255, cv2.THRESH_BINARY)
    #腐蚀
    for i in range(num,h-num):
        for j in range(num,w-num):
            sum=np.array([])
            for k in range(i-num,i+num+1):
                for l in range(j-num,j+num+1):
                    a=Binary[k,l] and 1  #每一个都与1进行与,也就是核函数进行与  255与1是1  0与1为0
                    sum=np.insert(sum,len(sum),a)  #将与的结果写入数组sum
            #print(sum)
            if (sum == 1).all()==True: #判断数组是否全为1,如果是,则将1写入该点像素值,如果不是,写0
                img1[i,j]=255
            else:
                img1[i,j]=0
    #膨胀
    for i in range(num,h-num):
        for j in range(num,w-num):
            sum=np.array([])
            for k in range(i-num,i+num+1):
                for l in range(j-num,j+num+1):
                    a=img1[k,l] and 1  #每一个都与1进行与运算,也就是核函数进行与  255与1是1  0与1为0
                    sum=np.insert(sum,len(sum),a)  #将与的结果写入数组sum
            if (sum == 1).any()==True: #判断数组是否有1,如果是,则写255,如果不是,将0写入该点像素值
                img2[i,j]=255
            else:
                img2[i,j]=0
    return img2

2)、读取图像,调用开运算函数进行开运算处理

import cv2
import numpy as np
#np.set_printoptions(threshold=np.inf)  #打印数组中的全部内容
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
#读取图像
img=cv2.imread("g.jpg")
#调用开运算函数
img1=morphologyEx_open(img,7)
#显示图像
titles = ['原图', '开运算']  #标题
images = [img, img1]   #图像对比显示
for i in range(2):
    plt.subplot(1,2,i+1), plt.imshow(images[i],"gray")  
    plt.title(titles[i])    
    plt.axis('off')#关闭坐标轴  设置为on则表示开启坐标轴
plt.show()#显示图像

由于原理涉及到多重for循环,因此执行时间会长一点,等待一下就好,代码执行完成开运算结果如下所示:
《OpenCv视觉之眼》Python图像处理十 :Opencv图像形态学处理之开运算、闭运算和梯度运算原理及方法_第1张图片

3、OpenCV开运算库函数调用

在OpenCV中,同样提供开运算的库函数,函数原型如下所示
1)、函数原型:result =cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

  • img:需要进行开运算处理的图像
  • cv2.MORPH_OPEN:图像进行开运算需要填写的参数(进行开运算时,该参数为固定参数不可改变)
  • kernel:卷积核模板,例如kernel = np.ones((5,5), np.uint8),5x5的卷积核

2)、开运算

'''
opencv-开运算
'''
import cv2
import numpy as np
#np.set_printoptions(threshold=np.inf)  #打印数组中的全部内容
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
#读取图像
img=cv2.imread("o.jpg")
#设置卷积核
kernel = np.ones((7,7), np.uint8)
#调用opencv开运算库函数
img1=cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
#显示图像
titles = ['原图', '开运算']  #标题
images = [img, img1]   #图像对比显示
for i in range(2):
    plt.subplot(1,2,i+1), plt.imshow(images[i],"gray")  
    plt.title(titles[i])    
    plt.axis('off')#关闭坐标轴  设置为on则表示开启坐标轴
plt.show()#显示图像

《OpenCv视觉之眼》Python图像处理十 :Opencv图像形态学处理之开运算、闭运算和梯度运算原理及方法_第2张图片
3)当然,同时可通过腐蚀膨胀迭代实现开运算的结果,完整代码如下:

'''
opencv-腐蚀、膨胀拟合开运算
'''
import cv2
import numpy as np
#np.set_printoptions(threshold=np.inf)  #打印数组中的全部内容
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
#读取图像
img=cv2.imread("o.jpg")
#设置卷积核
kernel = np.ones((9,9), np.uint8)
#调用opencv开运算库函数
img1=cv2.erode(img,kernel,1)#先腐蚀
img1=cv2.dilate(img1,kernel,1)#再膨胀
#显示图像
titles = ['原图', '开运算']  #标题
images = [img, img1]   #图像对比显示
for i in range(2):
    plt.subplot(1,2,i+1), plt.imshow(images[i],"gray")  
    plt.title(titles[i])    
    plt.axis('off')#关闭坐标轴  设置为on则表示开启坐标轴
plt.show()#显示图像

《OpenCv视觉之眼》Python图像处理十 :Opencv图像形态学处理之开运算、闭运算和梯度运算原理及方法_第3张图片
图像在进行开运算之后,可以消除图像轮廓外部的噪声,这对于阈值化图像处理是非常重要的步骤,通过形态学处理之后,后面通过图像轮廓提取算法提取的轮廓便非常好了!

二、闭运算

1、闭运算原理

1)、原理:图像开运算是图像依次经过膨胀、再腐蚀处理后的过程,至于图像腐蚀膨胀原理,上次博客已经介绍并实现了哦,本次便直接使用上次博客编写的图像腐蚀和膨胀算法
2)、特点:图像先膨胀,后腐蚀,它有助于关闭前景物体内部的小孔,或物体上的小黑点。

  • 闭运算可以消除图像轮廓内部的噪声

2、闭运算功能函数构造

1)、闭运算原理功能函数构造如下

'''
图像闭运算
'''
def morphologyEx_close(img,size):
    #获取图像尺寸及通道数
    h,w=img.shape[:2]
    num=int((size-1)/2)
    #自定义空白图像,用于显示膨胀
    img1=np.zeros((h,w),dtype=img.dtype)
    #自定义空白图像,用于显示闭运算之后的图像
    img2=np.zeros((h,w),dtype=img.dtype)
    #图像灰度处理
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    #图像阈值化
    ret, Binary = cv2.threshold(gray , 127, 255, cv2.THRESH_BINARY)
    #膨胀
    for i in range(num,h-num):
        for j in range(num,w-num):
            sum=np.array([])
            for k in range(i-num,i+num+1):
                for l in range(j-num,j+num+1):
                    a=Binary[k,l] and 1  #每一个都与1进行与运算,也就是核函数进行与  255与1是1  0与1为0
                    sum=np.insert(sum,len(sum),a)  #将与的结果写入数组sum
            if (sum == 1).any()==True: #判断数组是否有1,如果是,则写255,如果不是,将0写入该点像素值
                img1[i,j]=255
            else:
                img1[i,j]=0
    #腐蚀
    for i in range(num,h-num):
        for j in range(num,w-num):
            sum=np.array([])
            for k in range(i-num,i+num+1):
                for l in range(j-num,j+num+1):
                    a=img1[k,l] and 1  #每一个都与1进行与,也就是核函数进行与  255与1是1  0与1为0
                    sum=np.insert(sum,len(sum),a)  #将与的结果写入数组sum
            #print(sum)
            if (sum == 1).all()==True: #判断数组是否全为1,如果是,则将1写入该点像素值,如果不是,写0
                img2[i,j]=255
            else:
                img2[i,j]=0
    return img2

2)、读取图像,调用闭运算函数进行图像闭运算

import cv2
import numpy as np
#np.set_printoptions(threshold=np.inf)  #打印数组中的全部内容
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
#读取图像
img=cv2.imread("c.jpg")
#调用闭运算函数
img1=morphologyEx_close(img,7)
#显示图像
titles = ['原图', '闭运算']  #标题
images = [img, img1]   #图像对比显示
for i in range(2):
    plt.subplot(1,2,i+1), plt.imshow(images[i],"gray")  
    plt.title(titles[i])    
    plt.axis('off')#关闭坐标轴  设置为on则表示开启坐标轴
plt.show()#显示图像

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

3、OpenCV闭运算库函数调用

OpenCV中,也提供了图像闭运算的函数,和开运算库函数一样,唯一不同则为闭运算对应自己的参数,函数原型如下:
1)、函数原型:result =cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

  • img:需要进行开运算处理的图像
  • cv2.MORPH_CLOSE:图像进行闭运算需要填写的参数(进行闭运算时,该参数为固定参数不可改变)
  • kernel:卷积核模板,例如kernel = np.ones((5,5), np.uint8),5x5的卷积核

2)、闭运算库函数使用如下所示:

'''
opencv-闭运算
'''
import cv2
import numpy as np
#np.set_printoptions(threshold=np.inf)  #打印数组中的全部内容
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
#读取图像
img=cv2.imread("c.jpg")
#设置卷积核
kernel = np.ones((7,7), np.uint8)
#调用opencv闭运算库函数
img1=cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
#显示图像
titles = ['原图', '闭运算']  #标题
images = [img, img1]   #图像对比显示
for i in range(2):
    plt.subplot(1,2,i+1), plt.imshow(images[i],"gray")  
    plt.title(titles[i])    
    plt.axis('off')#关闭坐标轴  设置为on则表示开启坐标轴
plt.show()#显示图像

《OpenCv视觉之眼》Python图像处理十 :Opencv图像形态学处理之开运算、闭运算和梯度运算原理及方法_第5张图片
可以看出,我们同样设置为7x7的核进行计算,但通过库函数调用的闭运算效果没有我们自己编写闭运算的效果好哦,但可以通过调节核尺寸进行调整,如下11x11的卷积核:
《OpenCv视觉之眼》Python图像处理十 :Opencv图像形态学处理之开运算、闭运算和梯度运算原理及方法_第6张图片
3)、同样的,可以通过库函数先膨胀、再腐蚀对闭运算的库函数进行模拟,完整代码如下所示:

'''
opencv-膨胀、腐蚀拟合闭运算
'''
import cv2
import numpy as np
#np.set_printoptions(threshold=np.inf)  #打印数组中的全部内容
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
#读取图像
img=cv2.imread("c.jpg")
#设置卷积核
kernel = np.ones((9,9), np.uint8)
#调用opencv膨胀、腐蚀库函数
img1=cv2.dilate(img,kernel,1)#先膨胀
img1=cv2.erode(img1,kernel,1)#后腐蚀
#显示图像
titles = ['原图', '闭运算']  #标题
images = [img, img1]   #图像对比显示
for i in range(2):
    plt.subplot(1,2,i+1), plt.imshow(images[i],"gray")  
    plt.title(titles[i])    
    plt.axis('off')#关闭坐标轴  设置为on则表示开启坐标轴
plt.show()#显示图像

《OpenCv视觉之眼》Python图像处理十 :Opencv图像形态学处理之开运算、闭运算和梯度运算原理及方法_第7张图片
可以看出,设置为11x11的卷积核,和上面直接通过库函数调用的闭运算效果是一致的,因此,差别不大;从两张图可以对比看出,闭运算可以很好的降低图像轮廓内部噪声!

三、梯度运算

1、梯度运算原理

1)、原理
图像梯度运算是膨胀图像减去腐蚀图像的结果,得到图像的轮廓
2)、计算公式
梯度运算(img) = 膨胀(img) - 腐蚀(img)

2、梯度运算功能函数构造

1)、梯度运算功能函数构造

'''
图像梯度运算
'''
def morphologyEx_Tidu(img,size):
    #获取图像尺寸及通道数
    h,w=img.shape[:2]
    num=int((size-1)/2)
    #自定义空白图像,用于显示膨胀
    img1=np.zeros((h,w),dtype=img.dtype)
    #自定义空白图像,用于显示腐蚀
    img2=np.zeros((h,w),dtype=img.dtype)
    #图像灰度处理
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    #图像阈值化
    ret, Binary = cv2.threshold(gray , 127, 255, cv2.THRESH_BINARY)
    #膨胀
    for i in range(num,h-num):
        for j in range(num,w-num):
            sum=np.array([])
            for k in range(i-num,i+num+1):
                for l in range(j-num,j+num+1):
                    a=Binary[k,l] and 1  #每一个都与1进行与运算,也就是核函数进行与  255与1是1  0与1为0
                    sum=np.insert(sum,len(sum),a)  #将与的结果写入数组sum
            if (sum == 1).any()==True: #判断数组是否有1,如果是,则写255,如果不是,将0写入该点像素值
                img1[i,j]=255
            else:
                img1[i,j]=0
    #腐蚀
    for i in range(num,h-num):
        for j in range(num,w-num):
            sum=np.array([])
            for k in range(i-num,i+num+1):
                for l in range(j-num,j+num+1):
                    a=Binary[k,l] and 1  #每一个都与1进行与,也就是核函数进行与  255与1是1  0与1为0
                    sum=np.insert(sum,len(sum),a)  #将与的结果写入数组sum
            #print(sum)
            if (sum == 1).all()==True: #判断数组是否全为1,如果是,则将1写入该点像素值,如果不是,写0
                img2[i,j]=255
            else:
                img2[i,j]=0
    img3=img1-img2    
    return img3

2)、读取图像,调用梯度运算函数进行梯度运算

import cv2
import numpy as np
#np.set_printoptions(threshold=np.inf)  #打印数组中的全部内容
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
#读取图像
img=cv2.imread("g.jpg")
#调用梯度运算函数
img1=morphologyEx_Tidu(img,3)
#显示图像
titles = ['原图', '梯度运算']  #标题
images = [img, img1]   #图像对比显示
for i in range(2):
    plt.subplot(1,2,i+1), plt.imshow(images[i],"gray")  
    plt.title(titles[i])    
    plt.axis('off')#关闭坐标轴  设置为on则表示开启坐标轴
plt.show()#显示图像

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

3、OpenCV梯度运算库函数调用

OpenCV库函数中同样有梯度运算的库函数,同样的和开运算和闭运算相同函数,只是参数不同
1)、函数原型:result =cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

  • img:需要进行开运算处理的图像
  • cv2.MORPH_GRADIENT:图像进行梯度运算需要填写的参数(进行梯度运算时,该参数为固定参数不可改变)
  • kernel:卷积核模板,例如kernel = np.ones((5,5), np.uint8),5x5的卷积核

2)、梯度运算库函数使用方法如下所示:

'''
opencv-梯度运算
'''
import cv2
import numpy as np
#np.set_printoptions(threshold=np.inf)  #打印数组中的全部内容
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
#读取图像
img=cv2.imread("g.jpg")
#设置卷积核
kernel = np.ones((3,3), np.uint8)
#调用opencv梯度运算库函数
img1=cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
#显示图像
titles = ['原图', '梯度运算']  #标题
images = [img, img1]   #图像对比显示
for i in range(2):
    plt.subplot(1,2,i+1), plt.imshow(images[i],"gray")  
    plt.title(titles[i])    
    plt.axis('off')#关闭坐标轴  设置为on则表示开启坐标轴
plt.show()#显示图像

《OpenCv视觉之眼》Python图像处理十 :Opencv图像形态学处理之开运算、闭运算和梯度运算原理及方法_第9张图片
3)、同理,我们可以通过原理用膨胀-腐蚀库函数进行模拟梯度运算,完整代码如下所示:

'''
opencv-膨胀、腐蚀拟合梯度运算
'''
import cv2
import numpy as np
#np.set_printoptions(threshold=np.inf)  #打印数组中的全部内容
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
#读取图像
img=cv2.imread("g.jpg")
#设置卷积核
kernel = np.ones((3,3), np.uint8)
#调用opencv膨胀、腐蚀库函数
img1=cv2.dilate(img,kernel,1)#先膨胀
img2=cv2.erode(img1,kernel,1)#后腐蚀
img3=img1-img2
#显示图像
titles = ['原图', '梯度运算']  #标题
images = [img, img3]   #图像对比显示
for i in range(2):
    plt.subplot(1,2,i+1), plt.imshow(images[i],"gray")  
    plt.title(titles[i])    
    plt.axis('off')#关闭坐标轴  设置为on则表示开启坐标轴
plt.show()#显示图像

《OpenCv视觉之眼》Python图像处理十 :Opencv图像形态学处理之开运算、闭运算和梯度运算原理及方法_第10张图片
由上面运算结果可以看出,在确保图像噪声去除达到目的之后,通过梯度运算可以将图像完美的提取出来,作为一个图像的轮廓提取,梯度运算时图像轮廓提取的方法之一,后面我们会讲到轮廓提取的几种其他算法,一般情况,没有使用梯度算法进行轮廓提取,至少目前来说,林君学长还没有遇到,都是通过后面讲解到的其他几种算法进行图像轮廓的提取!

以上就是本次博客的全部内容,遇到问题的小伙伴记得留言评论,学长看到会为大家进行解答的,这个学长不太冷!

顺境时,多一份思索;逆境时,多一份勇气;成功时,多一份淡然;彷徨时,多一份信念。生活总是这样,你以为失去的,可能在来的路上;你以为拥有的,可能在去的途中。

陈一月的又一天编程岁月^ _ ^

你可能感兴趣的:(Opencv视觉之眼)