美文网首页
OpenGL ES 3.0(七)图像处理概述

OpenGL ES 3.0(七)图像处理概述

作者: StevenChou | 来源:发表于2018-09-01 23:05 被阅读118次

    图像处理的基本原理

    亮度调节

    亮度调节有非线性、线性两种实现方式。非线性亮度调节的实现非常简单,伪代码如下:

    byte* image = loadImage();
    byte* r, g, b = interlaceImage(image);
    int brightness = 3;
    r += brightness;
    g += brightness;
    b += brightness;
    

    线性亮度调节基于 HSL 色彩模式,HSL 分别代表色相(Hue)、饱和度(Saturation)、明度(Lightness),每个通道都可以使用 0~255 的数值来表示,线性亮度调节就是通过调节 L 的值实现的:

    L = (max(r, max(g, b)) + min(r, min(g, b))) / 2;
    
    if (L > 128) {
        rHS = (r * 128 - (L - 128) * 256) / (256 - L);
        gHS = (g * 128 - (L - 128) * 256) / (256 - L);
        bHS = (b * 128 - (L - 128) * 256) / (256 - L);
    } else {
        rHS = r * 128 / L;
        gHS = g * 128 / L;
        bHS = b * 128 / L;
    }
    
    int delta = 20; // [0 - 255]
    newL = L + delta - 128;
    if (newL > 0) {
        newR = rHS + (256 - rHS) * newL / 128;
        newG = gHS + (256 - gHS) * newL / 128;
        newB = bHS + (256 - bHS) * newL / 128;
    } else {
        newR = rHS + rHS * newL / 128;
        newG = gHS + gHS * newL / 128;
        newB = bHS + bHS * newL / 128;
    }
    

    对比度调节

    对比度要对 RGB 三个通道同时调整,不能分别调整,否则会造成色偏的问题。设置对比度的函数如下:

    y = (x - 0.5) * contrast + 0.5;
    

    假如图片原来的色彩范围为 0.25 ~ 0.75,那么当 contrast 取值为 1.2 时,新的图片的色彩范围会变成 0.29 ~ 0.89,相当于扩大了颜色的表示范围,相应了,如果 contrast 取值小于 1,则相当于缩小了颜色的表示范围。

    饱和度调节

    饱和度调节最简单的方法是判断 R、G、B 值是否大于 128,大于则加上调节值,小于则减去调节值;也可以将 RGB 转换为 HSL,然后调节 S 值。

    这里介绍第一种方法,首先需要通过 RGB 计算像素点的亮度值:

    luminance = 0.2125 * R + 0.7154 * G + 0.0721 * B;
    

    然后设计一个参数 saturation,取值范围为 [0.0, 2.0]:

    output = (1.0 - saturation) * vec3(luminance) + saturation * vec3(R, G, B);
    

    图像处理进阶

    图像的卷积过程

    线性滤波是一种常用的图像处理方法,做法很简单,假设有一个二维的滤波器矩阵,称为卷积核,对于要处理的图像的每个像素点,先计算它的领域像素和滤波器矩阵的对应元素的乘积,然后加起来,以此作为该像素位置的值,即完成整个滤波过程。

    对图像和滤波矩阵进行逐个元素相乘再求和的操作称为卷积,相当于将一个二维的函数移动到另一个二维函数的所有位置,对于平面图像的卷积,一般称为 2D 卷积。

    通常选用为 3x3 或 5x5的卷积核,比如:

    int matrix[3][3] = {
        0, 0, 0,
        0, 1, 0,
        0, 0, 0
    }
    

    滤波器矩阵一般有如下要求:
    1) 元素数目为奇数,这样才会有一个中心
    2) 所有元素之和应该等于 1,这是为了保持亮度不变
    3) 为了防止过载,滤波后的像素点的值一定要维持在 0 ~ 255 之间

    锐化效果器

    图像的锐化就是补偿图像的轮廓,增强图像的边缘以及灰度跳变的部分,使图像变得更加清晰。锐化效果器也是通过图像卷积来完成的,定义卷积矩阵如下:

    int matrix[3][3] = {
        0, -k, 0,
        -k, 4k + 1, -k,
        0, -k, 0
    }
    

    这个卷积矩阵实际上就是计算当前点和领域像素点的 Diff 值,然后将素有的 Diff 值加到像素点上,因此,当前像素点和领域像素点相差不大时,卷积之后的结果不变;而当它是正好是一个边缘或者细节点的时候,就会更加突出。

    边缘检测算法与锐化类似,检测横向边缘的的矩阵如下:

    int matrix[3][3] = {
        -1, -1, -1,
         0,  0,  0,
         1,  1,  1
    }
    

    检测竖向边缘的的矩阵如下:

    int matrix[3][3] = {
        -1,  0,  1,
        -1,  0,  1,
        -1,  0,  1
    }
    

    找到这两个边缘点之后,可以做一个平方和来代替当前点的亮度值,差别越大,亮度值越大。

    高斯模糊算法

    模糊滤波器其实就是对周围像素进行加权平均处理,对于均值模糊算法来说,周围所有领域点的权值都相同,所以不是很平滑。高斯模糊就是用来解决这个问题的,它会把图像的模糊处理的很平滑,被广泛用于图像降噪上。

    高斯模糊的的权重是正态分布的权重,正态分布在图形上表示为一种钟形曲线,越接近中心,取值越大,越远离中心,取值越小。在图像处理领域,需要使用二维的高斯分布函数来实现高斯模糊算法,二维高斯函数如下:

    二维正态分布

    根据该函数,可以给出一个 5x5 的卷积矩阵:

    int matrix[3][3] = {
        1,  4,  7,  4, 1,
        4, 16, 26, 16, 4,
        7, 26, 41, 26, 7,
        4, 16, 26, 16, 4,
        1,  4,  7,  4, 1,
    }
    

    双边滤波算法

    双边滤波是一种可以降噪保边的滤波器,它由两个因素共同影响,一个是由几何空间距离;另一个是像素差值。几何空间距离类似高斯模糊,由距离中心像素点的远近来确定权重值,然后由像素差值来决定是否让这个权重值参与权重计算,如果差值过大,那么就有可能丢弃该权重值,以达到保边的效果;如果差值不大,那么就保留该权重值,以达到降噪的效果。

    最终的权重 = 高斯权重 * 像素差值权重(差值越大,权重越小)

    图层混合

    假设 A 代表上面的图层的色彩值,B 代表下面的图层的色彩值,C 代表混合之后的色彩值,取值范围为 [0.0, 1.0]

    正片叠底混合

    公式如下:

    C = A * B
    

    任何颜色与白色正片叠底之后仍保持原来的颜色不变,而与其它颜色执行正片叠底混合模式后,会产生暗室中以该颜色照明的效果。

    滤色混合模式

    C = 1 - (1 - A) * (1 - B)
    

    任何颜色与黑色混合,原色不受影响;与白色混合,得到白色;与其它颜色混合,会产生漂白的效果。

    叠加混合模式

    if (B <= 0.5) {
        C = 2 * A * B
    } else {
        C = 1 - 2 * (1 - A) * (1 - B)
    }
    

    可使底色的图像饱和度以及对比度得到相应提高,使图像看起来更加鲜亮。

    柔光混合模式

    if (A <= 0.5) {
        C = (2 * A - 1) * (B - B * B) + B
    } else {
        C = (2 * A - 1) * (sqrt(B) - B * B) + B
    }
    

    根据绘图色的明暗程度来决定最终色是变亮还是变暗,与发散的聚光灯照再图像上的效果类似。

    强光混合模式

    if (A <= 0.5) {
        C = 2 * A * B
    } else {
        C = 1 - 2 * (1 - A) * (1 - B);
    }
    

    根据绘图色来决定正片叠底还是滤色混合模式,与耀眼的聚光灯照在图像上的效果相似。

    相关文章

      网友评论

          本文标题:OpenGL ES 3.0(七)图像处理概述

          本文链接:https://www.haomeiwen.com/subject/gvhpwftx.html