四、线性混合、调整图像的亮度与对比度

一、线性混合操作

void cv::addWeighted    (   InputArray  src1,
                            double  alpha,
                            InputArray  src2,
                            double  beta,
                            double  gamma,
                            OutputArray     dst,
                            int     dtype = -1 
)   
  • 计算两个数组的加权和
  • 这两个数组的加权和的关系可有下式表示
    dst(I)=saturate(src1(I)alpha+src2(I)beta+gamma)
    用数学的方式表示
    dst(I)=saturate(src1(I)α+src2(I)β+γ)

    其中 I 是一个多维数组索引。在计算多维数组索引的情况下,每一个通道值都是单独计算的。这个函数可以用矩阵表达式代替
    dst = src1*alpha+src2*beta+gamma
    α,β是两图在新图中所占的比例,一般的 α+β=1 ,当然也可以不等于 1
    γ为一个增益变量,作用是可以提高或减小整体的亮度。
  • 最后一个参数dtype的作用是指定输出数组的类型;当两个输入数组是相同的depth时,dtype被设置成-1,也就是输出数组的类型与src1.depth()相等。

  • 相似的函数:
    add, subtract, scaleAdd, Mat::convertTo

  • nots:

    1. 输出数组的深度不能是CV_32S,如果是的话,你可能得到不正确的结果。
    2. 两个输入数组的类型必须相同。但是类型相同,主要就是说通道数相同;经过如下情况亦可
      第一种情况
cvtColor(src2, src2, COLOR_BGR2GRAY);   
cvtColor(src2, src2, COLOR_GRAY2BGR);
//得到的src2能够使用

第二种情况

src4.convertTo(src2, CV_16UC3);
//src4亦可使用

用处:视频字幕上可以看成是这样操作的

使用方法

//【1】API方式:
//addWeighted(src1, 2, src2, 2, -60, dst);

//【2】表达式方式
//dst = src1*2 + src1*2 - 60;

//【3】遍历图像的方式
    Mat_<Vec3b> src1_data = src1;
    Mat_<Vec3b> src2_data = src2;
    Mat_<Vec3b> dst_data = dst;

    for (int i = 0; i < src1.rows; i++)
    {
        for (int j = 0; j < src1.cols; j++)
        {
            dst_data(i, j)[0] = saturate_cast<uchar>(src1_data(i, j)[0] * 2 -src2_data(i, j)[0] * 2- 60);
            dst_data(i, j)[1] = saturate_cast<uchar>(src1_data(i, j)[1] * 2 -src2_data(i, j)[0] * 2- 60);
            dst_data(i, j)[2] = saturate_cast<uchar>(sr1c_data(i, j)[2] * 2 -src2_data(i, j)[0] * 2- 60);
        }
    }

程序文件

二、调整图像的亮度与对比度

图像变换可以分为两类操作:

  • 像素变换-点操作
  • 邻域操作-区域
    线性混合、调整图像的亮度与对比度属于像素变换。卷积操作,图形操作属于邻域操作;

调整图像的亮度与对比度原理:

dst(I)=saturate(src1(I)alpha+gamma)

用数学的方式表示
dst(I)=saturate(src1(I)α+γ)

γ 是增益变量同同上边的。 β=0
这个暂时不知道它有没有独有的API,但是可以通过上面线性混合的API得到两种,只需要把两个输入图像中的一个图像的比例设置为0,或者传入一个所有像素值为0的空图像,即可。
当然可以用矩阵的运算 dst = src1*alpha+src2*0+gamma
使用方法

    //【1】API方式:
    addWeighted(src1, 2, src2, 0, -60, dst);

    //【2】表达式方式
    dst = src1*2 + 60;

    //【3】遍历图像的方式
    Mat_<Vec3b> src_data = src1;
    Mat_<Vec3b> dst_data = dst;

    //Mat_<Vec3b> dst1_data = dst1;
    for (int i = 0; i < src1.rows; i++)
    {
        for (int j = 0; j < src1.cols; j++)
        {
            dst_data(i, j)[0] = saturate_cast<uchar>(src_data(i, j)[0] * 2 - 60);
            dst_data(i, j)[1] = saturate_cast<uchar>(src_data(i, j)[1] * 2 - 60);
            dst_data(i, j)[2] = saturate_cast<uchar>(src_data(i, j)[2] * 2 - 60);

            //这种方式是错误的,寻找错误方法见程序文件
            /* 比如说点(50,300)的值为26,经过下式计算应该得-8,经过saturate计算的为0,没有经过saturate转换的确成了228*/
            /*dst1_data(i, j)[0] = (uchar)(src_data(i, j)[0] * 1.2 - 60);
            dst1_data(i, j)[1] = (uchar)(src_data(i, j)[1] * 1.2 - 60);
            dst1_data(i, j)[2] = (uchar)(src_data(i, j)[2] * 1.2 - 60);*/
        }
    }

程序文件


注意:

这种对点的操作都需要把计算结果的值经过saturate_cast转换,不然容易溢出,得到不是想得到的值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值