转载:http://blog.sina.com.cn/s/blog_61866a820101192h.html
★自动色阶
一、作用:自动调整图像中的黑白场。
二、原理:剪切每个通道中的阴影和高光部分,并将每个颜色通道中最亮或最暗的像素映射到纯白或纯黑;中间像素按比例重新分配分布。
三、运用:会增强图像中的对比度,因数像素值会增大。
四、特点:单独调整每个颜色通道,有可能会移去颜色或引入色痕。在像素平衡分布且需要以简单方式增加对比度的特定图像中,提供较好的效果。
★自动对比度
一、作用:自动调整图像的对比度。
二、原理:剪切图像中的阴影和高光值,再将图像中的剩余部分的最亮和最暗像素映射到纯白或纯黑;中间像素按比例重新分配分布。
三、效果:会使高光看上去更亮,阴影看上去更暗。
四、特点:不会单独调整各个颜色通道,不会引入或消除色痕。
五、默认值情况:剪切白色/黑色像素的0.5%;也就是说忽略两个极端像素的0.5%
(可使用【色阶】或【曲线】对话框中的“自动颜色校正”选项来更改这个默认设置)
六、运用:可改进许多摄影或连续色调图像的外观,但无法改变单调颜色的图像属性。
★自动颜色
一、原理:能过搜索图像来标识阴影、中间调、高光,从而校正图像的对比度和颜色。
二、默认值情况:使用“RGB128灰色(中度灰色)”这一目标颜色来中和中间调,并将阴影和高光剪切0.5%
(可使用【色阶】或【曲线】对话框中的“自动颜色校正”选项来更改这个默认设置)
自动对比度和自动色阶的实现代码:http://www.cnblogs.com/Imageshop/archive/2011/11/13/2247614.html
我们以24位彩色图像为例说明这两个算法。
在执行两个算法之前,我们需要确定两个参数,大家在用PS时选择自动色阶并不会弹出什么参数设置对话框,那是因为PS把这个隐藏的比较深 。选择曲线或色阶命令,然后在弹出的界面中点击选项按钮,会出现如下界面:
注意其中的裁剪(C)/裁剪(P)中的变量,这两个参数是影响自动色阶效果的重要数据,我们以变量LowCut和HighCut来记录它。
好,接着说。两个算法的第一步,都是分别统计各通道(红/绿/蓝)的直方图。
Dim HistRed(255) As Long, HistGreen(255) As Long
Dim HistBlue(255) As Long
For Y = 0 To Height - 1
Speed = Y * Stride
For X = 0 To Width - 1
Red = ImageData(Speed + 2): Green = ImageData(Speed + 1): Blue = ImageData(Speed)
HistRed(Red) = HistRed(Red) + 1 '统计直方图
HistGreen(Green) = HistGreen(Green) + 1
HistBlue(Blue) = HistBlue(Blue) + 1
Speed = Speed + 3
Next
Next
- 看了上面代码,我很欣赏C++的++运算符,HistRed(Red)++,多么简单啊,而且更高效。
- 算法的第二步,分别计算各通道按照给定的参数所确定的上下限值。什么意思呢,比如对于蓝色通道,我们从色阶0开始向上累加统计直方图,当累加值大于LowCut*所有像素数时,以此时的色阶值计为MinBlue。然后从色阶255开始向下累计直方图,如果累加值大于HighCut*所有像素时,以此时的色阶值计为MaxBlue。
PixelAmount = Width * Height '所有像素的数目
Sum = 0
For Y = 0 To 255
Sum = Sum + HistBlue(Y)
If Sum >= PixelAmount * LowCut * 0.01 Then '注意PS界面里的那个百分号
MinBlue = Y '得到蓝色分量的下限
Exit For '退出循环
End If
Next
Sum = 0
For Y = 255 To 0 Step -1
Sum = Sum + HistBlue(Y)
If Sum >= PixelAmount * HighCut * 0.01 Then '注意PS界面里的那个百分号
MaxBlue = Y '得到蓝色分量的上限
Exit For '退出循环
End If
Next
绿色通道和红色通道的代码类似,请朋友们自己补充。
下一步,自动色阶和自动对比度就有所区别了,我们首先介绍自动色阶。
自动色阶:按照我们刚刚计算出的MinBlue/MaxBlue构建一个隐射表,隐射表的规则是,对于小于MinBlue的值,则隐射为0(实际上这句话也不对,隐射为多少是和那个自动颜色校正选项对话框中的阴影所设定的颜色有关,默认情况下是黑色,对应的RGB分量都为0,所以我们这里就隐射为0,有兴趣你们也可以指定为其他的参数),对于大于MaxBlue的值,则隐射为255(同理,这个值和高光的颜色设置有关),对于介于MinBlue和MaxBlue之间的值,则进行线性隐射,默认是隐射为0到255之间(当然实际是和我们的暗调和高光的设置有关,并且这里其实也不是线性隐射,是有一个Gamma校正,为了简便,用线性替代效果也没太大的问题)。
For Y = 0 To 255
If Y <= MinBlue Then
BlueMap(Y) = 0
ElseIf Y >= MaxBlue Then
BlueMap(Y) = 255
Else
BlueMap(Y) = (Y - MinBlue) / (MaxBlue - MinBlue) * 255 '线性隐射
End If
Next
顺便提一点,从程序的鲁棒性上来说,在执行这段代码前判断下MaxBlue是否等于MinBlue很有必要,两者相等,这图就无需校正了,直接结束程序。
用同样的道理,计算出绿色和红色通道的隐射表GreenMap和RedMap。
最后一步,对各通道图像数据进行隐射。
For Y = 0 To Height - 1
Speed = Y * Stride
For X = 0 To Width - 1
ImageData(Speed) = BlueMap(ImageData(Speed))
ImageData(Speed + 1) = GreenMap(ImageData(Speed + 1))
ImageData(Speed + 2) = RedMap(ImageData(Speed + 2))
Speed = Speed + 3
Next
Next
自动色阶完成,下面我们谈谈自动对比度的不同。
在计算完各通道对应的上下限值后,自动对比度算法首先获取三个通道下限值的最小值,以及上限值的最大值,如下代码:
If MinBlue < MinGreen Then
Min = MinBlue
Else
Min = MinGreen
End If
If Min > MinRed Then Min = MinRed
If MaxBlue > MaxGreen Then
Max = MaxBlue
Else
Max = MaxGreen
End If
If Max < MaxRed Then Max = MaxRed
然后以此为新的上下限,计算隐射表。
For Y = 0 To 255
If Y <= Min Then
Map(Y) = 0
ElseIf Y > Max Then
Map(Y) = 255
Else
Map(Y) = (Y - Min) / (Max - Min) * 255 '线性隐射
End If
Next
最后,以这个隐射表分别对红绿蓝通道进行处理。
For Y = 0 To Height - 1
Speed = Y * Stride
For X = 0 To Width - 1
ImageData(Speed) = Map(ImageData(Speed))
ImageData(Speed + 1) = Map(ImageData(Speed + 1))
ImageData(Speed + 2) = Map(ImageData(Speed + 2))
Speed = Speed + 3
Next
Next
由以上过程可以看出,对于灰度图像,由于只有一个通道,自动对比度和自动色阶实际上算法相同,结果一样。
对于32位图像,这类单点像素处理的过程一般是无需处理Alpha通道的。