python 灰世界白平衡算法
白平衡是图像处理比较常见的一个概念,在采集图像的过程中,相机的感光元件或者镜头会对原始色彩造成影响,而白平衡技术通常可以用来校正这种光线和镜头对颜色影响。
灰度世界算法(Gray World)假设认为,一幅彩色图像中,RGB三个通道的颜色平均值是趋于同一个灰度值K的,所以如果当前的通道的均值与K值存在差异,就需要对该通道的像素值进行矫正,矫正的结果则是与K有关。K值的取法有两种,一种是取最大像素值的一般,即8位图中的127或者128;第二种是以三通道的均值来作为K值。
灰度世界白平衡算法流程如下:
(1)计算RGB三个通道各自的均值,得到Ravg、Gavg和Bavg ;
(2)取RGB均值的均值得到K值:K = ( Ravg + Gavg + Bavg ) / 3 ;
(3)计算各通道相对于K值的增益:
KR = K / Ravg
KG = K / Gavg
KB = K / Bavg
(4)根据增益逐个调整RGB三通道的像素值:
Rnew = R * KR
Gnew = G * KG
Bnew = B * KB
(5)调整输出,由于上面的计算可能存在溢出,因此需要对结果进行调整,调整有两种做法:
a)超出部分取255;
b)计算Rnew、Gnew、Bnew的最大值,然后映射回0到255。
python代码实现如下:
import cv2 import numpy as np img = cv2.imread('./cat.jpg') b,g,r = cv2.split(img) #图像bgr通道分离 avg_b = np.average(b) avg_g = np.average(g) avg_r = np.average(r) k = (avg_b+avg_g+avg_r)/3 #计算k值 kr = k/avg_r #计算rgb的增益(增益通常在0-2的浮点数之间) kb = k/avg_b kg = k/avg_g #根据增益逐个调整RGB三通道的像素值,超出部分取255(数据类型还是要转换回uint8) new_b = np.where((kb * b) > 255,255,kb*b).astype(np.uint8) new_g = np.where((kg * g) > 255,255,kg*g).astype(np.uint8) new_r = np.where((kr * r) > 255,255,kr*r).astype(np.uint8) # 合并三个通道 img_new = cv2.merge([new_b,new_g,new_r]) cv2.imshow('img',img) cv2.imshow('img_new',img_new) cv2.waitKey(0) cv2.destroyAllWindows()
把awb算法封装到函数中:
# coding=gbk 文件中有中文字符,将其转换为utf-8,否则编译会出错 import cv2 import numpy as np def AWB(image): img = cv2.imread(image) b,g,r = cv2.split(img) #图像bgr通道分离 avg_b = np.average(b) avg_g = np.average(g) avg_r = np.average(r) k = (avg_b+avg_g+avg_r)/3 #计算k值 kr = k/avg_r #计算rgb的增益(增益通常在0-2的浮点数之间) kb = k/avg_b kg = k/avg_g #根据增益逐个调整RGB三通道的像素值,超出部分取255(数据类型还是要转换回uint8) new_b = np.where((kb * b) > 255, 255, kb*b).astype(np.uint8) new_g = np.where((kg * g) > 255, 255, kg*g).astype(np.uint8) new_r = np.where((kr * r) > 255, 255, kr*r).astype(np.uint8) # 合并三个通道 img_new = cv2.merge([new_b,new_g,new_r]) return img_new img = cv2.imread('./night.png') awb_img = AWB('./night.png') #对图片进行简单灰世界算法处理 cv2.imshow('img',img) cv2.imshow('awb',awb_img) cv2.waitKey(0) cv2.destroyAllWindows()
k值取127或者128也可以,但是效果会差一点: