图像亮度变化

由于毕设的关系,开始折腾计算机视觉
双目测距的具体实现,现在刚有点眉目而已
看了下图像亮度/对比度的变换的资料
结果又发现漫山遍野的都是同一份代码
而且几乎没有什么解释
原本决定等Harris角点那些弄完再写篇文章
现在想想
还是先记下这份简单的笔记并加以讲解下

那些计算机科班出身的人就不用看这篇了
这只是给我们这些物理/电子系中没有学过”数字图像处理“这门课的人看的

术语解释

亮度(Brightness)

也叫亮度,中文翻译不同而已,你可以看Wikipedia
在 RGB 色彩空间中,明度可以被认为是R(红色),G(绿色)和B(蓝色)座标的算术平均 μ(尽管这三个成分中的某个要比其他看起来更明亮,但这可以被某些显示系统自动补偿):

 \mu = {R + G + B \over 3 }

对比度(Contrast)

我实在google不到满意的解释
大概上来说
灰度图像的对比度指的是图像中的最黑与最白的点,他们灰度值的比值关系
彩色图像由于有3种通道,我的理解是各个通道中的灰度值的比值关系,确切的定义还望有人指教

实现思路

知道明度跟对比度的定义,接下来
要修改亮度,就把图像的通道的灰度值一起增加或者减少就可以
要修改对比度,需要把图像的通道的灰度值以一个值为临界点,往相反两个方向变化
比如,取128为阈值,要增强对比度,低于128的值修改得比原来更小,高于128的值再修改得更大,要降低对比度就反向操作

下面给出我自己写的一份代码,演示明度以及对比度的调整
对比度的公式参考自Photoshop的公式:
nRGB = RGB + (RGB – Threshold) * Contrast / 255

源代码

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "highgui.h"
#pragma comment(lib,"cv200d.lib")
#pragma comment(lib,"cxcore200d.lib")
#pragma comment(lib,"highgui200d.lib")
 
int BrightnessAdjust(const IplImage* srcImg,
                     IplImage* dstImg,
                     float brightness)
{
    assert(srcImg != NULL);
    assert(dstImg != NULL);
 
    int x,y,i;
    float val;
    for (i = 0; i < 3; i++)//彩色图像需要处理3个通道,灰度图像这里可以删掉
    {
        for (y = 0; y < srcImg->height; y++)
        {
            for (x = 0; x < srcImg->width; x++)
            {
 
                val = ((uchar*)(srcImg->imageData + srcImg->widthStep*y))[x*3+i];
                val += brightness;
                //对灰度值的可能溢出进行处理
                if(val>255)    val=255;
                if(val<0) val=0;
                ((uchar*)(dstImg->imageData + dstImg->widthStep*y))[x*3+i] = (uchar)val;
            }
        }
    }
 
    return 0;
}
 
int ContrastAdjust(const IplImage* srcImg,
                   IplImage* dstImg,
                   float nPercent)
{
    assert(srcImg != NULL);
    assert(dstImg != NULL);
 
    int x,y,i;
    float val;
    for (i = 0; i < 3; i++)//彩色图像需要处理3个通道,灰度图像这里可以删掉
    {
        for (y = 0; y < srcImg->height; y++)
        {
            for (x = 0; x < srcImg->width; x++)
            {
 
                val = ((uchar*)(srcImg->imageData + srcImg->widthStep*y))[x*3+i];
                val = 128 + (val - 128) * nPercent;
                //对灰度值的可能溢出进行处理
                if(val>255) val=255;
                if(val<0) val=0;
                ((uchar*)(dstImg->imageData + dstImg->widthStep*y))[x*3+i] = (uchar)val;
            }
        }
    }
    return 0;
}
 
int main(int argc, char** argv)
{
    IplImage* srcImg = cvLoadImage("lena.jpg");
    assert( srcImg != NULL );
 
    IplImage* brightnessImg = cvCloneImage(srcImg);
    //亮度变换,最后数值取值为正时变亮,负则变暗
    BrightnessAdjust(srcImg, brightnessImg, 80.0f);
 
    IplImage* contrastImg = cvCloneImage(srcImg);
    //对比度变换,数值小于1降低对比度,大于1增强对比度
    ContrastAdjust(srcImg, contrastImg, 1.3f);
 
    cvNamedWindow("Source",CV_WINDOW_AUTOSIZE);
    cvNamedWindow("BrightnessAdjust",CV_WINDOW_AUTOSIZE);
    cvNamedWindow("ContrastAdjust",CV_WINDOW_AUTOSIZE);
    cvShowImage("Source",srcImg);
    cvShowImage("BrightnessAdjust",brightnessImg);
    cvShowImage("ContrastAdjust",contrastImg);
    cvWaitKey(0);
    cvReleaseImage(&srcImg);
    cvReleaseImage(&brightnessImg);
    cvReleaseImage(&contrastImg);
    cvDestroyWindow("Source");
    cvDestroyWindow("BrightnessAdjust");
    cvDestroyWindow("ContrastAdjustrast");
 
    return 0;
}

对新手提示几句,运行这个代码请在工程文件的目录下放一个图片,名字是lena.jpg
另外,对彩色通道的处理,循环只有3次,这种循环最好放在最外围,因为图像的长宽一般都远大于这个值
如果你把小循环放最里面,频繁的循环切换,效率会低不少
这只是程序编写技巧上的小提示

本代码在Visual Studio 2008+OpenCV 2.0下运行通过,效果如下


并且与photoshop的调整效果对比过
亮度变换与ps旧版效果一致,貌似ps对亮度变换的公式进行过调整,新版不是这么单纯的加减灰度值
对比度就几乎都差不多了

更多资料

关于OpenCV的安装、配置以及基础学习,可以在OpenCV中文官网查得
官网的入门说明异常详细,各种平台各种IDE都有介绍,我就不多废话了

下次再说说Harris角点的事情吧

posted on 2012-02-09 14:35  伪君  阅读(1309)  评论(0编辑  收藏  举报

导航