基於openCV3的顏色通道分離及多通道影象混合
注:文件摘至《OpenCV3程式設計入門》毛星雲版
<1>通道分離: split()函式
split函式用於將一個多通道陣列分離成幾個單通道陣列。這裡的array 按語境翻譯為陣列或者陣列。split函式的C++版本有兩個原型, 分別是:
• c ++: void split( const Mat& src, Mat*mvbegin);
• C++ : void split(InputArray m ,Outpu從nayOfArrays mv);
變數介紹如下:
· 第一個引數, InputArray 型別的m 或者const Mat&型別的src ,填我們需要進行分離的多通道陣列。
· 第二個引數, OutputArrayOfArrays 型別的mv , 填函式的輸出陣列或者輸出
的vector 容器。
split 函式分割多通道陣列轉換成獨立的單通道陣列,公式如下:
mv[c] (I)= src(I )c
<2>通道合併: merge()函式
merge() 函式是split() 函式的逆向操作將多個數組合併成一個多通道的陣列。它通過組合一些給定的單通道陣列,將這些孤立的單通道數組合併成一個多通道的陣列,從而創建出一個由多個單通道陣列組成的多通道陣列。它有兩個基於C十+的函式原型如下。
• C++: void merge(const Mat* mv, size_tcount, Ou陽山rray dst)
• C++: void merge( In putArrayO隊rrays mv,OutputArray dst)
變數介紹如下。
· 第一個引數, mv 。填需要被合井的輸入矩陣或vector 容器的陣列,這個mv 引數中所有的矩陣必須有著一樣的尺寸和深度。
· 第二個引數, count。 當mv 為一個空白的C 陣列時,代表輸入矩陣的個數,這個引數顯然必須大於1。
· 第三個引數, dst。即輸出矩陣,和mv[0]擁有一樣的尺寸和深度,井且通道的數量是矩陣陣列中的通道的總數。
函式解析如下。
merge 函式的功能是將一些數組合併成一個多通道的陣列。關於組合的細節,輸出矩陣中的每個元素都將是輸出陣列的串接。其中, 第i 個輸入陣列的元素被視為mv[i] 。 C 一般用其中的Mat: :at()方法對某個通道進行存取,也就是這樣用:channels.at(0) 。
這裡的Mat: :at()方法返回一個引用到指定的陣列元素。注意是引用,相當於兩者等價,也就是修改其中一個,另一個也會隨之改變。
<例項>
標頭檔案包含及名稱空間
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
實現多通道的影象混合
bool MultiChannelBlending()
{
//【0】定義相關變數
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("Oh,no,讀取logoImage錯誤~! \n"); return false; }
if( !srcImage.data ) { printf("Oh,no,讀取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);
//【6】顯示效果圖
namedWindow(" <1>遊戲原畫+logo藍色通道");
imshow(" <1>遊戲原畫+logo藍色通道",srcImage);
//=================【綠色通道部分】=================
// 描述:多通道混合-綠色分量部分
//============================================
//【0】定義相關變數
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】將一個三通道影象轉換成三個單通道影象
split(srcImage,channels);//分離色彩通道
//【3】將原圖的綠色通道的引用返回給imageBlueChannel,注意是引用,相當於兩者等價,修改其中一個另一個跟著變
imageGreenChannel= channels.at(1);
//【4】將原圖的綠色通道的(500,250)座標處右下方的一塊區域和logo圖進行加權操作,將得到的混合結果存到imageGreenChannel中
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);
//【6】顯示效果圖
namedWindow("<2>遊戲原畫+logo綠色通道");
imshow("<2>遊戲原畫+logo綠色通道",srcImage);
//=================【紅色通道部分】=================
// 描述:多通道混合-紅色分量部分
//============================================
//【0】定義相關變數
Mat imageRedChannel;
//【1】重新讀入圖片
logoImage= imread("dota_logo.jpg",0);
srcImage= imread("dota_jugg.jpg");
if( !logoImage.data ) { printf("Oh,no,讀取logoImage錯誤~! \n"); return false; }
if( !srcImage.data ) { printf("Oh,no,讀取srcImage錯誤~! \n"); return false; }
//【2】將一個三通道影象轉換成三個單通道影象
split(srcImage,channels);//分離色彩通道
//【3】將原圖的紅色通道引用返回給imageBlueChannel,注意是引用,相當於兩者等價,修改其中一個另一個跟著變
imageRedChannel= channels.at(2);
//【4】將原圖的紅色通道的(500,250)座標處右下方的一塊區域和logo圖進行加權操作,將得到的混合結果存到imageRedChannel中
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);
//【6】顯示效果圖
namedWindow("<3>遊戲原畫+logo紅色通道 ");
imshow("<3>遊戲原畫+logo紅色通道 ",srcImage);
return true;
}
測試一下
int main( )
{
system("color 9F");
if(MultiChannelBlending( ))
{
cout<<endl<<"\n執行成功,得出了需要的影象~! ";
}
waitKey(0);
return 0;
}
效果圖如下: