系列内容:OpenCV概述与环境配置,OpenCV基础知识和绘制图形,图像的算数与位运算,图像视频的加载和显示,图像基本变换,滤波器,形态学,图像轮廓,图像直方图,车辆统计项目,特征检测和匹配,图像查找和拼接,虚拟计算器项目,信用卡识别项目,图像的分割与修复,人脸检测与车牌识别,目标追踪,答题卡识别判卷与文档ocr扫描识别,光流估计
什么是形态学
- 指一系列处理图像形状特征的图像处理技术。
- 形态学的基本思想是利用一种特殊的结构元(本质上就是卷积核)来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别。
- 这些处理方法基本是对二进制图像进行处理, 即黑白图像
- 卷积核决定着图像处理后的效果
形态学常用基本操作有:
- 膨胀和腐蚀
- 开运算
- 闭运算
- 顶帽
- 黑帽
二值化: 将图像的每个像素变成两种值, 比如0, 255.
threshold(src, thresh, maxval, type[, dst])
- src 最好是灰度图
- thresh: 阈值
- maxval: 最大值, 最大值不一定是255
- type: 操作类型, 常见操作类型如下图7.1所示:

示例代码,图像全局二值化
#形态学 import cv2 import numpy as np
#导入图片 img=cv2.imread(‘dog1.jpg’)
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#返回两个结果,一个是阈值,另一个是处理后的图片
ret,dst=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
cv2.imshow(‘dog’,np.hstack((gray,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
图像全局二值化,如图7.2所示:

在前面的部分我们使用是全局阈值,整幅图像采用同一个数作为阈值。当时这种方法并不适应与所有情况,尤其是当同一幅图像上的不同部分具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。
adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
这种方法需要我们指定六个参数,返回值只有一个。
- Adaptive Method - 指定计算阈值的方法。
- cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值
- cv2.ADPTIVE_THRESH_GAUSSIAN_C:阈值取值相邻区域的加权和,权重为一个高斯窗口。
- Block Size - 邻域大小(用来计算阈值的区域大小)。
- C - 这就是一个常数,阈值就等于的平均值或者加权平均值减去这个常数。
示例代码,自适应阈值二值化
(1)图像自适应阈值二值化处理
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘lena1.png’)
cv2.namedWindow(‘img’,cv2.WINDOW_NORMAL)
cv2.resizeWindow(‘img’,1920,1080)
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
dst=cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,9,0)
cv2.imshow(‘dog’,np.hstack((gray,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
lena图像自适应阈值二值化处理,如图7.3所示:

(2)图像自适应阈值二值化处理对比
不图像自适应阈值二值化处理
#数学题例子 import cv2 import numpy as np
#导入图片 img=cv2.imread(‘math1.jpg’)
cv2.namedWindow(‘img’,cv2.WINDOW_NORMAL) cv2.resizeWindow(‘img’,640,480)
#二值化操作是对灰度图片操作,把照片变成灰度图像 gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #我们发现适应全局阈值二值化,对图片光线不好的地方效果不好 thresh,dst=cv2.threshold(gray,175,255,cv2.THRESH_BINARY)
print(thresh) cv2.imshow(‘img’,np.hstack((gray,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
数学题例子,不图像自适应阈值二值化处理,如图7.4所示:

数学题,使用图像自适应阈值二值化处理
#数学题例子 import cv2 import numpy as np
#导入图片 img=cv2.imread(‘math1.jpg’)
cv2.namedWindow(‘img’,cv2.WINDOW_NORMAL) cv2.resizeWindow(‘img’,1080,720)
#二值化操作是对灰度图片操作,把照片变成灰度图像 gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #适应全局阈值二值化 dst=cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,5,0)
cv2.imshow(‘img’,np.hstack((gray,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
数学题用图像自适应阈值二值化处理,如图7.5所示:

腐蚀操作也就是用卷积核扫描图像,只不过腐蚀操作的卷积一般都是1,如果卷积核内所有的像素点都是白色,那么锚点即为白色.如图7.6所示:

大部分的时候,腐蚀操作都使用的是全为1的卷积核,如图7.7所示:

erode(src,kernel[,dst[,anchor[,iteration[,borderType[,borderValue]]]]])
iteration是腐蚀操作的迭代函数,次数越多,腐蚀操作执行的次数越多,腐蚀效果越明显
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘erode1.png’)
kernel=np.ones((3,3),np.uint8)
dst=cv2.erode(img,kernel,iterations=1)
cv2.imshow(‘img’,np.hstack((img,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
卷积核为1时,处理结果如图7.8所示:

卷积核为2时,处理结果如图7.9所示:

OpenCV提供了获取卷积核的API,用户无需手工创建卷积核。
getStructuringElement(shape, ksize[, anchor])
shape参数用于指定卷积核的形状,它代表卷积核中1的排列形状,而非卷积核的长宽。
可选的卷积核形状包括:
- MORPH_RECT:卷积核中的1呈矩形排列,这是常用的形状。
- MORPH_ELLIPSE:卷积核中的1呈椭圆排列。
- MORPH_CROSS:卷积核中的1呈十字形排列。
1.卷积核形状
(1)椭圆
import cv2 import numpy as np
kernel=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) print(kernel)
卷积核如图7.10所示:

(2)矩形
import cv2 import numpy as np
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)) print(kernel)
卷积核如图7.11所示:

(3)十字
import cv2 import numpy as np
kernel=cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) print(kernel)
卷积核如图7.12所示:

2.对字符”i”进行腐蚀
(1)矩形处理
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘i.png’)
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)) print(kernel) #腐蚀 dst=cv2.erode(img,kernel) cv2.imshow(‘img’,np.hstack((img,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
矩形处理结果如图7.13所示:

(2)椭圆处理
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘i.png’)
kernel=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) print(kernel) #腐蚀 dst=cv2.erode(img,kernel) cv2.imshow(‘img’,np.hstack((img,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
椭圆处理结果如图7.14所示:

(3)十字处理
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘i.png’)
kernel=cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) print(kernel) #腐蚀 dst=cv2.erode(img,kernel) cv2.imshow(‘img’,np.hstack((img,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
十字处理结果如图7.15所示:

膨胀是腐蚀的相反操作,基本原理是只要保证卷积核的锚点是非0值,周边无论是0还是非0值,都变成非0值.如图7.16所示:

dilate(img,kernel,iteratinotallow=1)
(1)矩形膨胀
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘i.png’)
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)) print(kernel) #腐蚀 dst=cv2.dilate(img,kernel,iterations=1) cv2.imshow(‘img’,np.hstack((img,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
矩形膨胀操作结果,如图7.17所示:

(2)椭圆膨胀
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘i.png’)
kernel=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) print(kernel) #腐蚀 dst=cv2.dilate(img,kernel,iterations=1) cv2.imshow(‘img’,np.hstack((img,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
椭圆膨胀操作结果,如图7.18所示:

(3)十字膨胀
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘i.png’)
kernel=cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) print(kernel) #腐蚀 dst=cv2.dilate(img,kernel,iterations=1) cv2.imshow(‘img’,np.hstack((img,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
十字膨胀操作结果,如图7.19所示:

应用:腐蚀之后膨胀还原
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘erode1.png’)
kernel=np.ones((3,3),np.uint8) #先腐蚀 dst1=cv2.erode(img,kernel,iterations=2)
#再膨胀 dst=cv2.dilate(dst1,kernel,iterations=2)
cv2.imshow(‘img’,np.hstack((img,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
腐蚀之后膨胀还原效果,如图7.20所示:

开运算和闭运算都是腐蚀和膨胀的基本应用
开运算=腐蚀+膨胀
morphologyEx(img, MORPH_OPEN, kernel)
- MORPH_OPEN 表示形态学的开运算
- kernel如果噪点比较多,会选择大一点的kernel,如果噪点比较小,可以选择小点的kernel
实例,处理黑白噪声图片
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘dogi.png’)
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
#先腐蚀
dst1=cv2.erode(img,kernel,iterations=2)
#再膨胀
dst=cv2.dilate(dst1,kernel,iterations=2)
dst=cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel,iterations=1)
cv2.imshow(‘img’,np.hstack((img,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
开运算处理黑白噪声图片,效果如图7.21所示:

闭运算=膨胀+腐蚀
morphologyEx(img, MORPH_CLOSE, kernel)
- MORPH_CLOSE 表示形态学的开运算
- kernel如果噪点比较多,会选择大一点的kernel,如果噪点比较小,可以选择小点的kernel
实例:白色内部有噪点
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘dog1i.png’)
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
#先腐蚀
dst1=cv2.erode(img,kernel,iterations=2)
#再膨胀
dst=cv2.dilate(dst1,kernel,iterations=2)
dst=cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel,iterations=1)
cv2.imshow(‘img’,np.hstack((img,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
闭运算处理黑白噪声图片,效果如图7.22所示:

梯度=原图-腐蚀
腐蚀之后原图边缘变小了,原图-腐蚀可以得到腐蚀掉的部分,即边缘.
morphologyEx(img,cv2.MORPH_GRADIENT,kernel,iterations)
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘i2.png’)
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
#先腐蚀
dst1=cv2.erode(img,kernel,iterations=2)
#再膨胀
dst=cv2.dilate(dst1,kernel,iterations=2)
dst=cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel,iterations=1)
cv2.imshow(‘img’,np.hstack((img,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
一次梯度,效果如图7.23所示:

二次梯度,效果如图7.24所示:

顶帽=原图-开运算
开运算的效果是去除图像外的噪点,原图-开运算就得到了去掉的噪点.
morphologyEx(img,cv2.MORPH_TOPHAT,kernel,iterations)
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘dogi.png’)
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
dst=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel,iterations=1)
cv2.imshow(‘img’,np.hstack((img,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
顶帽操作,效果如图7.25所示:

黑帽=原图-闭运算
闭运算的效果是去除图像内的噪点,原图-闭运算就得到了去掉的噪点.
morphologyEx(img,cv2.MORPH_BLACKHAT,kernel,iterations)
import cv2 import numpy as np
#导入图片 img=cv2.imread(‘dog1i.png’)
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
dst=cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel,iterations=1)
cv2.imshow(‘img’,np.hstack((img,dst)))
cv2.waitKey(0) cv2.destroyAllWindows()
黑帽操作,效果如图7.26所示:

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/257853.html