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); } }