灰度变换是数字图像处理中一项基础且关键的技术,它通过特定的规则独立地改变图像中每个像素的灰度值,以达到改善图像质量的目的。其主要作用有:改善图像中质量,调整图像对比度,兴趣区域突出,显示校正等。
1.灰度线性变换.
全局调整图像的对比度和亮度。用于解决曝光不足或过度的图像矫正。通过一个线性函数 g(x,y) = alpha * f(x,y) + beta全局调整图像像素值。
python
def linear_transform(image_path, alpha=1.5, beta=50):
"""
对图像进行线性变换
:param image_path: 图像路径
:param alpha: 对比度系数 (>1增强对比度, <1减弱对比度)
:param beta: 亮度调整量
:return: 变换后的图像
"""
# 读取图像,0表示以灰度模式读取
img = cv2.imread(image_path, 0)
if img is None:
print("错误:无法加载图像,请检查路径是否正确")
return None
# 进行线性变换并确保像素值在0-255之间
transformed_img = np.clip(alpha * img + beta, 0, 255).astype(np.uint8)
# 显示结果
cv2.imshow('Original Image', img)
cv2.imshow('Linear Transformed Image', transformed_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
return transformed_img
# 使用示例
linear_transform('D:\\photo\\lena.tif', alpha=1.5, beta=20)
2.图像分段线性变换。
指对不同灰度区间采用不同的线性变换,从而有针对性地增强图像特定部分。
python
def piecewise_linear_transform(image_path, points):
"""
分段线性变换
:param image_path: 图像路径
:param points: 分段点列表,格式为 [(r1, s1), (r2, s2), ...]
:return: 变换后的图像
"""
img = cv2.imread(image_path, 0)
if img is None:
print("错误:无法加载图像")
return None
# 创建查找表(LUT),提高运算效率[6](@ref)
lut = np.zeros(256, dtype=np.uint8)
points = sorted(points) # 按输入灰度值排序
points = [(0, 0)] + points + [(255, 255)] # 确保覆盖整个0-255范围
for i in range(len(points) - 1):
r1, s1 = points[i]
r2, s2 = points[i + 1]
# 对每个区间进行线性变换
if r1 != r2:
k = (s2 - s1) / (r2 - r1)
for r in range(r1, r2 + 1):
lut[r] = np.clip(s1 + k * (r - r1), 0, 255)
transformed_img = cv2.LUT(img, lut) # 应用查找表
cv2.imshow('Original', img)
cv2.imshow('Piecewise Linear', transformed_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
return transformed_img
# 使用示例:突出中间灰度区域(50-150),将其拉伸到0-255
piecewise_linear_transform('D:\\photo\\lena.tif', [(50, 0), (150, 255)])
3. 直方图均衡化。
将图像的直方图分布拉伸得更加均匀,有效增强图像整体对比度,尤其适用于灰度集中在一个狭窄范围的图像。
python
def histogram_equalization(image_path):
"""
直方图均衡化
:param image_path: 图像路径
"""
img = cv2.imread(image_path, 0)
if img is None:
print("错误:无法加载图像")
return
# 使用OpenCV内置函数进行直方图均衡化[10,11](@ref)
equalized_img = cv2.equalizeHist(img)
# 显示原图与均衡化后的图像及其直方图
plt.figure(figsize=(10, 8))
plt.subplot(2, 2, 1)
plt.imshow(img, cmap='gray')
plt.title('Original Image')
plt.subplot(2, 2, 2)
plt.imshow(equalized_img, cmap='gray')
plt.title('Equalized Image')
plt.subplot(2, 2, 3)
plt.hist(img.ravel(), 256, [0, 256])
plt.title('Original Histogram')
plt.subplot(2, 2, 4)
plt.hist(equalized_img.ravel(), 256, [0, 256])
plt.title('Equalized Histogram')
plt.tight_layout()
plt.show()
# 使用示例
histogram_equalization('your_image.jpg')
4. 灰度级分层。
将特定灰度区间内的像素值设置为最大值(如白色),其他区域保持不变,用于突出显示图像中的特定目标。
python
def gray_level_slicing(image_path, r_left=100, r_right=200, highlight_max=255):
"""
灰度级分层:突出显示特定灰度范围
:param image_path: 图像路径
:param r_left: 目标灰度区间下限
:param r_right: 目标灰度区间上限
:param highlight_max: 突出显示的灰度值(通常为255,白色)
:return: 变换后的图像
"""
img = cv2.imread(image_path, 0)
if img is None:
print("错误:无法加载图像")
return None
# 创建与原始图像相同尺寸的输出图像
result_img = np.zeros_like(img)
# 遍历每个像素,进行分层处理
for i in range(img.shape[0]):
for j in range(img.shape[1]):
if r_left <= img[i, j] <= r_right:
result_img[i, j] = highlight_max # 在目标区间内,置为突出值(如白色)
else:
result_img[i, j] = img[i, j] # 不在目标区间,保留原值[3](@ref)
cv2.imshow('Original Image', img)
cv2.imshow('Gray Level Slicing Result', result_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
return result_img
# 使用示例:突出灰度值在100到200之间的区域
gray_level_slicing('your_image.jpg', r_left=100, r_right=200)
5. 阈值处理。
将灰度图像转换为黑白二值图像,常用于图像分割和轮廓提取。
python
import cv2
import numpy as np
def threshold_processing(image_path, thresh=127, maxval=255, mode=cv2.THRESH_BINARY):
"""
图像阈值处理
:param image_path: 图像路径
:param thresh: 阈值
:param maxval: 超过阈值时赋予的新值
:param mode: 阈值化类型,如cv2.THRESH_BINARY(最常用)[4](@ref)
:return: 二值化后的图像
"""
img = cv2.imread(image_path, 0)
if img is None:
print("错误:无法加载图像")
return None
# 应用阈值处理[4](@ref)
_, binary_img = cv2.threshold(img, thresh, maxval, mode)
cv2.imshow('Original Image', img)
cv2.imshow('Binary Image', binary_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
return binary_img
# 使用示例
threshold_processing('your_image.jpg', thresh=127)
# 自适应阈值处理(适合光照不均的图像)[4](@ref)
def adaptive_threshold_processing(image_path):
img = cv2.imread(image_path, 0)
if img is None:
print("错误:无法加载图像")
return None
# 自适应阈值处理,根据图像局部区域亮度动态确定阈值[4](@ref)
adaptive_binary = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2)
cv2.imshow('Original', img)
cv2.imshow('Adaptive Binary', adaptive_binary)
cv2.waitKey(0)
cv2.destroyAllWindows()
return adaptive_binary
# 使用自适应阈值
adaptive_threshold_processing('D:\\photo\\bf.jpg')
结果如下图所示:
