图像处理亮度调节_图像处理之图像亮度调节 - CSDN
  • 图像处理之图像亮度调节

    万次阅读 2017-05-07 17:13:50
    图像处理中,图像亮度调节可能是最简单的算法了,非常常见的线性运算即可完成亮度调节,比如所有像素点亮度值乘或者加一个增强系数,使得图像整体变亮或者变暗。photoshop中是如何实现的不得而知,每个版本可能也不...

           图像处理中,图像亮度调节可能是最简单的算法了,非常常见的线性运算即可完成亮度调节,比如所有像素点亮度值乘或者加一个增强系数,使得图像整体变亮或者变暗。看过一些相关开源代码,常见的操作是乘以一个亮度调节系数。但是,这样做很容易使图像出现过饱和现象,即亮度值超出255。photoshop中是如何实现的不得而知,每个版本可能也不一样。还是说说我的实现方法,其实就是在调节过程中,根据像素点亮度,做非线性调节,即高光、阴影部分调节小一点,中间部分多调节一些,这样亮度调节看着更自然一些。下面是示例代码:

    void ImageBrightness(BMPINFO *pSrcBitmap, float strength)
    {
    	int brightness = (int)(strength*100);
    	uchar lookupTable[256];
    	for (int i = 0; i < 256; i++)
    	{
    		lookupTable[i] = (uchar)MIN(255, MAX(0, i + sin(FILTER_PI*i / 255.0f)*brightness));
    	}
    
    	int size = pSrcBitmap->lWidth*pSrcBitmap->lHeight;
    	uchar* pSrcData = pSrcBitmap->pPlane[0];
    	for (int i = 0; i < size; i++, pSrcData+=4)
    	{
    		pSrcData[AXJ_BLUE] = lookupTable[pSrcData[AXJ_BLUE]];
    		pSrcData[AXJ_GREEN] = lookupTable[pSrcData[AXJ_GREEN]];
    		pSrcData[AXJ_RED] = lookupTable[pSrcData[AXJ_RED]];
    	}
    }

           亮度调节示例图片,上面为原图,下面为结果图。

                  

                  




    展开全文
  • 数字图像处理亮度调整

    千次阅读 2019-08-08 20:09:17
    图像亮度、对比度、饱和度和锐化之间并不是彼此独立的,改变其中一个特征可能会同时引起图像其他特征的变化,至于变化的程度取决于图像本身的特性,先建立一个概念,在后面的会在详述 1、亮度基本概念 图像亮度...

     

     图像亮度、对比度、饱和度和锐化之间并不是彼此独立的,改变其中一个特征可能会同时引起图像其他特征的变化,至于变化的程度取决于图像本身的特性,先建立一个概念,在后面的会在详述

     

    1、亮度基本概念


    图像亮度通俗理解便是图像的明暗程度,数字图像 f(x,y) = i(x,y) r(x, y) ,如果灰度值在[0,255]之间,则 f 值越接近0亮度越低,f 值越接近255亮度越高。而且我们也要把亮度和对比度区分开来,正如上述提的对比度指的是最高和最低灰度级之间的灰度差。下面通过图片感受一下亮度变化对数字图像的影响:

    å¨è¿éæå¥å¾çæè¿°
    上面白色和红色两幅图中,图的右边相对于左边增加了亮度,可以看出图像右边相对于左边亮度有了一个整体的提升,这里只是对亮度做了一个小弧度的提升,我们尝试着将亮度提升的更高,如下图:

    å¨è¿éæå¥å¾çæè¿°
    这里需要强调的是如果我们对亮度做这么一个剧烈的改变,那么便会在改变图片强度的同时也影响了图片的饱和度、对比度和清晰度,此时两个图片右边部分饱和度、对比度和清晰度都降低了,原因是过度增加亮度导致阴影赶上了高光,因为最大灰度值是固定的,所以最低灰度值快赶上了最大灰度值,因此影响了图片的饱和度、对比度和清晰度

    2、图像亮度调节示例

    • 图像对比度调节可以直接在RGB空间利用变换公式 g(i,j)= af(i,j) + b 对图像进行线性变化;

    对于数字图像变换,设原像素灰度为 f(i,j),转化后的像素灰度为 g(i,j),则常用的线性变换是 g(i,j)= af(i,j) + b, 其中系数 a 影响图像的对比度,系数 b 影响图像的亮度,具体如下:
    (1) a=1时是原图;
    (2) a>1时对比度增强,图像看起来更加清晰;
    (3) a<1时对比度减弱,图像看起来变暗;
    (4) b影响图像的亮度,随着增加b (b>0)和减小b (b>0),图像整体的灰度值上移或者下移, 也就是图像整体变亮或者变暗, 不会改变图像的对比度


    代码:

    import cv2
    import imutils
    import numpy as np
    
    def c_and_b(arg):
        ''''''
        contrast_num = cv2.getTrackbarPos(trackbar_name1, wname)
        brightness_num = cv2.getTrackbarPos(trackbar_name2, wname)
        #print(bnum)
        cimg = np.ones((img.shape[0], img.shape[1], 3), dtype=np.uint8)
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
                lst = 0.1 * contrast_num * img[i, j] + brightness_num
                cimg[i, j] = [int(ele) if ele < 255 else 255 for ele in lst]
    
        cv2.imshow(wname, imutils.resize(cimg, 800))
    
    
    wname = 'brightness and contrast'
    trackbar_name1 = 'contrast'
    trackbar_name2 = 'brightness'
    img = cv2.imread(r"E:\yun_project\face_morpher\bieber.jpg")
    height, width = img.shape[:2]
    img = cv2.resize(img, (int(width/height*400), 400), interpolation=cv2.INTER_CUBIC)
    
    cv2.namedWindow(wname)
    cv2.createTrackbar(trackbar_name1, wname, 10, 20, c_and_b)
    cv2.createTrackbar(trackbar_name2, wname, 0, 100, c_and_b)
    
    c_and_b(0)
    
    if cv2.waitKey(1) & 0xFF == ord('q'):
        cv2.destroyAllWindows()

     

    效果:

     

    那么对于两张图像融合时,图像的色调不同, 可以通过调整三色通道,达到调节图像亮度的目的

    # 计算指定不规则图像中的平均亮度
    def calculate_average_brightness(img):
        # 三色通道的平均值
        B = img[..., 0].mean()
        G = img[..., 1].mean()
        R = img[..., 2].mean()
    
        # 显示亮度
        brightness = 0.299 * R + 0.587 * G + 0.114 * B
        return brightness, B, G, R
    
    # 计算图像平均亮度调节图像
    # 将目标图像的平均亮度调整为源图像的平均亮度
    def adjust_brightness_from_src_to_dst(src, dst):
        brightness1, B1, G1, R1 = calculate_average_brightness(src)
        brightness2, B2, G2, R2 = calculate_average_brightness(dst)
        brightness_difference = int(round(brightness1 - brightness2))
    
        print('原图的平均亮度', brightness1)
        print('目标的平均亮度', brightness2)
        print('原图与目标的亮度差距', brightness_difference)
    
    
        # 按照平均显示亮度进行增强
        dstf = dst + brightness_difference
    
        # 按照三色通道平均值进行增强
        # dstf = dst.copy().astype(np.float32)
        # dstf[..., 0] = dst[..., 0] + (B1 - B2)
        # dstf[..., 1] = dst[..., 1] + (G1 - G2)
        # dstf[..., 2] = dst[..., 2] + (R1 - R2)
    
        # 对结果进行限制,放置越界,必须转成uint8,不然结果默认为float32,会出错
        dstf = np.clip(dstf, 0, 255)
        dstf = np.uint8(dstf)
        return dstf

    按照平均显示亮度进行增强的效果图

    按照三色通道平均值进行增强的效果图

    推荐文章

    https://blog.csdn.net/feilong_csdn/article/details/82755816

    https://www.cnblogs.com/skiwnchiwns/p/10130833.html

     

    展开全文
  • 本系列python版本:python3.5.4 本系列opencv-python版本:opencv-python3.4.2.17 本系列使用的开发环境是jupyter notebook,是一个python的交互式开发环境,测试十分方便,并集成了vim操作,安装教程可参考...


    在上文【数字图像处理系列一】opencv-python快速入门篇 中结合了opencv-python对数字图像的基本操作有了一定的了解,本文我们将一起过数字图像概念和形成原理,并探讨一下亮度、对比度、分辨率、饱和度、锐化等基本属性

    来~干~,上一张程序截图:
    在这里插入图片描述



    一、何为数字图像


    1、数字图像定义

    对于一幅图像,我们可以将其放入坐标系中,这里取图像左上定点为坐标原点,x 轴向右,和笛卡尔坐标系x轴相同;y 轴向下,和笛卡尔坐标系y轴相反。这样我们可将一幅图像定义为一个二维函数 f(x,y),图像中的每个像素就可以用 (x,y) 坐标表示,而在任何一对空间坐标 (x,y) 处的幅值 f 称为图像在该点的强度或灰度,当 x,y 和灰度值 f 是有限离散数值时,便称该图像为 数字图像

    2、数字图像形成过程

    我们平时见到的多数图像都是有照射源和形成图像的场景元素对光能的反射和吸收而产生的,得到我们可见的数字图像分为一下几个步骤:

    (1) 图像感知和获取

    照射源入射光线照射到物体,经过反射或是折射光纤进入到人眼中,然后看到物体。而将照射能量转化为数字图像便需要用到传感器,主要的传感器有:

    • 单个成像传感器
    • 条带传感器
    • 阵列传感器

    原理很简单: 就是通过将输入电能和对特殊类型检测能源敏感的传感器材料相结合,把输入能源转化为电压,输出的电压波再经过取样和量化便可得到离散的数字图像 f(x,y)

    注:由图形形成模型来理解一下灰度级或强度级,请看下面

    上面我们提到图像可由而为函数 f(x,y) 表示,其物体意义其实就来自于照射源对物体的照射,函数 f(x,y) 可由两个分量来表示:

    • 入射到被观察场景的光源照射总量
    • 场景中物体所反射的光源总量

    上述两个分量分别称为入射分量和反射分量,表示为 i(x,y)、r(x, y),有:
    在这里插入图片描述
    其中:

    在这里插入图片描述
    在这里插入图片描述

    因此图像的灰度值或强度值是由入射分量和反射分量决定的,i(x,y) 的性质取决于照射源,而r(x, y) 的性质取决于成像物体的特性,公式只是给出了 i(x,y)、r(x, y) 的一般取值范围,自然对于不同的照射源和成像物体则 i(x,y)、r(x, y) 会有不同的取值,因此数字图像灰度取值范围便是:
    在这里插入图片描述
    在这里插入图片描述
    因此区间[Lmin,Lmax]便称为图像的灰度级,实际情况下常常令该区间为[0,L-1],其中f=0时为黑色,f=L-1时在灰度级中为白色,所有中间值是从黑色到白色之间变化的灰度色调,而图像最高和最低灰度级之间的灰度差便为对比度


    (2) 图像取样和量化

    为了产生一幅数字图像,我们需要把连续的感知数据转化为数字形式,便是:取样和量化。取样和量化目的便是为了将连续的感知数据离散化,而且图像的质量在很大程度上也取决于取样和量化中所用的样本数和灰度级,想了解详细过程请参考:图像的采样与量化及灰度直方图


    (3) 显示数字图像

    数字图像f(x,y)主要有三种表示方式:

    • 画为三维表面图像,如下图2.18(a)
    • 可视化灰度阵列图像,如下图2.18(b)
    • 二维数值阵列图像,如下图2.18(c )

    在这里插入图片描述




    二、亮度、对比度、饱和度、锐化、分辨率


    画重点啦: 图像亮度、对比度、饱和度和锐化之间并不是彼此独立的,改变其中一个特征可能会同时引起图像其他特征的变化,至于变化的程度取决于图像本身的特性,先建立一个概念,在后面的会在详述

    1、亮度

    图像亮度通俗理解便是图像的明暗程度,数字图像 f(x,y) = i(x,y) r(x, y) ,如果灰度值在[0,255]之间,则 f 值越接近0亮度越低,f 值越接近255亮度越高。而且我们也要把亮度和对比度区分开来,正如上述提的对比度指的是最高和最低灰度级之间的灰度差。下面通过图片感受一下亮度变化对数字图像的影响:
    在这里插入图片描述

    上面白色和红色两幅图中,图的右边相对于左边增加了亮度,可以看出图像右边相对于左边亮度有了一个整体的提升,这里只是对亮度做了一个小弧度的提升,我们尝试着将亮度提升的更高,如下图:
    在这里插入图片描述

    这里需要强调的是如果我们对亮度做这么一个剧烈的改变,那么便会在改变图片强度的同时也影响了图片的饱和度、对比度和清晰度,此时两个图片右边部分饱和度、对比度和清晰度都降低了,原因是过度增加亮度导致阴影赶上了高光,因为最大灰度值是固定的,所以最低灰度值快赶上了最大灰度值,因此影响了图片的饱和度、对比度和清晰度


    2、对比度和饱和度

    (1) 饱和度指的是图像颜色种类的多少, 上面提到图像的灰度级是[Lmin,Lmax],则在Lmin、Lmax 的中间值越多,便代表图像的颜色种类多,饱和度也就更高,外观上看起来图像会更鲜艳,调整饱和度可以修正过度曝光或者未充分曝光的图片。使图像看上去更加自然

    (2) 对比度上面已经介绍过,指的是图像暗和亮的落差值,即图像最大灰度级和最小灰度级之间的差值,看下图:
    在这里插入图片描述
    上面白色和红色辐条图像的右侧都增加了对比度,但我们可以看出右侧的白色辐条或是红色辐条随着对比度的增加,白/红色辐条都变亮了,背景变暗了,图像看起来更加清晰。


    但注意:在红色辐条中增加对比度同时也增加了饱和度,但白色辐条的饱和度没有随着亮度的增加而增加,这印证了前面说的变化的程度取决于图像本身的特性。因为饱和度对于具有鲜艳颜色,颜色丰富的图像影响很大,而对于暗淡的颜色或几乎是中性颜色影响较小


    3、锐化

    图像锐化是补偿图像的轮廓,增强图像的边缘及灰度跳变的部分,使图像变得清晰。图像锐化在实际图像处理中经常用到,因为在做图像平滑,图像滤波处理的时候经过会把丢失图像的边缘信息,通过图像锐化便能够增强突出图像的边缘、轮廓

    如需了解图像锐化原理请查看博文: 图像锐化(增强)和边缘检测

    再通过下图来观察一下图像锐化效果:
    在这里插入图片描述

    从山图中我们可以看出图像白色、红色辐条的接近中心的细辐条亮度、对比度和饱和度也有了明显的提升,但外侧确没有太明显的变化,这是因为图像锐化会更多的增强边缘数据,因此影响也就更加明显


    小结一下:上面三个小节分别对图像的亮度、对比度、饱和度、锐化的概念做了基本的阐述,同时配图也着重强调了图像的亮度、对比度、饱和度、锐化之间也不是完全孤立存在的,是会互相影响的,So明白了他们之间的相互影响,在以后做数字图像处理的时候能根据更好的去调节图像亮度、对比度、饱和度、锐化这些属性

    4、分辨率

    不太规范的说图像分辨率可以看成是图像的大小,分辨率高图像就大,更清晰反之分辨率低图像就小。官方说法:图像分辨率指图像中存储的信息量,是每英寸图像内有多少个像素点,即:像素每英寸,单位为PPI(Pixels Per Inch),因此放大图像便会增强图像的分辨率,图像分辨率大图像更大,更加清晰,例如:一张图片分辨率是500x200,也就是说这张图片在屏幕上按1:1放大时,水平方向有500个像素点(色块),垂直方向有200个像素点(色块)




    三、图像亮度、对比度、饱和度、锐化、分辨率调节示例


    先画个重点:

    • 图像对比度调节可以直接在RGB空间利用变换公式 g(i,j)= af(i,j) + b 对图像进行线性变化;
    • 图像饱和度通常在RGB色彩空间调整不是很直观,而HSL彩色空可以很直观表示出每个像素的饱和度,所以对于饱和度的调节,首先读取图像的像素RGB值然后再转换到HSL空间得到饱和度与亮度值,调整以后再从HSL空间转换到RGB空间的RGB值,完成图像饱和度调整
    • 图像锐化通常分为利用空间滤波器锐化图像、利用频域滤波器锐化图像,将在后续文章图像滤波中做详细阐述,本文不讨论

    1、RGB空间图像亮度、对比度调节

    对于数字图像变换,设原像素灰度为 f(i,j),转化后的像素灰度为 g(i,j),则常用的线性变换是 g(i,j)= af(i,j) + b, 其中系数 a 影响图像的对比度,系数 b 影响图像的亮度,具体如下:
    (1) a=1时是原图;
    (2) a>1时对比度增强,图像看起来更加清晰;
    (3) a<1时对比度减弱,图像看起来变暗;
    (4) b影响图像的亮度,随着增加b (b>0)和减小b (b>0),图像整体的灰度值上移或者下移, 也就是图像整体变亮或者变暗, 不会改变图像的对比度

    上代码:

    import cv2
    import imutils
    import numpy as np
    
    def c_and_b(arg):
        ''''''
        cnum = cv2.getTrackbarPos(trackbar_name1, wname)
        bnum = cv2.getTrackbarPos(trackbar_name2, wname)
        #print(bnum)
        cimg = np.ones((img.shape[0], img.shape[1], 3), dtype=np.uint8)
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
                lst = 0.1*cnum*img[i, j] + bnum
                cimg[i, j] = [int(ele) if ele < 255 else 255 for ele in lst]
        cv2.imshow(wname, imutils.resize(cimg, 800))
    
    wname = 'brightness and contrast'
    trackbar_name1 = 'contrast'
    trackbar_name2 = 'brightness'
    img = cv2.imread("E:/peking_rw/ocr_project/base_prehandle/img/li.jpg")
    height, width = img.shape[:2]
    img = cv2.resize(img, (int(width/height*400), 400), interpolation=cv2.INTER_CUBIC)
    
    cv2.namedWindow(wname)
    cv2.createTrackbar(trackbar_name1, wname, 10, 20, c_and_b)
    cv2.createTrackbar(trackbar_name2, wname, 0, 100, c_and_b)
    
    c_and_b(0)
    if cv2.waitKey(0) == 27:
        cv2.destroyAllWindows()
    

    运行效果如下:

    在这里插入图片描述


    2、HSL空间图像亮度、饱和度调节

    HSL空间:代表色相,饱和度,明度三个通道的颜色。 H: Hue 色相、 S:Saturation 饱和度、 L :Lightness 明度。例如:归一化后二维数字图像(0, 0)像素的值为(0.2,0.3,0.4),则代表H=0.2,S=0.3,L=0.4

    上代码:

    import cv2
    import imutils
    import numpy as np
    
    def s_and_b(arg):
        lsImg = np.zeros(image.shape, np.float32)
        hlsCopy = np.copy(hlsImg)
        l = cv2.getTrackbarPos('l', 'l and s')
        s = cv2.getTrackbarPos('s', 'l and s')
        #1.调整亮度饱和度(线性变换)、 2.将hlsCopy[:,:,1]和hlsCopy[:,:,2]中大于1的全部截取
        hlsCopy[:, :, 1] = (1.0 + l / float(MAX_VALUE)) * hlsCopy[:, :, 1]
        hlsCopy[:, :, 1][hlsCopy[:, :, 1] > 1] = 1
        #HLS空间通道2是饱和度,对饱和度进行线性变换,且最大值在255以内,这一归一化了,所以应在1以内
        hlsCopy[:, :, 2] = (1.0 + s / float(MAX_VALUE)) * hlsCopy[:, :, 2]
        hlsCopy[:, :, 2][hlsCopy[:, :, 2] > 1] = 1
        # HLS2BGR
        lsImg = cv2.cvtColor(hlsCopy, cv2.COLOR_HLS2BGR)
        # 显示调整后的效果
        cv2.imshow("l and s", imutils.resize(lsImg, 650))
        
    image = cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/cartoon.jpg', 1)
    # 图像归一化,且转换为浮点型, 颜色空间转换 BGR转为HLS
    fImg = image.astype(np.float32)
    fImg = fImg / 255.0
    #HLS空间,三个通道分别是: Hue色相、lightness亮度、saturation饱和度
    #通道0是色相、通道1是亮度、通道2是饱和度
    hlsImg = cv2.cvtColor(fImg, cv2.COLOR_BGR2HLS)
    
    l, s, MAX_VALUE = 100, 100, 100
    cv2.namedWindow("l and s", cv2.WINDOW_AUTOSIZE)
    cv2.createTrackbar("l", "l and s", l, MAX_VALUE, s_and_b)
    cv2.createTrackbar("s", "l and s", s, MAX_VALUE, s_and_b)
    
    s_and_b(0)
    if cv2.waitKey(0) == 27:
        cv2.destroyAllWindows()
    

    运行效果如下:

    在这里插入图片描述


    3、图像分辨率调节

    图像分辨率调节就比较简单了,经常使用,opencv-python中自带了resize函数可以对图像的分辨率进行调节,resize函数官方给出定义:

    cv2.resize(img, (width,  height),  interpolation = cv2.INTER_LINEAR)
    

    参数一: 图像对象
    参数二: (width, height)输入的图像的宽度和高度
    参数三: 使用何种差值方式对图像进行缩放,由一下常用几种

    • cv2.INTER_LINEAR: 双线性插值,默认情况使用
    • cv2.INTER_NEAREST: 最邻近插值
    • cv2.INTER_AREA: 使用像素区域关系重新采样,和cv2.INTER_NEAREST相似
    • cv2.INTER_CUBIC: 4x4像素邻域内的双立方插值
    import cv2
    import imutils
    import numpy as np
    
    rgb_img = cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/li.jpg')
    height, width = rgb_img.shape[:2]
    rgb_img = cv2.resize(rgb_img, (int(width/height*100), 100), interpolation=cv2.INTER_CUBIC)
    cv2.imshow('resize image', rgb_img))
    if cv2.waitKey(0) == 27:
        cv2.destroyAllWindows()
    

    图像分辨率调节效果
    在这里插入图片描述




    四、总结


    总结一下本文所学习的知识点:

    • 数字图像的定义
    • 数字图像的形成过程
    • 数字图像亮度、对比度、饱和度、锐化、分辨率概念以及亮度、对比度、饱和度、锐化之间相互影响的关系
    • 数字图像亮度、对比度、饱和度、分辨率调节示例演示

    本文分享结束,有问题欢迎交流学习,大家也可以关注我的微信公众号,一起交流学习:
    在这里插入图片描述

    展开全文
  • 目标 在本教程中,您将学习如何: 访问像素值 用零初始化矩阵 了解cv :: saturate_cast的作用以及它有用的原因 获取有关像素转换的一些很酷的信息 在实际例子中提高图像的亮度 ...一般图像处理操作符是获取一...

    目标

    在本教程中,您将学习如何:

    • 访问像素值
    • 用零初始化矩阵
    • 了解cv :: saturate_cast的作用以及它有用的原因
    • 获取有关像素转换的一些很酷的信息
    • 在实际例子中提高图像的亮度

    理论

    注意,以下解释属于Richard Szeliski 所着的Computer Vision:Algorithms and Applications一

    图像处理

    • 一般图像处理操作符是获取一个或多个输入图像并产生输出图像的功能。
    • 图像变换可以看作:
      • 点运算(像素变换)-
      • Point operators (pixel transforms)
      • 邻域操作
      • Neighborhood (area-based) operators

    像素转换

    • 在这种图像处理变换中,每个输出像素的值仅取决于相应的输入像素值。
    • 这种算子的例子包括亮度对比度调整以及颜色校正和变换

    亮度和对比度调整

    • 两个常用的点过程是乘法加法与常量:

    • 参数α>0和β通常称为增益偏差参数(the gain and bias parameters),这些参数分别控制对比度亮度
    • 假设f(x)作为源图像像素,g(x)作为输出图像像素,上述表达式可以改写为:

      其中,i和j表示像素位于i行和第j

       

    Coding

    C ++

    • 完整代码:
    /**
     * @file BasicLinearTransforms.cpp
     * @brief Simple program to change contrast and brightness
     * @author OpenCV team
     */
    
    #include "opencv2/imgcodecs.hpp"
    #include "opencv2/highgui.hpp"
    #include <iostream>
    
    // we're NOT "using namespace std;" here, to avoid collisions between the beta variable and std::beta in c++17
    using std::cin;
    using std::cout;
    using std::endl;
    using namespace cv;
    
    /**
     * @function main
     * @brief Main function
     */
    int main( int argc, char** argv )
    {
        /// Read image given by user
        //! [basic-linear-transform-load]
        CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" );
        Mat image = imread( parser.get<String>( "@input" ) );
        if( image.empty() )
        {
          cout << "Could not open or find the image!\n" << endl;
          cout << "Usage: " << argv[0] << " <Input image>" << endl;
          return -1;
        }
        //! [basic-linear-transform-load]
    
        //! [basic-linear-transform-output]
        Mat new_image = Mat::zeros( image.size(), image.type() );
        //! [basic-linear-transform-output]
    
        //! [basic-linear-transform-parameters]
        double alpha = 1.0; /*< Simple contrast control */
        int beta = 0;       /*< Simple brightness control */
    
        /// Initialize values
        cout << " Basic Linear Transforms " << endl;
        cout << "-------------------------" << endl;
        cout << "* Enter the alpha value [1.0-3.0]: "; cin >> alpha;
        cout << "* Enter the beta value [0-100]: ";    cin >> beta;
        //! [basic-linear-transform-parameters]
    
        /// Do the operation new_image(i,j) = alpha*image(i,j) + beta
        /// Instead of these 'for' loops we could have used simply:
        /// image.convertTo(new_image, -1, alpha, beta);
        /// but we wanted to show you how to access the pixels :)
        //! [basic-linear-transform-operation]
        for( int y = 0; y < image.rows; y++ ) {
            for( int x = 0; x < image.cols; x++ ) {
                for( int c = 0; c < image.channels(); c++ ) {
                    new_image.at<Vec3b>(y,x)[c] =
                      saturate_cast<uchar>( alpha*image.at<Vec3b>(y,x)[c] + beta );
                }
            }
        }
        //! [basic-linear-transform-operation]
    
        //! [basic-linear-transform-display]
        /// Show stuff
        imshow("Original Image", image);
        imshow("New Image", new_image);
    
        /// Wait until user press some key
        waitKey();
        //! [basic-linear-transform-display]
        return 0;
    }

    说明 
     

    • 我们使用cv :: imread加载图像并将其保存在Mat对象中:
      CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" );
        Mat image = imread( parser.get<String>( "@input" ) );
        if( image.empty() )
        {
          cout << "Could not open or find the image!\n" << endl;
          cout << "Usage: " << argv[0] << " <Input image>" << endl;
          return -1;
        }
    • 现在,由于我们将对此图像进行一些转换,因此我们需要一个新的Mat对象来存储它。此外,我们希望它具有以下功能:
      • 初始像素值等于零
      • 与原始图像的大小和类型相同
     Mat new_image = Mat::zeros( image.size(), image.type() );  
    // the same size and type of Mat img
    

    我们观察到cv :: Mat :: zeros返回一个基于image.size()image.type()的Matlab样式的零初始值设定项

    • 我们现在问α的值和β 由用户输入:
     double alpha = 1.0; /*< Simple contrast control */
        int beta = 0;       /*< Simple brightness control */
        cout << " Basic Linear Transforms " << endl;
        cout << "-------------------------" << endl;
        cout << "* Enter the alpha value [1.0-3.0]: "; cin >> alpha;
        cout << "* Enter the beta value [0-100]: ";    cin >> beta;
    
    • 现在,执行操作g(i,j)= α · f(i,j)+ b我们将访问图像中的每个像素。由于我们使用BGR图像进行操作,因此每个像素(B,G和R)将有三个值,因此我们也将单独访问它们。
    • 代码:
     for( int y = 0; y < image.rows; y++ ) {
            for( int x = 0; x < image.cols; x++ ) {
                for( int c = 0; c < image.channels(); c++ ) {
                    new_image.at<Vec3b>(y,x)[c] =
                      saturate_cast<uchar>( alpha*image.at<Vec3b>(y,x)[c] + beta );
                }
            }
        }
    

    请注意以下内容(仅限C ++代码):

    • 要访问图像中的每个像素,我们使用以下语法:image.at <Vec3b>(y,x)[c]其中y是行,x是列,c是R,G或B(0,1或2)。
    • 由于操作α&CenterDot;&p(i,j)+ b可以给出超出范围的值或不是整数(如果α是浮动),我们使用cv :: saturate_cast来确保值是有效的。
    • 最后,我们创建窗口并以通常的方式显示图像。

     

        imshow("Original Image", image);
        imshow("New Image", new_image);
        waitKey();
    

    注意

    我们可以简单地使用此命令,而不是使用for循环来访问每个像素:

    image.convertTo(new_image,-1,alpha,beta);
    

    其中cv :: Mat :: convertTo将有效地执行* new_image = a * image + beta *。但是,我们想向您展示如何访问每个像素。在任何情况下,两种方法都给出相同的结果,但convertTo更优化,工作速度更快。


    结果

    • 运行我们的代码并使用α=2.2和β= 50

      $ ./BasicLinearTransforms lena.jpg

      基本线性变换

      -------------------------

      *输入alpha值[1.0-3.0]:2.2

      *输入beta值[0-100]:50

    • 我们得到这个:

      Basic_Linear_Transform_Tutorial_Result_big.jpg

    例子

    在本段中,我们将通过调整图像的亮度和对比度来实践我们所学到的校正曝光不足图像的方法。我们还将看到另一种技术来校正称为伽马校正图像亮度。

    亮度和对比度调整

    增加(/减少)β将为每个像素添加(/减去)一个常量值。像素值在[0; 255]范围将饱和(即,高于(/小于)255(/ 0)的像素值将被截止到255(/ 0))。

    Basic_Linear_Transform_Tutorial_hist_beta.png

    原始图像的直方图,当Gimp中亮度= 80时为深灰色

    直方图针对每个颜色级别表示具有该颜色级别的像素的数量。暗图像将具有许多具有低颜色值的像素,因此直方图将在其左侧部分呈现峰值。当添加恒定偏置时,直方图向右移动,因为我们已经为所有像素添加了恒定偏置。

    在一个参数将修改级别的传播方式。如果α<1,颜色等级将被压缩,结果将是对比度较低的图像。

    Basic_Linear_Transform_Tutorial_hist_alpha.png

    原始图像的直方图,当在Gimp中对比度<0时为深灰色

    请注意,这些直方图是使用Gimp软件中的亮度 - 对比度工具获得的。亮度工具应与β相同偏差参数但对比工具似乎与α不同 输出范围似乎以Gimp为中心的增益(正如您在前面的直方图中所注意到的那样)。

    β可能会发生偏差会改善亮度,但同时图像会出现轻微的面纱,因为对比度会降低。该α 增益可以用来减少这种效果,但由于饱和,我们将失去原始明亮区域的一些细节。


    伽玛校正

    通过在输入值和映射的输出值之间使用非线性变换Gamma校正可用于校正图像的亮度:

     

     

    由于此关系是非线性的,因此对于所有像素,效果将不相同,并且将取决于它们的原始值。

    Basic_Linear_Transform_Tutorial_gamma.png

    绘制不同的伽玛值,当γ< 1中,原始的暗区将是明亮,直方图将被向右移位,而这将是与相对的γ> 1。

    纠正曝光不足的图像

    以下图像已更正为:α=1.3和β= 40。

     

    整体亮度已得到改善,但您可以注意到,经过对比度调整之后,暗部细节得到了明显改善,与此同时,高亮度部分的云已经过饱和,使得天空颜色失真。

    以下图像已用:γ校正= 0.4。

     

         伽马校正应该倾向于增加图像的动态对比度,因为映射是非线性的并且不存在如先前方法中那样的数值饱和。

    Basic_Linear_Transform_Tutorial_histogram_compare.png

                                 左:alpha,beta校正后的直方图;  中:原始图像的直方图; 右:伽马校正后的直方图

    上图比较了三幅图像的直方图(三个直方图之间的y范围不同)。您可以注意到,大多数像素值位于原始图像直方图的下半部分。在α之后,b校正,由于饱和以及右移,我们可以观察到255处的大峰值。在伽马校正之后,直方图向右移动但是暗区域中的像素比亮区域中的像素更加偏移(参见伽马曲线)。


    伽马变换代码段:

    C++

     Mat lookUpTable(1, 256, CV_8U);
        uchar* p = lookUpTable.ptr();
        for( int i = 0; i < 256; ++i)
            p[i] = saturate_cast<uchar>(pow(i / 255.0, gamma_) * 255.0);
        Mat res = img.clone();
        LUT(img, lookUpTable, res);

    完整代码:

    #include <iostream>
    #include "opencv2/imgcodecs.hpp"
    #include "opencv2/highgui.hpp"
    
    // we're NOT "using namespace std;" here, to avoid collisions between the beta variable and std::beta in c++17
    using std::cout;
    using std::endl;
    using namespace cv;
    
    namespace
    {
    /** Global Variables */
    int alpha = 100;
    int beta = 100;
    int gamma_cor = 100;
    Mat img_original, img_corrected, img_gamma_corrected;
    
    void basicLinearTransform(const Mat &img, const double alpha_, const int beta_)
    {
        Mat res;
        img.convertTo(res, -1, alpha_, beta_);
    
        hconcat(img, res, img_corrected);
        imshow("Brightness and contrast adjustments", img_corrected);
    }
    
    void gammaCorrection(const Mat &img, const double gamma_)
    {
        CV_Assert(gamma_ >= 0);
        //! [changing-contrast-brightness-gamma-correction]
        Mat lookUpTable(1, 256, CV_8U);
        uchar* p = lookUpTable.ptr();
        for( int i = 0; i < 256; ++i)
            p[i] = saturate_cast<uchar>(pow(i / 255.0, gamma_) * 255.0);
    
        Mat res = img.clone();
        LUT(img, lookUpTable, res);
        //! [changing-contrast-brightness-gamma-correction]
    
        hconcat(img, res, img_gamma_corrected);
        imshow("Gamma correction", img_gamma_corrected);
    }
    
    void on_linear_transform_alpha_trackbar(int, void *)
    {
        double alpha_value = alpha / 100.0;
        int beta_value = beta - 100;
        basicLinearTransform(img_original, alpha_value, beta_value);
    }
    
    void on_linear_transform_beta_trackbar(int, void *)
    {
        double alpha_value = alpha / 100.0;
        int beta_value = beta - 100;
        basicLinearTransform(img_original, alpha_value, beta_value);
    }
    
    void on_gamma_correction_trackbar(int, void *)
    {
        double gamma_value = gamma_cor / 100.0;
        gammaCorrection(img_original, gamma_value);
    }
    }
    
    int main( int argc, char** argv )
    {
        CommandLineParser parser( argc, argv, "{@input | ../data/lena.jpg | input image}" );
        img_original = imread( parser.get<String>( "@input" ) );
        if( img_original.empty() )
        {
          cout << "Could not open or find the image!\n" << endl;
          cout << "Usage: " << argv[0] << " <Input image>" << endl;
          return -1;
        }
    
        img_corrected = Mat(img_original.rows, img_original.cols*2, img_original.type());
        img_gamma_corrected = Mat(img_original.rows, img_original.cols*2, img_original.type());
    
        hconcat(img_original, img_original, img_corrected);
        hconcat(img_original, img_original, img_gamma_corrected);
    
        namedWindow("Brightness and contrast adjustments");
        namedWindow("Gamma correction");
    
        createTrackbar("Alpha gain (contrast)", "Brightness and contrast adjustments", &alpha, 500, on_linear_transform_alpha_trackbar);
        createTrackbar("Beta bias (brightness)", "Brightness and contrast adjustments", &beta, 200, on_linear_transform_beta_trackbar);
        createTrackbar("Gamma correction", "Gamma correction", &gamma_cor, 200, on_gamma_correction_trackbar);
    
        on_linear_transform_alpha_trackbar(0, 0);
        on_gamma_correction_trackbar(0, 0);
    
        waitKey();
    
        imwrite("linear_transform_correction.png", img_corrected);
        imwrite("gamma_correction.png", img_gamma_corrected);
    
        return 0;
    }
    


     


    Python

    lookUpTable = np.empty((1,256), np.uint8)
        for i in range(256):
            lookUpTable[0,i] = np.clip(pow(i / 255.0, gamma) * 255.0, 0, 255)
        res = cv.LUT(img_original, lookUpTable)

     

    完整代码:

    from __future__ import print_function
    from __future__ import division
    import cv2 as cv
    import numpy as np
    import argparse
    
    alpha = 1.0
    alpha_max = 500
    beta = 0
    beta_max = 200
    gamma = 1.0
    gamma_max = 200
    
    def basicLinearTransform():
        res = cv.convertScaleAbs(img_original, alpha=alpha, beta=beta)
        img_corrected = cv.hconcat([img_original, res])
        cv.imshow("Brightness and contrast adjustments", img_corrected)
    
    def gammaCorrection():
        ## [changing-contrast-brightness-gamma-correction]
        lookUpTable = np.empty((1,256), np.uint8)
        for i in range(256):
            lookUpTable[0,i] = np.clip(pow(i / 255.0, gamma) * 255.0, 0, 255)
    
        res = cv.LUT(img_original, lookUpTable)
        ## [changing-contrast-brightness-gamma-correction]
    
        img_gamma_corrected = cv.hconcat([img_original, res]);
        cv.imshow("Gamma correction", img_gamma_corrected);
    
    def on_linear_transform_alpha_trackbar(val):
        global alpha
        alpha = val / 100
        basicLinearTransform()
    
    def on_linear_transform_beta_trackbar(val):
        global beta
        beta = val - 100
        basicLinearTransform()
    
    def on_gamma_correction_trackbar(val):
        global gamma
        gamma = val / 100
        gammaCorrection()
    
    parser = argparse.ArgumentParser(description='Code for Changing the contrast and brightness of an image! tutorial.')
    parser.add_argument('--input', help='Path to input image.', default='lena.jpg')
    args = parser.parse_args()
    
    img_original = cv.imread(cv.samples.findFile(args.input))
    if img_original is None:
        print('Could not open or find the image: ', args.input)
        exit(0)
    
    img_corrected = np.empty((img_original.shape[0], img_original.shape[1]*2, img_original.shape[2]), img_original.dtype)
    img_gamma_corrected = np.empty((img_original.shape[0], img_original.shape[1]*2, img_original.shape[2]), img_original.dtype)
    
    img_corrected = cv.hconcat([img_original, img_original])
    img_gamma_corrected = cv.hconcat([img_original, img_original])
    
    cv.namedWindow('Brightness and contrast adjustments')
    cv.namedWindow('Gamma correction')
    
    alpha_init = int(alpha *100)
    cv.createTrackbar('Alpha gain (contrast)', 'Brightness and contrast adjustments', alpha_init, alpha_max, on_linear_transform_alpha_trackbar)
    beta_init = beta + 100
    cv.createTrackbar('Beta bias (brightness)', 'Brightness and contrast adjustments', beta_init, beta_max, on_linear_transform_beta_trackbar)
    gamma_init = int(gamma * 100)
    cv.createTrackbar('Gamma correction', 'Gamma correction', gamma_init, gamma_max, on_gamma_correction_trackbar)
    
    on_linear_transform_alpha_trackbar(alpha_init)
    on_gamma_correction_trackbar(gamma_init)
    
    cv.waitKey()

    查找线性表用于提高计算性能,因为只需要计算一次256个值。

    展开全文
  • 图像处理之调整亮度与对比度

    千次阅读 2017-06-07 14:32:18
    图像处理之调整亮度与对比度   很多时候,一张图像被过度曝光显得很白,或者光线不足显得很暗,有时候背景跟图像人物 也观察不清楚,这个时候可以通过调节图像的两个基本属性-亮度与对比度来获得整体效果 ...
  • 通过重新计算颜色分量,可以修改图像亮度和对比度。 graph(x,y) = graph_src(x,y) * alpha + beta #define alpha 1.2 #define beta 20 inline uchar brighten(uchar b) { return saturate_cast<uchar>(b*...
  • 1 图像读取与保存 f=imread(‘路径+图像名称.后缀’)%读取图像 imshow(f,G)%f是2*2数组,G是该灰度图像的等级,默认256 imshow(f,[low high])%所有小于或等于low的显示为黑色,所有大于或等于high的值都显示为...
  • 本文将介绍数字图像处理中两个基本内容---图像亮度对比度,详细讲解两种基本的亮度对比度调节算法,并使用C语言进行算法实现,在教会初学者算法的同时,不依赖任何第三方库编程实现,学以致用且易学易用。
  • 数字图像处理,实现图像非线性调节亮度的Python实现,
  • 简单来说,目的就是想在图像中模拟不同角度光源对图中物体造成的不同的光照和阴影效果。目前有些工作通过3D模型重建来做这个事,效果很不错,但是本身比较复杂。这里就用了一个比较简单粗暴的方法来模拟,在我们的...
  • C++图像处理 -- 线性亮度/对比度调整

    万次阅读 热门讨论 2013-02-05 08:52:04
    阅读提示: 《C++图像处理》系列以代码清晰,可读性为主,全部使用C++代码。 《Delphi图像处理》系列以效率为侧重点,一般代码为PASCAL,核心代码采用... 本文代码是在《C++图像处理 -- 亮度/对比度调整》基础上,
  • 上一期:医学图像处理——Hough变换的线检测 之前的边缘检测我们已经由浅及深的过关斩将把基础的知识一一扫荡过了,从今天开始我们就开始进入到Imaging Enhencement上来了,希望大家能在其中收获到自己想要的东西...
  • 图像亮度自适应调整

    千次阅读 热门讨论 2016-04-06 19:27:16
    简介  本篇主要是对论文:Automatic Exposure ... 根据对输入图像亮度信息进行分析处理,进而获得该图片对应的S型Gamma曲线。利用这条曲线对输入图像进行处理,得到更好曝光和细节效果的图像。 算法实现
  • 关键词:图像处理亮度调整 色彩平衡Photoshop   参考博客 http://blog.csdn.net/maozefa/article/details/4493395 http://www.cnblogs.com/Imageshop/archive/2011/11/10/2244664.
  • C++图像处理 -- 亮度/对比度调整

    万次阅读 多人点赞 2012-12-21 14:32:36
    阅读提示: 《C++图像处理》系列以代码清晰,可读性为主,全部使用C++代码。 《Delphi图像处理》系列以效率为侧重点,一般代码为PASCAL,核心代码采用BASM。... 在《Delphi图像处理 -- 亮度/对比度调整》一文实现了P
  • 图像处理------调整亮度与饱和度

    千次阅读 2015-07-24 14:50:25
    什么是亮度:简单点说一幅图像亮度属性是图像的RGB值的大小,RGB各个值越大亮度越高RGB分量取值范围为0~255之间。调整图像亮度。什么是饱和度:饱和度是是指颜色的强度,调整饱和度可以修正过度曝光或者未充分...
  • 亮度调整算法说明(完整python代码在文末): 本算法的基本原理就是对像素点统一进行加上或减去某个调整值,已达到亮度的增强或减弱。包括基于RGB空间R、G、B值的调整和基于HSV空间V值的调整。 (参考CSDN博客:...
  • 通过OpenCV,制作一个有关图像处理的在Linux下的软件。 制作可以自动处理图像亮度的简单软件。 算法思想就是给每个像素加上一个固定的值来改变亮度。但是对于不同的图片效果就不是很好,最好是把代码中两行解注释...
  • 转载自:https://blog.csdn.net/linxid/article/details/78147625亮度(灰度)变换是一种非常重要的空间域内处理图像的方法,主要介绍几个亮度变换函数,以及应用。函数简介1.imadjust该函数用来调整亮度,可以映射...
  • 上一篇文章,我们讲解了图像处理中的卷积操作和平滑(也就是模糊)处理,这篇文章我们进行亮度和对比度的变化。   其实,亮度是啥玩意? 亮度就是比较亮眼咯…… 实际上对于RGBA颜色空间,变亮其实就等于R、G...
1 2 3 4 5 ... 20
收藏数 7,361
精华内容 2,944
关键字:

图像处理亮度调节