opencv学习笔记27-opencv伽马校正调整图像亮度和对比度

一、函数:

a.MatIterator_ 类:

(1)模板类定义:

/** @brief Matrix read-write iterator
*/
template<typename _Tp>
class MatIterator_ : public MatConstIterator_<_Tp>
{
public:
    typedef _Tp* pointer;
    typedef _Tp& reference;

    typedef std::random_access_iterator_tag iterator_category;

    //! the default constructor
    MatIterator_();
    //! constructor that sets the iterator to the beginning of the matrix
    MatIterator_(Mat_<_Tp>* _m);
    //! constructor that sets the iterator to the specified element of the matrix
    MatIterator_(Mat_<_Tp>* _m, int _row, int _col=0);
    //! constructor that sets the iterator to the specified element of the matrix
    MatIterator_(Mat_<_Tp>* _m, Point _pt);
    //! constructor that sets the iterator to the specified element of the matrix
    MatIterator_(Mat_<_Tp>* _m, const int* _idx);
    //! copy constructor
    MatIterator_(const MatIterator_& it);
    //! copy operator
    MatIterator_& operator = (const MatIterator_<_Tp>& it );

    //! returns the current matrix element
    _Tp& operator *() const;
    //! returns the i-th matrix element, relative to the current
    _Tp& operator [](ptrdiff_t i) const;

    //! shifts the iterator forward by the specified number of elements
    MatIterator_& operator += (ptrdiff_t ofs);
    //! shifts the iterator backward by the specified number of elements
    MatIterator_& operator -= (ptrdiff_t ofs);
    //! decrements the iterator
    MatIterator_& operator --();
    //! decrements the iterator
    MatIterator_ operator --(int);
    //! increments the iterator
    MatIterator_& operator ++();
    //! increments the iterator
    MatIterator_ operator ++(int);
};

(2)继承关系:

  • MatIterator_ 继承自 MatConstIterator_<_Tp>,这意味着它具有只读迭代器的特性,并添加了写入功能。

(3)类型定义:

  • pointer 和 reference 类型别名分别定义了迭代器指向的指针类型和引用类型。

(4)迭代器类别:

  • iterator_category 定义了迭代器的类别,这里是 std::random_access_iterator_tag,表示迭代器支持随机访问。

(5)构造函数:

  • 提供了多个构造函数,允许以不同的方式初始化迭代器,例如指定矩阵、行号、列号或点坐标。

(6)赋值操作:

  • 复制构造函数和赋值运算符允许将一个迭代器赋值给另一个迭代器。

(7)解引用操作:

  • operator * 允许通过解引用迭代器来访问当前指向的矩阵元素。
  • operator [] 允许访问相对于当前迭代器位置的第 i 个元素。

(8)位移操作:

  • operator += 和 operator -= 分别用于将迭代器向前或向后移动指定数量的元素。
  • operator ++ 和 operator -- 用于递增和递减迭代器。

(9)前后缀递增/递减:

  • 提供了前后缀版本的递增和递减运算符,以满足不同的使用场景。

 b.saturate_cast 函数:

(1)函数原型:

template<> inline uchar saturate_cast<uchar>(float v) { int iv = cvRound(v); return saturate_cast<uchar>(iv); }

 

(2) 模板特化:

  • template<> 表示这是一个模板函数的特化版本,即针对特定类型(这里是 uchar)的实现。

(3)内联函数:

  • inline 关键字表示这个函数在编译时会被插入到每个调用该函数的地方,以减少函数调用的开销。

(4)函数返回类型:

  • uchar 是 OpenCV 中定义的 8 位无符号整型别名。

(5)函数名:

  • saturate_cast 是函数的名称,表示执行饱和的类型转换。

(6)参数:

  • 函数接受一个 float 类型的参数 v,这是要转换的值。

(7)转换逻辑:

  • int iv = cvRound(v); 首先将浮点数 v 四舍五入到最近的整数 ivcvRound 是 OpenCV 中的四舍五入函数。
  • return saturate_cast<uchar>(iv); 然后调用 saturate_cast 函数模板,将整数 iv 转换为 uchar 类型。如果 iv 超出了 uchar 类型可以表示的范围(0-255),这个函数会进行饱和处理,即把值限制在可表示的最大或最小范围内。

(8)饱和处理:

  • 如果 iv 小于 0,它将被转换为 0;如果 iv 大于 255,它将被转换为 255。

二、示例代码:

#include <opencv2/core/utils/logger.hpp>
#include <opencv2/opencv.hpp>           
#include <opencv2/videoio.hpp>       
#include <opencv2/objdetect.hpp>        
#include <opencv2/highgui/highgui_c.h>  
#include <iostream>                     

using namespace cv;                    
using namespace std; 
   
#define RGB_image		1;		//0,使用灰度图进行演示	1.使用RGB图进行演示
#define GAMMA_FACTOR	0.5;	//gamma矫正的gamma值
int gammaCorrection(cv::Mat srcMat, cv::Mat& dstMat, float gamma);

int main() {
    utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);
    int readType = RGB_image; // 定义读取图像的类型
    Mat srcMat; // 定义源图像的Mat对象

    // 检查参数是否合法
    if (readType == 0) {
    //以灰度图方式读取图像
        srcMat = imread("C:\\Users\\86173\\Desktop\\TI\\Gama.jpg",0); 
    }
    else if (readType == 1) {
    //以原图方式读取图像
        srcMat = imread("C:\\Users\\86173\\Desktop\\TI\\Gama.jpg"); 
    }
    else {
        cout << "参数错误!" << endl; // 参数错误提示
        return -1; // 参数不合法时返回错误码
    }

    if (srcMat.empty()) { // 检查图像是否成功加载
        cout << "fail to read pic!" << endl; // 读取图像失败提示
        return -1; // 读取图像失败时返回错误码
    }

    Mat Gam_image; // 定义目标图像的Mat对象
    float gamma = GAMMA_FACTOR; // 设置伽马值

    // 对图像进行伽马校正
    if (srcMat.type() == CV_8UC1) { // 如果图像是单通道(灰度图)
        gammaCorrection(srcMat, Gam_image, gamma); // 调用伽马校正函数
    }
    else if (srcMat.type() == CV_8UC3) { // 如果图像是三通道(彩色图)
        Mat channel[3]; // 定义颜色通道数组
        Mat out[3]; // 定义输出图像数组
        float hist[3][256]; // 定义直方图数组,未使用

        // 分离颜色通道
        split(srcMat, channel);

        for (int i = 0; i < 3; i++) { // 对每个通道进行伽马校正
            gammaCorrection(channel[i], out[i], gamma); // 调用伽马校正函数
        }

        // 合并校正后的通道
        merge(out, 3, Gam_image);
    }

    // 显示原始图像和伽马校正后的图像
    imshow("原图像", srcMat);
    imshow("Gam_image", Gam_image);

    waitKey(0); // 等待用户按键
    destroyAllWindows(); // 销毁所有窗口
    return 0; // 正常退出
}

//实现伽马校正,用于调整图像的亮度和对比度。
int gammaCorrection(Mat srcMat, Mat& dstMat, float gamma) {
    // 本函数只处理单通道图像
    if (srcMat.channels() != 1) return -1; // 如果不是单通道图像,则返回错误码

    // 建立查询表
    unsigned char lut[256]; // 定义查找表数组
    for (int i = 0; i < 256; i++) {
        // 计算查找表的每个值
        lut[i] = saturate_cast<uchar>(pow((float)(i / 255.0f), gamma) * 255.0f); 
        // 使用伽马函数计算
    }

    // 复制源图像到目标图像
    srcMat.copyTo(dstMat);

    // 使用MatIterator遍历目标图像的每个像素并应用查找表
    MatIterator_<uchar> it, end; // 定义uchar类型的Mat迭代器
    for (it = dstMat.begin<uchar>(), end = dstMat.end<uchar>(); it != end; it++) {
        *it = lut[(*it)]; // 应用查找表进行伽马校正
    }

    return 0; // 函数成功执行返回0
}

 

三、运行结果:

3050096b87514b128abcdea538c440c6.png

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值