OpenCV 分离颜色通道 图像混合 亮度对比度调整
概述
- 读取两张图片,将一张图片插入另一张图片进行混合
- 将图片1的颜色通道分离
- 分别将图片2插入图片1的蓝色和红色通道进行混合
- 合并颜色通道
- 调整合并后图像的亮度和对比度
懒,图片素材直接取自浅墨的图片。
代码段
#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);
}
程序运行效果
图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)为计算后的像素值。
注意事项
在这个程序中容易出现的几种问题:- 单通道图像不能和多通道图像混合,否则将内存溢出。
g_mask = imread("dota_logo.jpg",0);
第二个参数意义为将图片以灰度图读入,在后面的与单通道图像混合时才不至于引发错误。 addWeighted(imageROI, 0.5, g_mask, 0.5, 0.0,imageROI);
最后一个参数为ROI,为原图像的引用,因此将加权叠加后的图像输出到ROI即改变了原图像对应的区域。- 在调整图像时为了避免像素值溢出需要加上
saturate_cast<uchar>
。
心得
图像较大时,遍历处理每一个像素将会对程序性能造成很大影响,因此在编写图像处理程序时还得考虑如何提高效率。加油。