完整代码在 FchZero/Digita_Image_Processing_Experiment (github.com)
一、实验目的
1.熟悉并学会opencv-python中图像增强的相关函数;
2.了解图像增强的方法、去噪的方法和效果。
二、实验原理
图像增强是指按特定的需要突出一幅图像中的某些信息,同时,消弱或去除某些不需要的信息的处理方法。其主要目的是处理后的图像对某些特定的应用比原来的图像更加有效。
图像增强技术主要有直方图修改处理、图像平滑化处理、图像尖锐化处理和彩色处理技术等。
1.直方图
直方图是多种空间域处理技术的基础。直方图操作能有效地用于图像增强。除了提供有用的图像统计资料外,直方图固有的信息在其他图像处理应用中也是非常有用的,如图像压缩与分割。直方图在软件中易于计算,也适用于商用硬件设备,因此,它们成为了实时图像处理的一个流行工具。直方图是图像的最基本的统计特征,它反映的是图像的灰度值的分布情况。直方图均衡化的目的是使图像在整个灰度值动态变化范围内的分布均匀化,改善图像的亮度分布状态,增强图像的视觉效果。灰度直方图是图像预处理中涉及最广泛的基本概念之一。图像的直方图事实上就是图像的亮度分布的概率密度函数,是一幅图像的所有象素集合的最基本的统计规律。直方图反映了图像的明暗分布规律,可以通过图像变换进行直方图调整,获得较好的视觉效果。直方图均衡化是通过灰度变换将一幅图像转换为另一幅具有均衡直方图,即在每个灰度级上都具有相同的象素点数的过程。
2.图像锐化
图像锐化(image sharpening)是补偿图像的轮廓,增强图像的边缘及灰度跳变的部 分,使图像变得清晰,分为空域处理和频域处理两类。
2.1.空域
2.2.频域
3.图像平滑
图像平滑是对图像作低通滤波,可在空间域或频率域实现。
3.1.空域
3.2.频域
三、实验内容、核心算法/代码及结果
1.绘制灰度图像直方图并对直方图均衡化
# 灰度直方图
img_GRAY = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imshow("gray", img_GRAY)
cv.waitKey(0)
# 绘制直方图
hist_ori = cv.calcHist([img_GRAY], [0], None, [256], [0, 255])
plt.figure()
plt.plot(hist_ori)
# 进行直方图均衡化。
equ = cv.equalizeHist(img_GRAY)
cv.imshow("equ", equ)
cv.waitKey(0)
cv.destroyAllWindows()
hist_equ = cv.calcHist([equ], [0], None, [256], [0, 255])
plt.figure()
plt.plot(hist_equ)
plt.show()
2.利用模版进行空域滤波
# 空域中的平滑滤波
img_GRAY = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 进行均值滤波
# 模板大小为 3*5, 模板的大小是可以设定的
blur_mean = cv.blur(img_GRAY, (3, 5))
box_mean = cv.boxFilter(img_GRAY, -1, (3, 5))
cv.imshow("blur_mean", blur_mean)
cv.waitKey(0)
cv.imshow("box_mean", box_mean)
cv.waitKey(0)
# 进行高斯模糊滤波
# (5,5)表示的是卷积模板的大小,0 表示的是沿 x 与 y 方向上的标准差
blur_gauss = cv.GaussianBlur(img_GRAY, (5, 5), 0)
cv.imshow("blur_gauss", blur_gauss)
cv.waitKey(0)
# 进行中值滤波
# 5 表示的是卷积模板的大小
blur_mid = cv.medianBlur(img_GRAY, 5)
cv.imshow("blur_mid", blur_mid)
cv.waitKey(0)
# 空域中的锐化滤波
img_GRAY = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# Roberts 算子
# 图像高斯滤波去噪
blur = cv.GaussianBlur(img_GRAY, (3, 3), 1, 1) # 核尺寸通过对图像的调节自行定义
# 图像阈值化处理
ret, thresh = cv.threshold(blur, 127, 255, cv.THRESH_BINARY) # 二进制阈值化
# 调用 Roberts 算法的 OpenCV 库函数进行图像轮廓提取
R_kernelx = np.array([[-1, 0], [0, 1]], dtype=int)
R_kernely = np.array([[0, -1], [1, 0]], dtype=int)
R_x = cv.filter2D(thresh, cv.CV_16S, R_kernelx)
R_y = cv.filter2D(thresh, cv.CV_16S, R_kernely)
# 转 uint8
R_absX = cv.convertScaleAbs(R_x)
R_absY = cv.convertScaleAbs(R_y)
Roberts = cv.addWeighted(R_absX, 0.5, R_absY, 0.5, 0)
cv.imshow("Roberts", Roberts)
cv.waitKey()
# Prewitt 算子
P_S_kernelx = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]], dtype=int)
P_S_kernely = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]], dtype=int)
P_x = cv.filter2D(thresh, -1, P_S_kernelx)
P_y = cv.filter2D(thresh, -1, P_S_kernely)
P_absX = cv.convertScaleAbs(P_x)
P_absY = cv.convertScaleAbs(P_y)
Prewitt = cv.addWeighted(P_absX, 0.5, P_absY, 0.5, 0)
cv.imshow("Prewitt", Prewitt)
cv.waitKey()
# Sobel 算子
S_x = cv.Sobel(thresh, cv.CV_16S, 1, 0) # 对 x 求一阶导
S_y = cv.Sobel(thresh, cv.CV_16S, 0, 1) # 对 y 求一阶导
S_absX = cv.convertScaleAbs(S_x) # 对 x 取绝对值,并将图像转换为 8 位图
S_absY = cv.convertScaleAbs(S_y) # 对 y 取绝对值,并将图像转换为 8 位图
Sobel = cv.addWeighted(S_absX, 0.5, S_absY, 0.5, 0)
cv.imshow("Sobel", Sobel)
cv.waitKey()
3.分别利用常见低通(平滑)滤波器与高通(锐化)滤波器进行频域滤波
# 频域中的低通(平滑)滤波器
img_GRAY = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 傅里叶变换
img_dft = np.fft.fft2(img_GRAY)
dft_shift = np.fft.fftshift(img_dft)
# 低通滤波
h, w = dft_shift.shape[0:2]
h_center, w_center = int(h / 2), int(w / 2)
dft_shift_black = np.zeros((h, w), np.uint8)
# 中心点加减滤波尺寸的一半,刚好形成一个定义尺寸的滤波大小,然后设置为1,保留低频部分
dft_shift_black[
h_center - int(size / 2) : h_center + int(size / 2),
w_center - int(size / 2) : w_center + int(size / 2),
] = 1
dft_shift = dft_shift * dft_shift_black # 将定义的低通滤波与传入的傅里叶频谱图一一对应相乘,得到低通滤波
res = np.log(np.abs(dft_shift))
# 傅里叶逆变换
idft_shift = np.fft.ifftshift(dft_shift)
ifimg = np.fft.ifft2(idft_shift)
ifimg = np.abs(ifimg)
cv.imshow("lowPassFilter", np.int8(ifimg))
cv.waitKey(0)
# 频域中的高通(锐化)滤波器
img_GRAY = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 傅里叶变换
img_dft = np.fft.fft2(img_GRAY)
dft_shift = np.fft.fftshift(img_dft) # 将频域从左上角移动到中间
# 高通滤波
h, w = dft_shift.shape[0:2] # 获取图像属性(高、宽和图像通道数)
h_center, w_center = int(h / 2), int(w / 2) # 找到傅里叶频谱图的中心点
# 中心点加减滤波尺寸的一半,刚好形成一个定义尺寸的滤波大小,然后设置为0
dft_shift[
h_center - int(size / 2) : h_center + int(size / 2),
w_center - int(size / 2) : w_center + int(size / 2),
] = 0
res = np.log(np.abs(dft_shift))
# 傅里叶逆变换
idft_shift = np.fft.ifftshift(dft_shift) # 将频域从中间移动到左上角
img_idft = np.fft.ifft2(idft_shift)
img_idft = np.abs(img_idft)
cv.imshow("highPassFilter", np.int8(img_idft))
cv.waitKey(0)
完整代码在FchZero/Digita_Image_Processing_Experiment (github.com)