OpencCV之基础学习:图像的基本操作(二)---图像混合&调整图像亮度和对比度

根据自己在网课上的学习,记录一些笔记,加深记忆,在这里分享出来,大家一起学习,自己编程能力有限,对于一些专业名词的运用可能不太得当,不过希望能够让自己不断进步。如有不足不严谨之处希望大家指出来。

这次继续学一点简单的操作吧。

1.图像的混合

图像的混合即把两张大小一样类型一致的图像合成一张图片。

(1)理论知识

    线性混合操作的理论:

    g(x)=(1-⍺)f₀(x)+⍺f₁(x) 

     其中⍺代表了每个图像占的权重,⍺的取值范围为0~1之间。通过对⍺值的调整可以使得两张图片得到更好的融合。

(2)相关api

    使用addWeighted(cv::InputArray src1,    输入图像1

                              double alpha,            输入图像1的alpha值

                              cv::InputArray src2,    输入图像2                     

                              double beta,             输入图像2的alpha值

                              double gamma,         这个是校验值,默认为0

                              cv::OutputArray dst,   输出混合图像
                              int type=-1                
 )
在编程过程中注意判断一下两张图片大小类型是否一致。核心演示代码如下:
double alpha=0.5;
if(src1.size()==src2.size()&&src1.type()==src2.type()){
        addWeighted(src1,alpha, src2, (1.0-alpha), 0.0, dst);
        imshow("qianxi", src1);
        imshow("spiderman", src2);
        namedWindow("blend image",CV_WINDOW_NORMAL);
        imshow("blend image",dst);
    }
    else{
        cout<<"this two pictures are not same size or type";
    }   

出来的效果图如下,中间那个图是两张图合成后的效果,嘻嘻嘻~大家有其他的创意也可以试着去实现:


把两个图合成一张图,也可以直接采用下面这种不基于权重方式,包括加法和乘法的合成,但是合成的效果非常生硬。一般不采取。代码如下:

add(src1,src2,dst,Mat());
multiply(src1,src2,dst);

2.调整图像亮度和对比度

(1)理论知识

    图像变换有两种变换方式,一种是像素的变换——点操作,另一种是邻域操作下的变化——区域变换,后面这种图像变换可以用来做识别等比较复杂一些的图像计算。今天主要学会用第一种,像素变换(之前上一次我已经写了一些小的读取修改像素方面的知识,可以回顾一下)。

像素变换:

g(i,j)=⍺f(i,j)+β,其中⍺>0,β是增益变量。

对于这个式子的理解可以理解成这样。⍺是用来调整对比度的,β是用来调整亮度的,i、j是图像的像素点。

#include <iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;

//提高图像的亮度和对比度
int main(int argc, const char * argv[]) {
    Mat src,src2,dst;
    src=imread("/Users/Meng/Documents/opencvTest/Pictures/WechatIMG1.jpeg");
    if(!src.data){
        cout<<"can not load image..."<<endl;
        return -1;
    }
    //cvtColor(src, src2, CV_RGB2GRAY);//变成灰度图像
    //src.convertTo(src2, CV_32F);//如果想使用vec3f需要提前转换一下
    dst=Mat::zeros(src.size(),src.type());
    int height=src.rows;
    int width=src.cols;
    float alpha=1.5;
    float beta=10;
    for(int row=0;row<height;row++){
        for(int col=0;col<width;col++){//多通道rgb
            if(src.channels()==3){
                float b=src.at<Vec3b>(row,col)[0];
                float g=src.at<Vec3b>(row,col)[1];
                float r=src.at<Vec3b>(row,col)[2];
                
                dst.at<Vec3b>(row,col)[0]=saturate_cast<uchar>(b*alpha+beta);
                dst.at<Vec3b>(row,col)[1]=saturate_cast<uchar>(g*alpha+beta);
                dst.at<Vec3b>(row,col)[2]=saturate_cast<uchar>(r*alpha+beta);
            }//灰度图像
            else if(src.channels()==1){
                float gray=src.at<uchar>(row,col);
                dst.at<uchar>(row,col)=saturate_cast<uchar>(gray*alpha+beta);
            }
        }
    }
    char input_title[]="spider man";
    char output_title[]="contrast and brightness image";
    namedWindow(input_title,CV_WINDOW_NORMAL);
    imshow(input_title, src);
    
    namedWindow(output_title,CV_WINDOW_NORMAL);
    imshow(output_title, dst);
    waitKey(0);
}

小插曲:在这里面有一段代码可以用来建一张新的空白图像,经常会用的到,可以掌握好这种方法。其实Mat对象有很多有意思的使用,大家可以自己查查,我也边学边用。代码如下:

 dst=Mat::zeros(src.size(),src.type());

还有一处需要大家留意,谨记下段代码:

saturate_cast<uchar>(value);
这个很有用的,可以保证色彩值在0~255之间,如果不加这个图片可能会很奇怪很不自然的。

这段代码中包含灰度图像的测试,可以自己感兴趣去做一下~上面这段代码效果是这样的:


看了蜘蛛侠小哥哥,学习opencv很开心。继续努力哈哈哈~

猜你喜欢

转载自blog.csdn.net/z714977076/article/details/80469916