一、模块导入与环境准备import cv2 import numpy as np import matplotlib.pyplot as plt import oscv2OpenCV 库提供图像读取、写入、颜色空间转换、直方图均衡化等函数。numpy科学计算库用于高效的数组运算图像本质上就是 NumPy 数组。matplotlib.pyplot绘图库用于显示图像和绘制直方图。os操作系统接口库用于创建输出目录。二、准备工作创建输出目录output_dir output_1 os.makedirs(output_dir, exist_okTrue)output_dir定义输出文件夹名称为output_1。os.makedirs()递归创建目录exist_okTrue表示若目录已存在不报错保证每次运行都能正常保存结果。三、自定义工具函数读取灰度图像def load_gray_image(path):定义函数load_gray_image接收一个参数path图像文件路径负责将任意图像统一读取为灰度图。img cv2.imread(path, cv2.IMREAD_UNCHANGED)cv2.imread()读取图像文件。cv2.IMREAD_UNCHANGED保留原始图像的通道数和位深度不自动转换。if img is None: raise FileNotFoundError(f图像文件 {path} 未找到请检查路径)若图像读取失败返回None抛出一个明确的文件未找到异常方便定位错误。if len(img.shape) 3: print(f[提示] {path} 是彩色图已自动转换为灰度图) return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)len(img.shape) 3判断是否为三通道彩色图像形状为(高, 宽, 3)。若是彩色图打印提示信息并用cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)将 BGR 彩色图转换为单通道灰度图后返回。return img若已是灰度图二维数组直接返回。四、任务1反色处理def task1_invert(original_gray):定义函数task1_invert接收正常光照的灰度图像实现底片效果的反色处理。inverted 255 - original_gray # s 255 - r反色公式s 255 - r对每个像素值r用 255 减去暗变亮、亮变暗呈现底片效果。利用 NumPy 广播机制对整幅图像一次性完成运算。plt.figure(figsize(10, 4)) plt.subplot(1, 2, 1) plt.imshow(original_gray, cmapgray, vmin0, vmax255) plt.title(Original Gray Image) plt.axis(off)创建 10×4 英寸画布1行2列布局左侧显示原图。vmin0, vmax255固定灰度显示范围确保0为黑、255为白。plt.subplot(1, 2, 2) plt.imshow(inverted, cmapgray, vmin0, vmax255) plt.title(Inverted Image (255 - r)) plt.axis(off) plt.tight_layout() plt.show()右侧显示反色图像tight_layout()调整间距show()渲染显示。cv2.imwrite(os.path.join(output_dir, inverted.jpg), inverted) print([任务1] 反色图像已保存)cv2.imwrite()将反色图像保存为 JPG 文件到输出目录并打印完成提示。五、任务2对数变换def task2_log_transform(low_light, over_exposed):定义函数接收低照度图像low_light和曝光过度图像over_exposed两幅灰度图。5.1 内部辅助函数对数变换def log_transform(img): img_float img.astype(np.float32) c 255.0 / np.log(1 np.max(img_float)) log_img c * np.log(1 img_float) return np.clip(log_img, 0, 255).astype(np.uint8)img.astype(np.float32)将 uint8 类型转为 float32避免对数运算溢出。c缩放常数计算公式为255 / log(1 max)使变换后最大像素值恰好映射到 255。np.log(1 img_float)对数变换核心加1防止对0取对数导致负无穷。np.clip(log_img, 0, 255)裁剪到 [0, 255] 范围防止越界。.astype(np.uint8)转回 8 位无符号整数类型用于显示和保存。log_low log_transform(low_light) log_over log_transform(over_exposed)分别对低照度和过度曝光图像执行对数变换。5.2 显示与直方图绘制以低照度为例plt.figure(figsize(12, 8)) plt.subplot(2, 2, 1) plt.imshow(low_light, cmapgray, vmin0, vmax255) plt.title(Low Light Original) plt.axis(off)2行2列布局左上角显示低照度原图。plt.subplot(2, 2, 2) plt.imshow(log_low, cmapgray, vmin0, vmax255) plt.title(After Log Transform) plt.axis(off)右上角显示对数变换后的低照度图像。plt.subplot(2, 2, 3) plt.hist(low_light.ravel(), bins256, range[0, 256], colorgray, alpha0.7) plt.title(Low Light Histogram)plt.hist()绘制直方图。.ravel()将二维图像数组展平为一维便于统计。bins256256 个柱对应 0-255 每个灰度级。range[0, 256]统计范围为 [0, 256)。alpha0.7设置透明度。plt.subplot(2, 2, 4) plt.hist(log_low.ravel(), bins256, range[0, 256], colorgray, alpha0.7) plt.title(Log Transformed Histogram) plt.tight_layout() plt.show()右下角绘制变换后的直方图展示对数变换对灰度分布的扩展效果。曝光过度图像的显示逻辑完全相同仅替换数据源。5.3 保存结果cv2.imwrite(os.path.join(output_dir, log_low.jpg), log_low) cv2.imwrite(os.path.join(output_dir, log_over.jpg), log_over) print([任务2] 对数变换结果已保存)六、任务3线性拉伸与直方图均衡化def task3_histogram_enhancement(low_light, over_exposed):定义函数对低照度和过度曝光图像分别进行线性拉伸和直方图均衡化并对比展示。6.1 内部辅助函数def linear_stretch(img): min_val, max_val np.min(img), np.max(img) if max_val min_val: return img return ((img - min_val) / (max_val - min_val) * 255).astype(np.uint8)线性拉伸公式(x - min) / (max - min) * 255将原图灰度范围线性映射到 [0, 255]。max_val min_val若图像灰度值全部相同常量图像直接返回原图避免除零错误。def equalize(img): return cv2.equalizeHist(img)cv2.equalizeHist()OpenCV 的直方图均衡化函数自动重新分布灰度值使直方图尽可能平坦增强全局对比度。6.2 执行增强low_linear linear_stretch(low_light) low_eq equalize(low_light) over_linear linear_stretch(over_exposed) over_eq equalize(over_exposed)分别生成四幅增强结果。6.3 三组对比显示以低照度为例plt.figure(figsize(15, 10))2行3列布局上排三幅图原图、线性拉伸、均衡化下排对应直方图。plt.subplot(2, 3, 1) plt.imshow(low_light, cmapgray, vmin0, vmax255) plt.title(Low Light Original) plt.axis(off)左上低照度原图。plt.subplot(2, 3, 2) plt.imshow(low_linear, cmapgray, vmin0, vmax255) plt.title(Linear Stretch) plt.axis(off)中上线性拉伸结果。plt.subplot(2, 3, 3) plt.imshow(low_eq, cmapgray, vmin0, vmax255) plt.title(Histogram Equalization) plt.axis(off)右上直方图均衡化结果。plt.subplot(2, 3, 4) plt.hist(low_light.ravel(), bins256, range[0, 256], colorgray, alpha0.7) plt.title(Original Histogram)左下原图直方图反映灰度集中在暗区的特点。plt.subplot(2, 3, 5) plt.hist(low_linear.ravel(), bins256, range[0, 256], colorgray, alpha0.7) plt.title(Linear Stretch Histogram)中下线性拉伸后直方图分布被均匀拉开但保持原有相对形状。plt.subplot(2, 3, 6) plt.hist(low_eq.ravel(), bins256, range[0, 256], colorgray, alpha0.7) plt.title(Equalized Histogram) plt.tight_layout() plt.show()右下均衡化后直方图分布更加均匀平坦。曝光过度图像的三组对比采用完全相同的布局。6.4 保存结果cv2.imwrite(os.path.join(output_dir, low_linear.jpg), low_linear) cv2.imwrite(os.path.join(output_dir, low_eq.jpg), low_eq) cv2.imwrite(os.path.join(output_dir, over_linear.jpg), over_linear) cv2.imwrite(os.path.join(output_dir, over_eq.jpg), over_eq) print([任务3] 线性拉伸与直方图均衡化结果已保存)七、主程序入口if __name__ __main__:Python 的惯用写法确保该脚本被直接运行时才执行以下代码被 import 时不执行。img_normal_path ./DIP2026/DIP2026/bird.jpg img_low_path ./DIP2026/DIP2026/night.jpg img_over_path ./DIP2026/DIP2026/car_1.jpg定义三幅测试图像的路径变量分别为正常光照、低照度、曝光过度图像。original load_gray_image(img_normal_path) low load_gray_image(img_low_path) over load_gray_image(img_over_path)调用load_gray_image()读取并统一转换为灰度图。task1_invert(original) task2_log_transform(low, over) task3_histogram_enhancement(low, over)按顺序执行三个实验任务。print(f\n所有实验完成结果保存在 {output_dir} 文件夹中。)打印完成提示。八、整体流程总结任务功能核心算法输入输出文件任务1反色处理s 255 - r正常光照图inverted.jpg任务2对数变换c·log(1r)低照度图 过曝图log_low.jpg,log_over.jpg任务3线性拉伸与均衡化(x-min)/(max-min)*255equalizeHist低照度图 过曝图low_linear.jpg,low_eq.jpg,over_linear.jpg,over_eq.jpg每个任务都包含处理 → 可视化对比图像 直方图 → 保存三个环节便于观察灰度变换对图像质量和像素分布的影响。框图结构说明层级节点说明准备阶段创建输出目录确保output_1文件夹存在数据加载三路读取load_gray_image()自动将彩色图转灰度任务1反色处理一路输入正常图公式简单直接输出1个文件任务2对数变换两路输入低照度过曝内部定义log_transform()每路显示4幅图原图、变换图、两直方图输出2个文件任务3线性拉伸与均衡化两路输入每路执行linear_stretch()和cv2.equalizeHist()两种算法每路显示6幅图3图3直方图输出4个文件收尾结束三个任务按顺序串行执行完毕后程序终止三种灰度变换算法对比算法公式适用场景效果反色s 255 - r正常光照亮暗反转底片效果对数变换s c·log(1r)低照度 / 过曝压缩高灰度、拉伸低灰度线性拉伸(x-min)/(max-min)×255对比度不足线性展开灰度范围直方图均衡化累计分布函数映射对比度不足非线性展平灰度分布
机器学习篇---数字图像增强(灰度变换与直方图均衡)
发布时间:2026/6/1 16:21:01
一、模块导入与环境准备import cv2 import numpy as np import matplotlib.pyplot as plt import oscv2OpenCV 库提供图像读取、写入、颜色空间转换、直方图均衡化等函数。numpy科学计算库用于高效的数组运算图像本质上就是 NumPy 数组。matplotlib.pyplot绘图库用于显示图像和绘制直方图。os操作系统接口库用于创建输出目录。二、准备工作创建输出目录output_dir output_1 os.makedirs(output_dir, exist_okTrue)output_dir定义输出文件夹名称为output_1。os.makedirs()递归创建目录exist_okTrue表示若目录已存在不报错保证每次运行都能正常保存结果。三、自定义工具函数读取灰度图像def load_gray_image(path):定义函数load_gray_image接收一个参数path图像文件路径负责将任意图像统一读取为灰度图。img cv2.imread(path, cv2.IMREAD_UNCHANGED)cv2.imread()读取图像文件。cv2.IMREAD_UNCHANGED保留原始图像的通道数和位深度不自动转换。if img is None: raise FileNotFoundError(f图像文件 {path} 未找到请检查路径)若图像读取失败返回None抛出一个明确的文件未找到异常方便定位错误。if len(img.shape) 3: print(f[提示] {path} 是彩色图已自动转换为灰度图) return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)len(img.shape) 3判断是否为三通道彩色图像形状为(高, 宽, 3)。若是彩色图打印提示信息并用cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)将 BGR 彩色图转换为单通道灰度图后返回。return img若已是灰度图二维数组直接返回。四、任务1反色处理def task1_invert(original_gray):定义函数task1_invert接收正常光照的灰度图像实现底片效果的反色处理。inverted 255 - original_gray # s 255 - r反色公式s 255 - r对每个像素值r用 255 减去暗变亮、亮变暗呈现底片效果。利用 NumPy 广播机制对整幅图像一次性完成运算。plt.figure(figsize(10, 4)) plt.subplot(1, 2, 1) plt.imshow(original_gray, cmapgray, vmin0, vmax255) plt.title(Original Gray Image) plt.axis(off)创建 10×4 英寸画布1行2列布局左侧显示原图。vmin0, vmax255固定灰度显示范围确保0为黑、255为白。plt.subplot(1, 2, 2) plt.imshow(inverted, cmapgray, vmin0, vmax255) plt.title(Inverted Image (255 - r)) plt.axis(off) plt.tight_layout() plt.show()右侧显示反色图像tight_layout()调整间距show()渲染显示。cv2.imwrite(os.path.join(output_dir, inverted.jpg), inverted) print([任务1] 反色图像已保存)cv2.imwrite()将反色图像保存为 JPG 文件到输出目录并打印完成提示。五、任务2对数变换def task2_log_transform(low_light, over_exposed):定义函数接收低照度图像low_light和曝光过度图像over_exposed两幅灰度图。5.1 内部辅助函数对数变换def log_transform(img): img_float img.astype(np.float32) c 255.0 / np.log(1 np.max(img_float)) log_img c * np.log(1 img_float) return np.clip(log_img, 0, 255).astype(np.uint8)img.astype(np.float32)将 uint8 类型转为 float32避免对数运算溢出。c缩放常数计算公式为255 / log(1 max)使变换后最大像素值恰好映射到 255。np.log(1 img_float)对数变换核心加1防止对0取对数导致负无穷。np.clip(log_img, 0, 255)裁剪到 [0, 255] 范围防止越界。.astype(np.uint8)转回 8 位无符号整数类型用于显示和保存。log_low log_transform(low_light) log_over log_transform(over_exposed)分别对低照度和过度曝光图像执行对数变换。5.2 显示与直方图绘制以低照度为例plt.figure(figsize(12, 8)) plt.subplot(2, 2, 1) plt.imshow(low_light, cmapgray, vmin0, vmax255) plt.title(Low Light Original) plt.axis(off)2行2列布局左上角显示低照度原图。plt.subplot(2, 2, 2) plt.imshow(log_low, cmapgray, vmin0, vmax255) plt.title(After Log Transform) plt.axis(off)右上角显示对数变换后的低照度图像。plt.subplot(2, 2, 3) plt.hist(low_light.ravel(), bins256, range[0, 256], colorgray, alpha0.7) plt.title(Low Light Histogram)plt.hist()绘制直方图。.ravel()将二维图像数组展平为一维便于统计。bins256256 个柱对应 0-255 每个灰度级。range[0, 256]统计范围为 [0, 256)。alpha0.7设置透明度。plt.subplot(2, 2, 4) plt.hist(log_low.ravel(), bins256, range[0, 256], colorgray, alpha0.7) plt.title(Log Transformed Histogram) plt.tight_layout() plt.show()右下角绘制变换后的直方图展示对数变换对灰度分布的扩展效果。曝光过度图像的显示逻辑完全相同仅替换数据源。5.3 保存结果cv2.imwrite(os.path.join(output_dir, log_low.jpg), log_low) cv2.imwrite(os.path.join(output_dir, log_over.jpg), log_over) print([任务2] 对数变换结果已保存)六、任务3线性拉伸与直方图均衡化def task3_histogram_enhancement(low_light, over_exposed):定义函数对低照度和过度曝光图像分别进行线性拉伸和直方图均衡化并对比展示。6.1 内部辅助函数def linear_stretch(img): min_val, max_val np.min(img), np.max(img) if max_val min_val: return img return ((img - min_val) / (max_val - min_val) * 255).astype(np.uint8)线性拉伸公式(x - min) / (max - min) * 255将原图灰度范围线性映射到 [0, 255]。max_val min_val若图像灰度值全部相同常量图像直接返回原图避免除零错误。def equalize(img): return cv2.equalizeHist(img)cv2.equalizeHist()OpenCV 的直方图均衡化函数自动重新分布灰度值使直方图尽可能平坦增强全局对比度。6.2 执行增强low_linear linear_stretch(low_light) low_eq equalize(low_light) over_linear linear_stretch(over_exposed) over_eq equalize(over_exposed)分别生成四幅增强结果。6.3 三组对比显示以低照度为例plt.figure(figsize(15, 10))2行3列布局上排三幅图原图、线性拉伸、均衡化下排对应直方图。plt.subplot(2, 3, 1) plt.imshow(low_light, cmapgray, vmin0, vmax255) plt.title(Low Light Original) plt.axis(off)左上低照度原图。plt.subplot(2, 3, 2) plt.imshow(low_linear, cmapgray, vmin0, vmax255) plt.title(Linear Stretch) plt.axis(off)中上线性拉伸结果。plt.subplot(2, 3, 3) plt.imshow(low_eq, cmapgray, vmin0, vmax255) plt.title(Histogram Equalization) plt.axis(off)右上直方图均衡化结果。plt.subplot(2, 3, 4) plt.hist(low_light.ravel(), bins256, range[0, 256], colorgray, alpha0.7) plt.title(Original Histogram)左下原图直方图反映灰度集中在暗区的特点。plt.subplot(2, 3, 5) plt.hist(low_linear.ravel(), bins256, range[0, 256], colorgray, alpha0.7) plt.title(Linear Stretch Histogram)中下线性拉伸后直方图分布被均匀拉开但保持原有相对形状。plt.subplot(2, 3, 6) plt.hist(low_eq.ravel(), bins256, range[0, 256], colorgray, alpha0.7) plt.title(Equalized Histogram) plt.tight_layout() plt.show()右下均衡化后直方图分布更加均匀平坦。曝光过度图像的三组对比采用完全相同的布局。6.4 保存结果cv2.imwrite(os.path.join(output_dir, low_linear.jpg), low_linear) cv2.imwrite(os.path.join(output_dir, low_eq.jpg), low_eq) cv2.imwrite(os.path.join(output_dir, over_linear.jpg), over_linear) cv2.imwrite(os.path.join(output_dir, over_eq.jpg), over_eq) print([任务3] 线性拉伸与直方图均衡化结果已保存)七、主程序入口if __name__ __main__:Python 的惯用写法确保该脚本被直接运行时才执行以下代码被 import 时不执行。img_normal_path ./DIP2026/DIP2026/bird.jpg img_low_path ./DIP2026/DIP2026/night.jpg img_over_path ./DIP2026/DIP2026/car_1.jpg定义三幅测试图像的路径变量分别为正常光照、低照度、曝光过度图像。original load_gray_image(img_normal_path) low load_gray_image(img_low_path) over load_gray_image(img_over_path)调用load_gray_image()读取并统一转换为灰度图。task1_invert(original) task2_log_transform(low, over) task3_histogram_enhancement(low, over)按顺序执行三个实验任务。print(f\n所有实验完成结果保存在 {output_dir} 文件夹中。)打印完成提示。八、整体流程总结任务功能核心算法输入输出文件任务1反色处理s 255 - r正常光照图inverted.jpg任务2对数变换c·log(1r)低照度图 过曝图log_low.jpg,log_over.jpg任务3线性拉伸与均衡化(x-min)/(max-min)*255equalizeHist低照度图 过曝图low_linear.jpg,low_eq.jpg,over_linear.jpg,over_eq.jpg每个任务都包含处理 → 可视化对比图像 直方图 → 保存三个环节便于观察灰度变换对图像质量和像素分布的影响。框图结构说明层级节点说明准备阶段创建输出目录确保output_1文件夹存在数据加载三路读取load_gray_image()自动将彩色图转灰度任务1反色处理一路输入正常图公式简单直接输出1个文件任务2对数变换两路输入低照度过曝内部定义log_transform()每路显示4幅图原图、变换图、两直方图输出2个文件任务3线性拉伸与均衡化两路输入每路执行linear_stretch()和cv2.equalizeHist()两种算法每路显示6幅图3图3直方图输出4个文件收尾结束三个任务按顺序串行执行完毕后程序终止三种灰度变换算法对比算法公式适用场景效果反色s 255 - r正常光照亮暗反转底片效果对数变换s c·log(1r)低照度 / 过曝压缩高灰度、拉伸低灰度线性拉伸(x-min)/(max-min)×255对比度不足线性展开灰度范围直方图均衡化累计分布函数映射对比度不足非线性展平灰度分布