zoukankan      html  css  js  c++  java
  • python+opencv图像形态学处理详细解释(膨胀、腐蚀、开闭运算、礼帽和黑猫)

    python+opencv图像形态学处理

    本篇博客主要是关于形态学中的腐蚀、膨胀、开运算、闭运算、礼帽和黑帽的函数用法。

    内容会比较,为方便查阅。代码的解释会写在代码中。

    用于测试的图像原图:

    一、腐蚀

    • 关于腐蚀就是将图像的边界腐蚀掉,或者说使得图像整体上看起来变瘦了。它的操作原理就是卷积核沿着图像滑动,如果与卷积核对应的原图像的所有像素值都是1,那么中心元素保持原来的值,否则就变为0。这对于去除白噪声很有用,也可以用于断开两个连载一起的物体。
    • 通俗的讲,腐蚀操作就是让图像整体看起来瘦一点。
    • 但是老猫发现,这句话并不完全正确,腐蚀操作不一定会让图像变瘦,有可能还会让它变胖。

    例如:

     1 #腐蚀
     2 #读取图像
     3 img1=cv.imread("oldcat.jpg")
     4 
     5 #将图像进行反向二值化操作,即将白色部分变为黑色,黑色部分变为白色
     6 #ret,img2=cv.threshold(img1,80,255,cv.THRESH_BINARY_INV) 
     7 
     8 #定义一个3*3的卷积核
     9 kernel=np.ones((3,3),np.uint8)
    10 
    11 #图像腐蚀:cv2.erode(输入图像,卷积核,iterations=腐蚀的次数)
    12 erosion=cv.erode(img1,kernel,iterations=1)
    13 
    14 #在图像上添加文本,方便分清每个操作相对应的图像
    15 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
    16 cv.putText(erosion,"erosion",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
    17 
    18 #将原图像和腐蚀操作的图像放在同一个窗口显示
    19 glay=np.hstack((img1,erosion))
    20 cv.imshow("glay",glay)
    21 cv.waitKey(0)
    22 cv.destroyAllWindows()

    效果图:

    可以发现:

      相比于原图,腐蚀并没有变瘦,反而还“胖”了。

    原因:

      形态学处理是一个对二值化灰度图像的处理,主要是对白色图像的一个卷积操作。

      由于原图字体是黑色,底色为白色,所以在进行腐蚀操作的时候,卷积核中只要有一个点为0,卷积核的中心点也会为0。

    解决方法:

      对原图像进行一个反向二值化处理,即将白色部分变为黑色,黑色部分变为白色

      去掉上面代码ret,img2=cv.threshold(img,80,255,cv.THRESH_BINARY_INV)的注释,同时将erosion=cv.erode(img1,kernel,iterations=1)改为erosion=cv.erode(img2,kernel,iterations=1)

    效果图:

    如图所示:这样腐蚀处理的图像才会变瘦

    二、膨胀

    膨胀:卷积核所对应的原图像的像素值只要有一个是1,中心像素值就是1。一般在除噪是,先腐蚀再膨胀,因为腐蚀在去除白噪声的时候也会使图像缩小,所以我们之后要进行膨胀。当然也可以用来将两者物体分开。

    例如:

     1 import numpy as np
     2 import cv2 as cv
     3 #膨胀
     4 #读取图像
     5 img1=cv.imread("oldcat.jpg",0)
     6 
     7 #将图像进行反向二值化操作,即将白色部分变为黑色,黑色部分变为白色
     8 ret,img2=cv.threshold(img1,80,255,cv.THRESH_BINARY_INV) 
     9 
    10 #定义一个3*3的卷积核
    11 kernel=np.ones((3,3),np.uint8)
    12 
    13 #图像腐蚀:cv2.dilate(输入图像,卷积核,iterations=腐蚀的次数)
    14 dilation=cv.dilate(img2,kernel,iterations=1)
    15 
    16 #在图像上添加文本,方便分清每个操作相对应的图像
    17 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
    18 
    19 #将原图像和膨胀操作的图像放在同一个窗口显示
    20 glay=np.hstack((img1,dilation))
    21 cv.imshow("glay",glay)
    22 cv.waitKey(0)
    23 cv.destroyAllWindows()

    效果图:

     腐蚀和膨胀是比较简单的。

     三、开运算

    了解形态学基本处理的同学都知道,开运算和闭运算就是将腐蚀和膨胀按照一定的次序进行处理。但这两者并不是可逆的,即先开后闭并不能得到原先的图像。

    例如:

     1 import numpy as np
     2 import cv2 as cv
     3 #开运算
     4 #先腐蚀,再膨胀
     5 img1=cv.imread("oldcat.jpg",0)
     6 #反二值化,小于127设为255,即黑变白;大于127的设为 0,即白变黑。
     7 ret,img2=cv.threshold(img1,127,255,cv.THRESH_BINARY_INV)
     8 
     9 #定义一个3*3的卷积核
    10 kernel=np.ones((3,3),np.uint8)
    11 
    12 #开运算
    13 opening2=cv.morphologyEx(img2,cv.MORPH_OPEN,kernel)
    14 
    15 #在图像上添加文本,方便分清每个操作相对应的图像
    16 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
    17 
    18 #将原图像和开运算操作的图像放在同一个窗口显示
    19 glay=np.hstack((img1,opening2))
    20 cv.imshow("glay",glay)
    21 cv.waitKey(0)
    22 cv.destroyAllWindows()

    效果图:

    四、闭运算

    闭运算:就是先膨胀,后腐蚀,也是不可逆的。

     1 import numpy as np
     2 import cv2 as cv
     3 #闭运算
     4 #先膨胀,后腐蚀
     5 img1=cv.imread("oldcat.jpg",0)
     6 #反二值化,小于127设为255,即黑变白;大于127的设为 0,即白变黑。
     7 ret,img2=cv.threshold(img1,127,255,cv.THRESH_BINARY_INV)
     8 
     9 #定义一个3*3的卷积核
    10 kernel=np.ones((3,3),np.uint8)
    11 
    12 #闭运算
    13 closing=cv.morphologyEx(img2,cv.MORPH_CLOSE,kernel)
    14 
    15 #在图像上添加文本,方便分清每个操作相对应的图像
    16 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
    17 
    18 #将原图像和闭运算操作的图像放在同一个窗口显示
    19 glay=np.hstack((img1,closing))
    20 cv.imshow("glay",glay)
    21 cv.waitKey(0)
    22 cv.destroyAllWindows()

    效果图:

     五、梯度运算

    梯度运算,类似于提取轮廓。梯度=膨胀-腐蚀

    例如:

     

     1 import numpy as np
     2 import cv2 as cv
     3 #梯度运算,类似于提取轮廓
     4 #梯度=膨胀-腐蚀
     5 img1=cv.imread("oldcat.jpg",0)
     6 
     7 #反二值化,小于127设为255,即黑变白;大于127的设为 0,即白变黑。
     8 ret,img2=cv.threshold(img1,127,255,cv.THRESH_BINARY_INV)
     9 
    10 #定义一个3*3的卷积核
    11 kernel=np.ones((3,3),np.uint8)
    12 
    13 #梯度运算
    14 gradient=cv.morphologyEx(img2,cv.MORPH_GRADIENT,kernel)
    15 
    16 #在图像上添加文本,方便分清每个操作相对应的图像
    17 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
    18 
    19 #将原图像和梯度运算操作的图像放在同一个窗口显示
    20 glay=np.hstack((img1,gradient))
    21 cv.imshow("glay",glay)
    22 cv.waitKey(0)
    23 cv.destroyAllWindows()

     

    效果图:

     

    六、礼帽

    礼帽就是原始初入减去开运算结果

    例如:

     1 import numpy as np
     2 import cv2 as cv
     3 #礼帽,小线条
     4 #礼帽=原始输入-运算结果
     5 img1=cv.imread("oldcat.jpg",0)
     6 ret,img2=cv.threshold(img1,127,255,cv.THRESH_BINARY_INV)
     7 kernel=np.ones((3,3),np.uint8)
     8 
     9 #礼帽
    10 tophat=cv.morphologyEx(img2,cv.MORPH_TOPHAT,kernel)
    11 
    12 #在图像上添加文本,方便分清每个操作相对应的图像
    13 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
    14 
    15 #将原图像和礼帽运算操作的图像放在同一个窗口显示
    16 glay=np.hstack((img1,tophat))
    17 cv.imshow("glay",glay)
    18 cv.waitKey(0)
    19 cv.destroyAllWindows()

    效果图:

     

     七、黑帽

    黑帽=闭运算-原始输入

    例如:

     1 import numpy as np
     2 import cv2 as cv
     3 #黑帽。只能看见大概轮廓
     4 #黑帽=闭运算-原始输入
     5 img1=cv.imread("oldcat.jpg",0)
     6 ret,img2=cv.threshold(img1,127,255,cv.THRESH_BINARY_INV)
     7 kernel=np.ones((3,3),np.uint8)
     8 
     9 #黑帽
    10 blackhat=cv.morphologyEx(img2,cv.MORPH_BLACKHAT,kernel)
    11 
    12 #在图像上添加文本,方便分清每个操作相对应的图像
    13 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
    14 
    15 #将原图像和开运算操作的图像放在同一个窗口显示
    16 glay=np.hstack((img1,blackhat))
    17 cv.imshow("glay",glay)
    18 cv.waitKey(0)
    19 cv.destroyAllWindows()

    效果图:

     八、总结

    • 本篇博客主要是关于图像形态学处理,文字描述虽然不多,但是每一行代码都有解释,并且每一个运算处理的效果图都有原图和处理后的图像对比。
    • 图像形态学处理是针对灰度图的,所以在读取原图的过程中,直接关闭了颜色通道,虽然方便但也有不足,就是图像上,添加的文字信息也会失去颜色。具体可以观察腐蚀处理和膨胀处理再读取代码上的区别。
    • 为了方便更容易理解,我是将原图进行了一个二值化反色处理,再进行相应的形态学处理。若不进行二值化反色处理,结果是跟我的效果图是不一样的。具体就是将代码中的二值化处理代码去掉,大家可以试一试,对比观察,更深的理解形态学处理是什么实现的。

    实践出真知,博客的代码很完整,但还需要自己实际写一遍才能更加理解。

  • 相关阅读:
    rpm包的管理
    多态应用实例--制作饮品
    纯虚函数和抽象类
    rpm包的管理
    动态监控进程
    封装继承和多态
    计网面试题
    模拟浏览器加载页面时的版本下载
    xpath中extract()使用
    MVC+EF CODE FIRST的使用
  • 原文地址:https://www.cnblogs.com/cyt99/p/12483580.html
Copyright © 2011-2022 走看看