逆光图像处理
- CEM
- BBHE
- 代码
- CEM
- BBHE
今天又了解到了两种对亮度处理的方法。分别是CEM和BBHE。
参考: CEM_matlab. BBHE_matlab. BBHE_C++.
CEM
单纯的CEM公式比较简单,原理和公式如下

根据网上一个matlab程序复写了一遍python的,灰度图是有效果的。彩色图片下我一开始用HSV空间中拿出V分量,会产生色差。
对rgb图像就对三个通道都进行了cem模型,效果还可以。
但是注意到他的作用是提升亮度,即使本来很亮的位置他仍然在提升亮度
效果如下,右面时处理之后的效果。

BBHE
简单来说就是进行两次直方图均衡算法。将图片灰度均值作为分开的标准。
灰度直方图均衡的步骤比较简单:
1.统计所有出现的灰度值的次数
2.将次数归一化,得到归一化直方图
3.计算累计直方图
4.将累计直方图进行区间转换
而BBHE就是先根据灰度均值分割成两部分来计算。第一部分计算(0,mean_gray)的归一化直方图,第二部分计算(mean_gray,255)的归一化直方图。和直接计算的区别就在于分母不同。直接计算分母是所有像素个数,而BBHE是属于(0,mean_gray)或(mean_gray,255)的像素个数。分子都是某像素(如0,1,2…)出现的个数。
也就是说第一个累计直方图在像素值为mean_gray出就已经为1了并且之后也都为1。第二个累计直方图,在像素值小于mean_gray时全部为mean_gray对应的值,直到最后为1。
而均衡化体现在最后一步的区间转换上。也就是说。比如原图片像素是一堆聚集在1到10之间的数,求出每个数出现的频率,并进行了累计。然后再扩展到1~255的范围时只需要将累计的结果直接乘255就可以了。
灰度直方图原来是个这么奇妙的东西啊。比如10,20,30,40,50每个出现了一次。那么频率就都是1/5。累加直方图就可以通过区间转换把频率和数值联系起来。累计直方图为1/5,2/5,3/5,4/5,5/5。区间转换公式就是:结果 = 最小值 + 累计直方图的值 ×(最大值 - 最小值)
我之前一直以为直方图均衡化只是将小范围的数值投影到大范围,但是现在看起来并不是这样。使得,肯定不是这样,我以前太想当然了。
代码
在网上找到了matlab和c的,我就简单的改成了python的,希望能帮助到大家。
CEM
def cem(img, lamb=1.33):# 求取灰度均值height, width = img.shapeall = height * widthgray_mean = np.sum(img) / all# 图像优化fcem = np.exp(-(lamb * img / gray_mean))I = (1 - fcem) / (1 + fcem)return I
是的,你没有看错就是这么简单,因为python中有广播机制,所以不用那么麻烦的把遍历写出来了。我还把rgb三个通道分别用着试了一下,理论上是不可以这样的,但是效果还是挺好的。
BBHE
import cv2
import numpy as npdef bbhe(img):""":param img: 从实现来看仍然是灰度图:return: 返回修改后的图像"""# xm = np.exp(9)xmin = np.min(img)xmax = np.max(img)img_result = np.zeros_like(img)# 平均灰度值xm = np.mean(img)sl = np.zeros((256, 1)) # 图像分成l 和 u两部分su = np.zeros((256, 1))pl = np.zeros((256, 1))pu = np.zeros((256, 1))hist_cl = np.zeros((256, 1))hist_cu = np.zeros((256, 1))nl = 0nu = 0# 统计图像中的像素并进行归类for i in range(img.shape[0]):for j in range(img.shape[1]):if img[i, j] < xm:sl[img[i, j]] += 1nl += 1else:su[img[i, j]] += 1nu += 1pl = sl / nlpu = su / nuhist_cl = np.cumsum(pl)hist_cu = np.cumsum(pu)hist_cl = xmin + hist_cl * (xm - xmin)hist_cu = xm + 1 + hist_cu * (xmax - xm -1)for i in range(img.shape[0]):for j in range(img.shape[1]):if img[i, j] <= xm:temp = img[i, j]img_result[i, j] = hist_cl[temp - 1]else:temp = img[i, j]img_result[i, j] = hist_cu[temp - 1]return img_resultdef hsv_bbhe(img):img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)h, s, v = cv2.split(img_hsv)img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)img_gray = bbhe(img_gray).astype(np.uint8)result = cv2.merge((h, s, img_gray))result = cv2.cvtColor(result, cv2.COLOR_HSV2BGR)return result
直接调用最后一个函数就可以啦。转换到hsv空间然后完成工作。因为网上的都是灰度图,所以我对彩色图片就是这么处理的,效果还好,但是颜色还是有点失真。
以上,我要去LOL杀人了,祝大家生活愉快!













