最近的图像处理涉及到了很多重映射的算法,比如 线性对比度变换, 伽马变换, 二值化, 对数变换, 直方图均衡化等,这些算法具有以下特性:
- 基于每一个像素点的处理
- 一对一或多对一的映射,不存在一对多的映射
- 每一个像素点之间没有关联
以上特点使得这类重映射算法可以用向量化运算做并行处理。
映射函数
这里以图像的伽马变换为例子,伽马变换实际上是将颜色数据规格化到[0,1]并取幂函数的值,即以下的函数关系。
f
(
x
)
=
(
(
x
/
255
)
g
a
m
m
a
)
×
255
f(x)=((x/255)^{gamma})\times255
f(x)=((x/255)gamma)×255
从映射函数计算查找表
由于颜色数据的类型是uint8,并且不存在一对多的映射,所以我们可以制作一个长度为256的查找表用来存储结果。方法很简单,只需要把range(0,256)序列作为上述函数的输入即可。
#关键代码
np.power(np.arange(0,256)/255,val)*255
#实际代码
Map = np.clip(np.round(np.power((np.arange(0,256).astype(np.float64))/255,val)*255),0,255).astype(np.uint8)
由于整型数据可能会上溢,所以这里将np.arange(0,256)转换为浮点型
输出类型是uint8,为了避免转换成短类型溢出,需要四舍五入并且钳制到[0,255]
最后转换成uint8即可。
使用数组切片并行处理
这里把img.data[:,:,:](即x坐标,y坐标,颜色通道)作为下标去索引map查找表,此时data会被替换成查找表对应的值
img.data = Map[img.data[:,:,:]].astype(np.uint8)