如何实现彩色图像光照均匀化?含已尝试代码及效果需求
解决图像光照均匀化问题的改进方案
看起来你当前的代码主要依赖CLAHE做局部对比度增强,但后续的锐化、二值化步骤其实偏离了「全局光照一致」的核心目标,而且CLAHE本身是局部增强,对于全局明暗不均的场景(比如一半亮一半暗的图像)效果有限。我来给你几个针对性的改进思路和代码示例:
问题分析
你的现有流程存在几个和目标不符的点:
- 转LAB空间用CLAHE增强L通道:CLAHE擅长提升局部暗部细节,但不会平衡全局光照,甚至可能让局部过曝或噪点加重
- 后续的锐化、阈值、降噪:这些是针对二值化的操作,会丢失原始图像的色彩和亮度层次,完全不符合「全局光照一致」的输出要求
改进方案1:全局光照估计与补偿
这个方法的核心是先估算图像的光照分量,再用原图除以光照分量来抵消光照不均,适合处理全局明暗差异大的场景:
import cv2 import numpy as np def normalize_illumination(img): # 转灰度图用于估算光照 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 大尺寸高斯模糊获取全局光照分布(核大小可根据图像尺寸调整) illumination = cv2.GaussianBlur(gray, (151, 151), 0) # 归一化光照图到0-1范围 illumination = illumination.astype(np.float32) / 255.0 # 原图转浮点型,对每个通道做光照补偿 img_float = img.astype(np.float32) / 255.0 normalized = np.zeros_like(img_float) for i in range(3): normalized[..., i] = img_float[..., i] / illumination # 把结果限制在0-255范围内并转成uint8格式 normalized = np.clip(normalized * 255, 0, 255).astype(np.uint8) return normalized # 测试代码 img = cv2.imread('new_sample/sample6.jpg', 1) original = img.copy() normalized_img = normalize_illumination(img) # 对比显示结果 stack_horizontal = np.concatenate((original, normalized_img), axis=1) cv2.imshow('Original vs Illumination Normalized', cv2.resize(stack_horizontal, (800, 600))) cv2.imwrite("illumination_normalized.jpg", normalized_img) cv2.waitKey() cv2.destroyAllWindows()
改进方案2:CLAHE结合全局亮度校准
如果还是想用CLAHE,可以先调整全局亮度,再做局部增强,避免局部过度增强的问题:
import cv2 import numpy as np img = cv2.imread('new_sample/sample6.jpg', 1) original = img.copy() lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB) l, a, b = cv2.split(lab) # 先把全局L通道亮度校准到均值127(中间灰),平衡整体明暗 l_mean = np.mean(l) l_global = cv2.convertScaleAbs(l, alpha=127/l_mean, beta=0) # 降低CLAHE的clipLimit,避免局部过度增强,同时增大tileGridSize覆盖更大区域 clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(16, 16)) l_clahe = clahe.apply(l_global) limg = cv2.merge((l_clahe, a, b)) final = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR) # 对比显示结果 stack_horizontal = np.concatenate((original, final), axis=1) cv2.imshow('Original vs Improved CLAHE', cv2.resize(stack_horizontal, (800, 600))) cv2.imwrite("clahe_improved.jpg", final) cv2.waitKey() cv2.destroyAllWindows()
改进方案3:Retinex算法(专业光照平衡)
Retinex算法专门针对光照不均场景,能同时保留细节和平衡全局光照,这里是简化版的多尺度实现:
import cv2 import numpy as np def single_scale_retinex(img, sigma): img_float = img.astype(np.float32) + 1e-8 # 避免除0错误 log_img = np.log10(img_float) blur = cv2.GaussianBlur(img_float, (0,0), sigma) log_blur = np.log10(blur) retinex = log_img - log_blur # 归一化到0-255范围 retinex = (retinex - np.min(retinex)) / (np.max(retinex) - np.min(retinex)) * 255 return retinex.astype(np.uint8) def multi_scale_retinex(img, sigmas=[15, 80, 250]): retinex = np.zeros_like(img, dtype=np.float32) # 多尺度融合,兼顾局部和全局光照 for sigma in sigmas: retinex += single_scale_retinex(img, sigma) retinex /= len(sigmas) return retinex.astype(np.uint8) # 测试代码 img = cv2.imread('new_sample/sample6.jpg', 1) original = img.copy() msr_img = multi_scale_retinex(img) # 对比显示结果 stack_horizontal = np.concatenate((original, msr_img), axis=1) cv2.imshow('Original vs MSR Normalized', cv2.resize(stack_horizontal, (800, 600))) cv2.imwrite("msr_normalized.jpg", msr_img) cv2.waitKey() cv2.destroyAllWindows()
你可以根据自己的图像场景选择合适的方案:如果是全局明暗差异大,优先用方案1;如果是局部暗部细节不足但全局光照还行,用方案2;如果追求更专业的光照平衡效果,方案3的Retinex会更合适。
内容的提问来源于stack exchange,提问作者Naman Gupta




