OpenCV學習筆記【六】影象的混合操作,對比度和亮度調整
阿新 • • 發佈:2018-12-16
線性混合是一種典型的二元(兩個輸入)的畫素操作,它的理論公式如下:
我們通過在範圍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);
}
}
