1. 程式人生 > >OpenCV學習筆記【六】影象的混合操作,對比度和亮度調整

OpenCV學習筆記【六】影象的混合操作,對比度和亮度調整

線性混合是一種典型的二元(兩個輸入)的畫素操作,它的理論公式如下:

                                                             g(x)=(1-a)f_{a}(x)+af_{3}(x)

我們通過在範圍0到1之間改變alpha值,來對兩幅影象或兩段視訊產生時間上的畫面疊化。下面給出程式碼示例:

//ROI區域影象疊加&影象混合
#include<opencv2/opencv.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include<iostream>
using namespace cv;
using namespace std;
bool ROI_ADDImage()
{//讀入影象
	Mat srcImage1 = imread("group.jpg");
	Mat logoImage = imread("2.jpg");
	if (!srcImage1.data) { printf("讀取srcImage錯誤~! \n"); return false; }
	if (!logoImage.data) { printf("讀取logoImage錯誤~! \n"); return false; }
	//定義一個Mat型別並給其設定ROI區域
	Mat imageROI = srcImage1(Rect(300, 250, logoImage.cols, logoImage.rows));
	//載入掩模(必須是灰度圖)
	Mat mask = imread("2.jpg",0);
	logoImage.copyTo(imageROI, mask);//將掩模複製到ROI
	//顯示結果
	namedWindow("<1>利用ROI實現影象疊加示例視窗");
	imshow("<1>利用ROI實現影象疊加示例視窗", srcImage1);
	return true;
}
bool LinearBlending()
{//定義一些區域性變數
	double alphaValue = 0.5;
	double betaValue;
	Mat srcImage2, srcImage3, dstImage;
	//讀取影象(兩幅圖需為同樣的型別和尺寸)
	srcImage2 = imread("mogu.jpg");
	srcImage3 = imread("rain.jpg");
	if (!srcImage2.data) { printf("讀取srcImage2錯誤~! \n"); return false; }
	if (!srcImage3.data) { printf("讀取srcImage3錯誤~! \n"); return false; }
	//做影象混合加權操作
	betaValue = (1.0 - alphaValue);
	addWeighted(srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);
	//建立並顯示原圖視窗
	namedWindow("<2>線形混合視窗【原圖】",1);
	imshow("<2>線形混合視窗【原圖】", srcImage2);
	namedWindow("<3>線形混合視窗【原圖】", 1);
	imshow("<3>線形混合視窗【原圖】", dstImage);
	return true;
}
bool ROI_LinearBlending()
{//讀取影象
	Mat srcImage4 = imread("dota_pa.jpg", 1);
	Mat logoImage = imread("dota_logo.jpg");
	if (!srcImage4.data) { printf("讀取srcImage4錯誤~! \n"); return false; }
	if (!logoImage.data) { printf("讀取logoImage錯誤~! \n"); return false; }
	//定義一個Mat型別並給其設定ROI區域
	Mat imageROI;
	imageROI = srcImage4(Rect(200, 250, logoImage.cols, logoImage.rows));
	//將logo加到原圖上
	addWeighted(imageROI, 0.5, logoImage, 0.3, 0., imageROI);
	//顯示結果
	namedWindow("<4>區域線性影象混合示例視窗");
	imshow("<4>區域線性影象混合示例視窗",srcImage4);
	return true;
}
int main()
{
	if (ROI_ADDImage()&&LinearBlending()&&ROI_LinearBlending())
		cout << endl << "執行成功";
	waitKey(0);
	return 0;
}

效果圖如下:

 

多通道混合

//多通道影象混合
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace cv;
using namespace std;
//全域性函式宣告
bool MultiChannelBlending();
//void ShowHelpText();
//main函式
int main()
{
	system("color 9F");
	if (MultiChannelBlending())
	{
		cout << endl << "\n執行成功,得出了需要的影象";
	}
	waitKey(0);
	return 0;
}
bool MultiChannelBlending()
{//定義相關變數
	Mat srcImage;
	Mat logoImage;
	vector<Mat>channels;
	Mat imageBlueChannel;
	//藍色通道部分,多通道混合—藍色分量部分
	//1.讀入圖片
	logoImage = imread("dota_logo.jpg", 0);
	srcImage = imread("dota_jugg.jpg");
	if (!logoImage.data) { printf("讀取logoImage錯誤~! \n"); return false; }
	if (!srcImage.data) { printf("讀取srcImage錯誤~! \n"); return false; }
	//2.把一個3通道影象轉換成3個單通道影象
	split(srcImage, channels);//分離彩色通道
	//3.將原圖的藍色通道引用返回給imageBlueChannel,
	//注意是引用,相當於兩者是等價,修改其中一個另一個跟著變
	imageBlueChannel = channels.at(0);
	//4.將原圖的藍色通道的(500,250)座標處右下方的一塊區域和logo圖進行加權操作,
	//將得到的混合結果存到imageBlueChannel中
	addWeighted(imageBlueChannel(Rect(500, 250, logoImage.cols, logoImage.rows)), 1.0,
		logoImage, 0.5,0,imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows)));
	//5.將三個通道重新合併為一個三通道
	merge(channels, srcImage);
	namedWindow("<1>遊戲原畫+logo藍色通道");
	imshow("<1>遊戲原畫+logo藍色通道",srcImage);
//-------------------------------------綠色通道部分------------------------------------
	Mat imageGreenChannel;
	//藍色通道部分,多通道混合—藍色分量部分
	//1.讀入圖片
	logoImage = imread("dota_logo.jpg", 0);
	srcImage = imread("dota_jugg.jpg");
	if (!logoImage.data) { printf("讀取logoImage錯誤~! \n"); return false; }
	if (!srcImage.data) { printf("讀取srcImage錯誤~! \n"); return false; }
	//2.把一個3通道影象轉換成3個單通道影象
	split(srcImage, channels);//分離彩色通道
	//3.將原圖的藍色通道引用返回給imageBlueChannel,
	//注意是引用,相當於兩者是等價,修改其中一個另一個跟著變
	imageGreenChannel = channels.at(1);
	//4.將原圖的藍色通道的(500,250)座標處右下方的一塊區域和logo圖進行加權操作,
	//將得到的混合結果存到imageBlueChannel中
	addWeighted(imageGreenChannel(Rect(500, 250, logoImage.cols, logoImage.rows)), 1.0,
		logoImage, 0.5,0,imageGreenChannel(Rect(500,250,logoImage.cols,logoImage.rows)));
	//5.將三個通道重新合併為一個三通道
	merge(channels, srcImage);
	namedWindow("<1>遊戲原畫+logo藍色通道");
	imshow("<1>遊戲原畫+logo藍色通道",srcImage);
//--------------------------------------紅色通道部分------------------------------------
		Mat imageRedChannel;
	//藍色通道部分,多通道混合—藍色分量部分
	//1.讀入圖片
	logoImage = imread("dota_logo.jpg", 0);
	srcImage = imread("dota_jugg.jpg");
	if (!logoImage.data) { printf("讀取logoImage錯誤~! \n"); return false; }
	if (!srcImage.data) { printf("讀取srcImage錯誤~! \n"); return false; }
	//2.把一個3通道影象轉換成3個單通道影象
	split(srcImage, channels);//分離彩色通道
	//3.將原圖的藍色通道引用返回給imageBlueChannel,
	//注意是引用,相當於兩者是等價,修改其中一個另一個跟著變
	imageRedChannel = channels.at(2);
	//4.將原圖的藍色通道的(500,250)座標處右下方的一塊區域和logo圖進行加權操作,
	//將得到的混合結果存到imageBlueChannel中
	addWeighted(imageRedChannel(Rect(500, 250, logoImage.cols, logoImage.rows)), 1.0,
		logoImage, 0.5,0,imageRedChannel(Rect(500,250,logoImage.cols,logoImage.rows)));
	//5.將三個通道重新合併為一個三通道
	merge(channels, srcImage);
	namedWindow("<1>遊戲原畫+logo藍色通道");
	imshow("<1>遊戲原畫+logo藍色通道",srcImage);
	return true;
}

                                           

 

影象對比度和亮度的調整

//影象對比度、亮度調整
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace cv;
using namespace std;
//全域性函式宣告
static void on_ContrastAndBright(int, void*);
//static void ShowHelpText();
//全域性變數宣告
int g_nContrastValue;//對比度值
int g_nBrightValue;//亮度值
Mat g_srcImage, g_dstImage;
int main()
{//讀入影象
	g_srcImage = imread("1.jpg");
	if (!g_srcImage.data) { printf("讀取圖片錯誤,請確定目錄下是否有imread函式指定圖片存在~!"); return false; }
	g_dstImage = Mat::zeros(g_srcImage.size(), g_srcImage.type());
	//設定對比度和亮度的初值
	g_nContrastValue = 80;
	g_nBrightValue = 80;
	//建立效果視窗
	namedWindow("【效果圖視窗】", 1);
	//建立軌跡條
	createTrackbar("對比度:", "【效果圖視窗】", &g_nContrastValue, 300, on_ContrastAndBright);
	createTrackbar("亮 度:", "【效果圖視窗】", &g_nBrightValue, 200, on_ContrastAndBright);
	//進行回撥函式初始化
	on_ContrastAndBright(g_nContrastValue, 0);
	on_ContrastAndBright(g_nBrightValue, 0);
	//按下“q”鍵時,程式退出 
	while (char(waitKey(1)) != 'q') {}
	return 0;
}
//改變影象對比度和亮度值的回撥函式
static void on_ContrastAndBright(int, void*)
{//建立視窗
	namedWindow("【原始圖視窗】",1);
//三個for迴圈,執行g_dstImage(i,j)=a*g_srcImage(i,j)+b
	for (int y = 0; y < g_srcImage.rows; y++)
	{
		for (int x = 0; x < g_srcImage.cols; x++)
		{
			for (int c = 0; c < 3; c++)
			{
				g_dstImage.at<Vec3b>(y, x)[c] =
					saturate_cast<uchar>( (g_nContrastValue*0.01)*(g_srcImage.at<Vec3b>
					(y,x)[c]) + g_nBrightValue);
			}
		}
		//顯示影象
		imshow("【原始圖視窗】", g_srcImage);
		imshow("【效果圖視窗】", g_dstImage);
	}
}