一、灰度级形态学
灰度级形态学将形态学操作从二值图像扩展到灰度图像。灰度形态学处理也有腐蚀、膨胀、开运算、闭运算、顶帽操作、低帽操作等操作,可以实现图像平滑、图像增强、图像分割功能。
把图像像素点的灰度值视为高度,不同的灰度级表示不同的高度,整个图像就像一张高低起伏的地形图。明亮的区域(灰度值大)相当于高山,黑暗的区域(灰度值小)相当于深谷,边缘区域即明亮与黑暗的交界相当于悬崖。
二、灰度顶帽变换和灰度底帽运算
-
图像相减结合开运算和闭运算,就得到顶帽变换和底帽变换。
灰度图像f 的顶帽变换定义为原图像减去图像开运算结果:
-
开运算可以删除暗背景下的亮区域,顶帽变换可以得到原图中的亮区域,因此又称白顶帽变换。
类似地,灰度图像 f 的低帽变换定义为图像闭运算结果减去原图像:
闭运算可以删除亮背景下的暗区域,底帽变换可以得到原图中的暗区域,因此又称黑底帽变换。
OpenCV 中的函数 cv.morphologyEx 可以实现图像的顶帽运算和底帽运算,参数 op 则要分别设为 MORPH_TOPHAT、MORPH_BLACKHAT。
三、例程
- 10.30:灰度顶帽变换校正阴影
均匀光照对于从背景中提取目标十分重要,顶帽变换的重要用途就是校正不均匀光照的影响。
本例图像是在非均匀光照条件下拍摄的,图像底部和右侧的暗色区域比较明显。
如果直接用 Otsu 最优阈值处理方法对灰度图像进行二值化处理,在暗区域的分割出现错误,一些米粒未能从背景中提取出来,而在左上角的亮区域则把部分背景理解为米粒。
我们可以先对图像进行顶帽运算,减弱图像中亮端和暗端的差别,再用 Otsu 最优阈值处理方法进行二值化处理,就可以得到正确的阈值处理结果。
import cv2
import numpy as np
from matplotlib import pyplot as plt
# 10.30: 灰度顶帽变换校正阴影
imgGray = cv2.imread("../images/Fig0940a.tif", flags=0) # flags=0 灰度图像
# 直接用 Otsu 最优阈值处理方法进行二值化处理
ret, imgBin = cv2.threshold(imgGray, 127, 255, cv2.THRESH_OTSU) # 二值化处理,黑色背景
# 顶帽运算后再用 Otsu 最优阈值处理方法进行二值化处理
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (50, 50)) # 十字交叉结构元
imgThat = cv2.morphologyEx(imgGray, cv2.MORPH_TOPHAT, element) # 顶帽运算
ret, imgThatBin = cv2.threshold(imgThat, 127, 255, cv2.THRESH_OTSU) # 二值化处理,黑色背景
plt.figure(figsize=(9, 6))
plt.subplot(221), plt.title("Origin"), plt.axis('off')
plt.imshow(imgGray, cmap='gray', vmin=0, vmax=255)
plt.subplot(222), plt.title("Otsu binary"), plt.axis('off')
plt.imshow(imgBin, cmap='gray', vmin=0, vmax=255)
plt.subplot(223), plt.title("Tophat image"), plt.axis('off')
plt.imshow(imgThat, cmap='gray', vmin=0, vmax=255)
plt.subplot(224), plt.title("Tophat binary"), plt.axis('off')
plt.imshow(imgThatBin, cmap='gray', vmin=0, vmax=255)
plt.tight_layout()
plt.show()
四、资料
youcans_的博客:
https://blog.csdn.net/youcans/article/details/123565771