【图像处理】伽马亮度矫正

采集的图像部分区域较亮,而部分区域较暗,需要进行亮度矫正来调整整个图片的亮度,使得整体亮度较为均匀。

传统Gamma函数亮度矫正

gamma校正原理
在这里插入图片描述

假设图像F中有一个像素A,值是 200 ,那么对这个像素进行校正必须执行如下步骤:

1.归一化 :将像素值转换为 0 ~ 1 之间的实数。 算法如下 : F/255 。对于像素 A 而言 , 其对应的归一化值为 0. 7843 。

2.预补偿 :求出gamma 值。这一步包含一个 求指数运算。若 gamma = 1 /2.2 = 0. 454545 , 对归一化后的 A 值进行预补偿的结果就 是 0. 7843 ^0. 454545 = 0. 8954 。

3.反归一化 :将经过预补偿的实数值反变换为 0 ~ 255 之间的整数值,即将预补偿的实数值乘以255。0.8954×255=228 , 这个 228 就是最后送 入显示器的数据。
即当 gamma<1时,输出图像变亮;当gamma >1时,输出图像变暗。

以下是python代码:

#-*-coding: UTF-8-*-
import numpy as np
import cv2
import math
from matplotlib import pyplot as plt
#import Recognise
 
#读取图片
img = cv2.imread('5.jpg')
#将原图片(RGB)转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#显示并保存
cv2.imshow('gray', gray)
cv2.imwrite('gray.jpg', gray)
#将灰度图做gamma校正运算
image = np.power(gray/255.0, 1/2.2)
cv2.imshow('imagechange', image)
 
#由于后面需要进行类型转换,转换成uint8,所以需要对其乘以255处理
image = image * 255
 
cv2.imwrite('imagechange.jpg',image)
#这里需要将image->转换为uint8类型,因为会出现类型不匹配
gray2rgb = cv2.cvtColor(image.astype(np.uint8), cv2.COLOR_GRAY2RGB)
#保存图片
cv2.imwrite('gray2rgb.jpg', gray2rgb)
 
cv2.waitKey(0)
cv2.destroyAllWindows()

假设图像的分辨率为 800*600 ,对它进行 gamma 校正,需要执行 48 万个浮点数乘法、除法和指数运算。效率太低,根本达不到实时的效果。

针对上述情况,提出了一种快速算法,如果能够确知图像的像素取值范围 , 例如 , 0 ~ 255 之间的整数 , 则图像中任何一个像素值只能 是 0 到 255 这 256 个整数中的某一个 ; 在 gamma 值 已知的情况下 ,0 ~ 255 之间的任一整数 , 经过“归一 化、预补偿、反归一化”操作后 , 所对应的结果是唯一的 , 并且也落在 0 ~ 255 这个范围内。

如前例 , 已知 gamma 值为 2. 2 , 像素 A 的原始值是 200 , 就可求得 经 gamma 校正后 A 对应的预补偿值为 228 。基于上述原理 , 我们只需为 0 ~ 255 之间的每个整数执行一次预补偿操作 , 将其对应的预补偿值存入一个预先建立的 gamma 校正查找表 (LUT:Look Up Table) , 就可以使用该表对任何像素值在 0 ~ 255 之 间的图像进行 gamma 校正。

以下是c++代码:

#include <iostream>
#include <opencv2/opencv.hpp>

// 伽马亮度矫正函数
cv::Mat gammaCorrection(const cv::Mat& inputImage, float gamma)
{
    cv::Mat outputImage;
    cv::Mat lookupTable(1, 256, CV_8U);

    // 计算伽马校正的查找表
    for (int i = 0; i < 256; ++i)
    {
        lookupTable.at<uchar>(i) = cv::saturate_cast<uchar>(pow(i / 255.0, gamma) * 255.0);
    }

    // 应用查找表进行伽马校正
    cv::LUT(inputImage, lookupTable, outputImage);

    return outputImage;
}

int main()
{
    // 读取图像
    cv::Mat inputImage = cv::imread("input.jpg", cv::IMREAD_COLOR);

    // 检查图像是否成功读取
    if (inputImage.empty())
    {
        std::cout << "Failed to read the image!" << std::endl;
        return -1;
    }

    // 设置伽马值
    float gamma = 2.2;

    // 进行伽马亮度矫正
    cv::Mat outputImage = gammaCorrection(inputImage, gamma);

    // 显示原始图像和矫正后的图像
    cv::imshow("Original Image", inputImage);
    cv::imshow("Gamma Corrected Image", outputImage);
    cv::waitKey(0);

    return 0;
}

参考链接

https://blog.csdn.net/qq_35044509/article/details/78713289?
https://blog.csdn.net/LaoYuanPython/article/details/106966800?

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值