OpenCV 分离颜色通道 图像混合 亮度对比度调整

版权声明:转载请注明出处 https://blog.csdn.net/qq_27350133/article/details/81349040

OpenCV 分离颜色通道 图像混合 亮度对比度调整

概述

  1. 读取两张图片,将一张图片插入另一张图片进行混合
  2. 将图片1的颜色通道分离
  3. 分别将图片2插入图片1的蓝色和红色通道进行混合
  4. 合并颜色通道
  5. 调整合并后图像的亮度和对比度
    懒,图片素材直接取自浅墨的图片。

代码段

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace std;
using namespace cv;
/*窗口相关变量*/
#define WinName "showImage"
int lightness = 80;
int contrast = 80;
void on_trackbar(int, void*);
bool createWin();
/*通道混合相关变量*/
vector<Mat> g_MatCh;
Mat g_imageBlueCh;
Mat g_imageGreenCh;
Mat g_imageRedCh;

Mat g_srcImage, g_dstImage,g_mask;
Mat imageROI;
bool main()
{
    g_srcImage = imread("dota_pa.jpg");
    /*第二个参数很重要 这里将图片以灰度图方式传入 这样在后面加权平均时才不会发生内存溢出*/
    g_mask = imread("dota_logo.jpg",0);
    if (!g_srcImage.data) { cout << "srcImage load failure" << endl; return false; }//判断图像是否成功载入
    if (!g_mask.data) { cout << "mask load failure" << endl; return false; }

    split(g_srcImage, g_MatCh); //分离各通道
    g_imageBlueCh  = g_MatCh.at(0);
    g_imageGreenCh = g_MatCh.at(1);
    g_imageRedCh   = g_MatCh.at(2);

    createWin();//创建窗口
    //回调函数初始化
    on_trackbar(lightness, 0); 
    on_trackbar(contrast, 0); 
    waitKey(0);
}
/*创建窗口和trackbar*/
bool createWin()
{
    namedWindow(WinName);
    createTrackbar("lightness", WinName, &lightness, 200, on_trackbar);
    createTrackbar("contrast", WinName, &contrast, 300, on_trackbar);
    return true;
}
/*TrackBar 回调函数*/
void on_trackbar(int, void*)
{
    imageROI = g_imageBlueCh(Rect(200, 250, g_mask.cols, g_mask.rows)); //在蓝色通道划定感兴趣区域
    addWeighted(imageROI, 0.5, g_mask, 0.5, 0.0,
        imageROI);
    imshow("蓝色通道叠加后", g_imageBlueCh);

    imageROI = g_imageRedCh(Rect(200, 250, g_mask.cols, g_mask.rows)); //在红色通道划定感兴趣区域
    addWeighted(imageROI, 0.5, g_mask, 0.5, 0.0,
        imageROI);
    imshow("红色通道叠加后", g_imageRedCh);

    merge(g_MatCh, g_dstImage); //合并各通道
    /*亮度对比度调整*/
    for(int y=0;y<g_dstImage.rows;y++)
        for(int x=0;x<g_dstImage.cols;x++)
            for (int c = 0; c < 3; c++)
            {
                g_dstImage.at<Vec3b>(y, x)[c] = 
                    saturate_cast<uchar>(((contrast*0.01)*g_dstImage.at<Vec3b>(y, x)[c]) + lightness);
            }
    imshow(WinName, g_dstImage);
}

程序运行效果

蓝色通道叠加logo后的效果
图1 蓝色通道叠加后的效果

红色通道叠加后的效果
图2 红色通道叠加后的效果
最终效果
图3 合并通道后的效果

效果分析

在一张图中一个像素的色彩组成可以从通道分离后看出。例如 *图1 蓝色通道* 在原图中蓝色约深的地方,在图1 中表现的更明亮,反之,则更暗。分别将logo混合进蓝色通道和红色通道后 ,再将各通道合并,将得到紫色的logo。 在亮度和对比度调整时,要对每一个像素的每一个通道进行调整。一般遍历图象是2重循环,这里出现了三重循环,最里面一层则是分别访问每个像素的B、G、R通道。 这种点操作(亮度调整和对比度调整)的理论公式为:
                               g(i,j)=a*f(i,j)+b
其中a称为增益(gain),常用来控制对比度。b称为偏置(bias),常用来控制亮度。f(i,j)为图像中每个像素。g(i,j)为计算后的像素值。

注意事项

在这个程序中容易出现的几种问题:
  1. 单通道图像不能和多通道图像混合,否则将内存溢出。g_mask = imread("dota_logo.jpg",0); 第二个参数意义为将图片以灰度图读入,在后面的与单通道图像混合时才不至于引发错误。
  2. addWeighted(imageROI, 0.5, g_mask, 0.5, 0.0,imageROI); 最后一个参数为ROI,为原图像的引用,因此将加权叠加后的图像输出到ROI即改变了原图像对应的区域。
  3. 在调整图像时为了避免像素值溢出需要加上saturate_cast<uchar>

心得

图像较大时,遍历处理每一个像素将会对程序性能造成很大影响,因此在编写图像处理程序时还得考虑如何提高效率。加油。

猜你喜欢

转载自blog.csdn.net/qq_27350133/article/details/81349040