• AWB(Auto White Banlance)——自动白平衡


    产生原因

    image

    方法

    imageimageimageimage

    代码

    GW灰度世界白平衡算法

    灰度世界算法(Gray World)是以灰度世界假设为基础的,该假设认为对于一幅有着大量色彩变化的图像, R、 G、 B 三个分量的平均值趋于同一个灰度K。

    Rgain=k/Ravg" role="presentation" style="text-align: center; position: relative;">Rgain=k/Ravg

    Ggain=k/Gavg" role="presentation" style="text-align: center; position: relative;">Ggain=k/Gavg

    Bgain=k/Bavg" role="presentation" style="text-align: center; position: relative;">Bgain=k/Bavg

    然后通过k值来求各个通达的增益。

    1. 直接给定为固定值, 取其各通道最大值的一半,即取为127或128;
    2. 令 K = (Raver+Gaver+Baver)/3,其中Raver,Gaver,Baver分别表示红、 绿、 蓝三个通道的平均值。
      算法的第二步是分别计算各通道的增益:
      k=(Bavg+Gavg+Ravg)/3" role="presentation" style="text-align: center; position: relative;">k=(Bavg+Gavg+Ravg)/3
    3. 设定G通道不变,让R和B通道往G通道上靠,即:
      Rgain=Rave/Gave" role="presentation" style="text-align: center; position: relative;">Rgain=Rave/Gave

      Bgain=Bave/Gave" role="presentation" style="text-align: center; position: relative;">Bgain=Bave/Gave

      新的像素的绿色通道不变,红色和蓝色通道通过绿色通道来求
    1. import cv2 as cv
    2. import numpy as np
    3. src = cv.imread('test.jpg')
    4. # 求出各个颜色分量的平均值
    5. b_avg = np.mean(src[:, :, 0])
    6. g_avg = np.mean(src[:, :, 1])
    7. r_avg = np.mean(src[:, :, 2])
    8. # 求出灰度世界的灰度值
    9. k = (b_avg + g_avg + r_avg)/3
    10. # 求出各个颜色分量的增益
    11. b_gain = k / b_avg
    12. g_gain = k / g_avg
    13. r_gain = k / r_avg
    14. # 定义一个新的矩阵存放变换后的图像
    15. src1 = np.zeros(src.shape)
    16. src1[:, :, 0] = src[:, :, 0] * b_gain
    17. src1[:, :, 1] = src[:, :, 1] * g_gain
    18. src1[:, :, 2] = src[:, :, 2] * r_gain
    19. # 计算后类型为浮点数,需要类型转换
    20. src1 = src1.astype(np.uint8)
    21. # 拼接两张图片,便于观察
    22. img = np.hstack([src, src1])
    23. cv.namedWindow('input_image', cv.WINDOW_AUTOSIZE)
    24. cv.imshow('input_image', img)
    25. cv.waitKey(0)
    26. cv.destroyAllWindows()

    PR完全反射白平衡算法

    图像中最亮的点为白点,那么各个通道的最大值应该趋近白色,可是设定一个K值,如255,那么图像中最两点的值应该趋于255,这样就可以计算出各通道的增益:

    Rgain=k/Rmax" role="presentation" style="text-align: center; position: relative;">Rgain=k/Rmax

    Ggain=k/Gmax" role="presentation" style="text-align: center; position: relative;">Ggain=k/Gmax

    Bgain=k/Bmax" role="presentation" style="text-align: center; position: relative;">Bgain=k/Bmax

    1. import cv2 as cv
    2. import numpy as np
    3. src = cv.imread('test.jpg')
    4. # 求出各个颜色分量的增益
    5. b_gain = 255 / np.max(src[:, :, 0])
    6. g_gain = 255 / np.max(src[:, :, 1])
    7. r_gain = 255 / np.max(src[:, :, 2])
    8. # 定义一个新的矩阵存放变换后的图像
    9. src1 = np.zeros(src.shape)
    10. src1[:, :, 0] = src[:, :, 0] * b_gain
    11. src1[:, :, 1] = src[:, :, 1] * g_gain
    12. src1[:, :, 2] = src[:, :, 2] * r_gain
    13. # 计算后类型为浮点数,需要类型转换
    14. src1 = src1.astype(np.uint8)
    15. # 拼接两张图片,便于观察
    16. img = np.hstack([src, src1])
    17. cv.namedWindow('input_image', cv.WINDOW_AUTOSIZE)
    18. cv.imshow('input_image', img)
    19. cv.waitKey(0)
    20. cv.destroyAllWindows()

    通过GW和PR两种算法的正交组合,从而保留两者的优点,具体的算法公式如下:

    Kave=(Rave+Gave+Bave)/3" role="presentation" style="text-align: center; position: relative;">Kave=(Rave+Gave+Bave)/3

    Kmax=(Rmax+Gmax+Bmax)/3" role="presentation" style="text-align: center; position: relative;">Kmax=(Rmax+Gmax+Bmax)/3

    uRave2+vRave=Kave" role="presentation" style="text-align: center; position: relative;">uRave2+vRave=Kave

    uRmax2+vRmax=Kmax" role="presentation" style="text-align: center; position: relative;">uRmax2+vRmax=Kmax

    这是R通道的算法公式,求出u和v然后通过以下公式换算出新的值:
    Rnew=uRorg2+vRorg" role="presentation" style="text-align: center; position: relative;">Rnew=uRorg2+vRorg

    1. import cv2 as cv
    2. import numpy as np
    3. src0 = cv.imread('..//images//NikonD5200_0001_G_AS.png')
    4. src = src0.astype(np.uint16) # 调整一下数据类型,防止算术运算溢出
    5. # 求出各个颜色分量的平均值
    6. b_ave = np.mean(src[:, :, 0])
    7. g_ave = np.mean(src[:, :, 1])
    8. r_ave = np.mean(src[:, :, 2])
    9. # 各个颜色分量的最大值
    10. b_max = np.max(src[:, :, 0])
    11. g_max = np.max(src[:, :, 1])
    12. r_max = np.max(src[:, :, 2])
    13. # 根据QCGP公式求出系数
    14. k_ave = (b_ave + g_ave + r_ave)/3
    15. k_max = (b_max + g_max + r_max)/3
    16. k_matrix = np.mat([[k_ave], [k_max]])
    17. # 通过矩阵求出B通道的转换矩阵,并计算出新图的B通道
    18. b_coefficient_matrix = np.mat([[b_ave * b_ave, b_ave],
    19. [b_max * b_max, b_max]])
    20. b_conversion_matrix = b_coefficient_matrix.I * k_matrix
    21. b = (src[:, :, 0]).transpose()
    22. bb = (src[:, :, 0] * src[:, :, 0]).transpose()
    23. b = np.stack((bb, b), axis=0).transpose()
    24. b_des = np.dot(b, np.array(b_conversion_matrix))
    25. b_des = b_des.astype(np.uint8).reshape([280, 471])
    26. # 通过矩阵求出G通道的转换矩阵,并计算出新图的G通道
    27. g_coefficient_matrix = np.mat([[g_ave * g_ave, g_ave],
    28. [g_max * g_max, g_max]])
    29. g_conversion_matrix = g_coefficient_matrix.I * k_matrix
    30. g = (src[:, :, 1]).transpose()
    31. gg = (src[:, :, 1] * src[:, :, 1]).transpose()
    32. g = np.stack((gg, g), axis=0).transpose()
    33. g_des = np.dot(g, np.array(g_conversion_matrix))
    34. g_des = g_des.astype(np.uint8).reshape([280, 471])
    35. # 通过矩阵求出R通道的转换矩阵,并计算出新图的R通道
    36. r_coefficient_matrix = np.mat([[r_ave * r_ave, r_ave],
    37. [r_max * r_max, r_max]])
    38. r_conversion_matrix = r_coefficient_matrix.I * k_matrix
    39. r = (src[:, :, 2]).transpose()
    40. rr = (src[:, :, 2] * src[:, :, 2]).transpose()
    41. r = np.stack((rr, r), axis=0).transpose()
    42. r_des = np.dot(r, np.array(r_conversion_matrix))
    43. r_des = r_des.astype(np.uint8).reshape([280, 471])
    44. # 用一个新的矩阵接受新的图片,注意数据类型要和原图一致
    45. src1 = np.zeros(src.shape).astype(np.uint8)
    46. src1[:, :, 0] = b_des
    47. src1[:, :, 1] = g_des
    48. src1[:, :, 2] = r_des
    49. # 显示图片
    50. img = np.hstack([src0, src1])
    51. cv.namedWindow("AWB", cv.WINDOW_AUTOSIZE)
    52. cv.imshow("AWB", img)
    53. cv.waitKey(0)
    54. cv.destroyAllWindows()
  • 相关阅读:
    从零开始写 Docker(三)---基于 cgroups 实现资源限制
    Rust的模块化
    百度paddleocr检测训练
    flutter 应用签名 Mac
    人力资源行业投资建议
    FastAPI 学习之路(三十三)操作数据库
    单元测试及其工具Junit
    抽象工厂设计模式是什么?什么是 Abstract Factory 抽象工厂设计模式?Python 抽象工厂设计模式示例代码
    MyBatis 的在使用上的注意事项及其辨析
    Java内存模型:创建对象在堆区如何分配内存
  • 原文地址:https://blog.csdn.net/weixin_44708624/article/details/126109266