OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-系列内容 OpenCV 概述与环境配置 OpenCV 基础知识和绘制图形 图像的算数与位运算 图像视频的加载和显示 图像基本变换 滤波器 形态学 图像轮廓 图像直方图 车辆统计项目 特征检测和匹配 图像查找和拼接 虚拟计算器项目 信用卡识别项目 图像的分割与修复 人脸检测与车牌识别 目标追踪 答题卡识别判卷与文档 ocr 扫描识别 光流估计 什么是形态学 指一系列处理图像形状特征的图像处理技术

大家好,我是讯享网,很高兴认识大家。这里提供最前沿的Ai技术和互联网信息。



系列内容:OpenCV概述与环境配置,OpenCV基础知识和绘制图形,图像的算数与位运算,图像视频的加载和显示,图像基本变换,滤波器,形态学,图像轮廓,图像直方图,车辆统计项目,特征检测和匹配,图像查找和拼接,虚拟计算器项目,信用卡识别项目,图像的分割与修复,人脸检测与车牌识别,目标追踪,答题卡识别判卷与文档ocr扫描识别,光流估计

什么是形态学

  1. 指一系列处理图像形状特征的图像处理技术。
  2. 形态学的基本思想是利用一种特殊的结构元(本质上就是卷积核)来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别。
  3. 这些处理方法基本是对二进制图像进行处理, 即黑白图像
  4. 卷积核决定着图像处理后的效果

形态学常用基本操作有:

  1. 膨胀和腐蚀
  2. 开运算
  3. 闭运算
  4. 顶帽
  5. 黑帽

二值化: 将图像的每个像素变成两种值, 比如0, 255.

threshold(src, thresh, maxval, type[, dst])

  • src 最好是灰度图
  • thresh: 阈值
  • maxval: 最大值, 最大值不一定是255
  • type: 操作类型, 常见操作类型如下图7.1所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#人工智能

示例代码,图像全局二值化

#形态学 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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_二值化_02

在前面的部分我们使用是全局阈值,整幅图像采用同一个数作为阈值。当时这种方法并不适应与所有情况,尤其是当同一幅图像上的不同部分具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。

adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)

这种方法需要我们指定六个参数,返回值只有一个。

  • Adaptive Method - 指定计算阈值的方法。
  1. cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值
  2. 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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#计算机视觉_03

(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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_二值化_04

数学题,使用图像自适应阈值二值化处理

#数学题例子 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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#人工智能_05

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

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_卷积核_06

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

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#人工智能_07

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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#计算机视觉_08

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

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_卷积核_09

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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#计算机视觉_10

(2)矩形

import cv2 import numpy as np

kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)) print(kernel)

卷积核如图7.11所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#计算机视觉_11

(3)十字

import cv2 import numpy as np

kernel=cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) print(kernel)

卷积核如图7.12所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_二值化_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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_卷积核_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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#计算机视觉_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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#人工智能_15

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

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_卷积核_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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_卷积核_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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#opencv_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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_卷积核_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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_卷积核_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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#opencv_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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#计算机视觉_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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#opencv_23

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

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_二值化_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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#opencv_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所示:

OpenCV这么简单为啥不学——1.7、实现OpenCV自带的七种形态学转换操作-_#人工智能_26

小讯
上一篇 2026-04-11 17:25
下一篇 2026-04-13 08:51

相关推荐

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