1. 程式人生 > >OpenCV split函式 merge函式 及示例

OpenCV split函式 merge函式 及示例

//-----------------------------------【標頭檔案包含部分】---------------------------------------
//     描述:包含程式所依賴的標頭檔案
//----------------------------------------------------------------------------------------------                                                                                    
#include <cv.h>
#include <highgui.h>
#include <iostream>
//-----------------------------------【名稱空間宣告部分】---------------------------------------
//     描述:包含程式所使用的名稱空間
//-----------------------------------------------------------------------------------------------  
using namespace cv;
using namespace std;

int main()
{
	vector<Mat> channels;
	Mat imageBlueChannel;
	Mat imageGreenChannel;
	Mat imageRedChannel;
	Mat	srcImage4 = imread("dota.png");
	// 把一個3通道影象轉換成3個單通道影象
	split(srcImage4, channels);//分離色彩通道
	imageBlueChannel = channels.at(0);
	imageGreenChannel = channels.at(1);
	imageRedChannel = channels.at(2);
	
	//三個分量R、G、B因為是單通道影象,所以只能顯示為灰度圖。
	//如果要想顯示出顏色來,應該用三通道影象來顯示,比如顯示R,我們就讓G和B通道的數值為0或255。
	//顯示彩色的B分量
	vector<Mat> mbgr(3);
	Mat bk1(srcImage4.size(), CV_8UC1, Scalar(0));
	//表示了矩陣中元素的型別以及矩陣的通道個數,它是一系列的預定義的常量,其命名規則為CV_ + (位數)+(資料型別)+(通道數)。
	Mat imageB(srcImage4.size(), CV_8UC3);
	mbgr[0] = channels[0];
	mbgr[1] = bk1;
	mbgr[2] = bk1;
	merge(mbgr, imageB);
	imshow("imageB", imageB);

	waitKey();
	return 0;
}

上面的程式碼先做了相關的型別宣告,然後把載入的3通道影象轉換成3個單通道影象,放到vector<Mat>型別的channels中,接著進行引用賦值。

根據OpenCV的BGR色彩空間(bule,Green,Red,藍綠紅),其中channels.at(0)就表示引用取出channels中的藍色分量,channels.at(1)就表示引用取出channels中的綠色色分量,channels.at(2)就表示引用取出channels中的紅色分量。

一對做相反操作的plit()函式和merge()函式和用法就是這些了。另外提一點,如果我們需要從多通道陣列中提取出特定的單通道陣列,或者說實現一些複雜的通道組合,可以使用mixChannels()函式。

多通道影象混合示例程式:

//-----------------------------------【程式說明】----------------------------------------------
//  程式名稱::【OpenCV入門教程之四】分離顏色通道&多通道影象混合 
//------------------------------------------------------------------------------------------------

//-----------------------------------【標頭檔案包含部分】---------------------------------------
//     描述:包含程式所依賴的標頭檔案
//----------------------------------------------------------------------------------------------                                                                                    
#include <cv.h>
#include <highgui.h>
#include <iostream>

//-----------------------------------【名稱空間宣告部分】---------------------------------------
//     描述:包含程式所使用的名稱空間
//-----------------------------------------------------------------------------------------------  
using namespace cv;
using namespace std;


//-----------------------------------【全域性函式宣告部分】--------------------------------------
//     描述:全域性函式宣告
//-----------------------------------------------------------------------------------------------
bool MultiChannelBlending();

//-----------------------------------【main( )函式】--------------------------------------------
//     描述:控制檯應用程式的入口函式,我們的程式從這裡開始
//-----------------------------------------------------------------------------------------------
int main()
{
	//system("color5E");

	if (MultiChannelBlending())
	{
		cout << "嗯。好了,得出了你需要的混合值影象~" << endl;
	}

	waitKey();//int cvWaitKey( int delay=0 )
	return 0;
}


//-----------------------------【MultiChannelBlending( )函式】--------------------------------
//     描述:多通道混合的實現函式
//-----------------------------------------------------------------------------------------------
bool MultiChannelBlending()
{
	//【0】定義相關變數
	Mat srcImage;
	Mat logoImage;
	vector<Mat>channels;
	Mat  imageBlueChannel;

	//=================【藍色通道部分】=================
	//     描述:多通道混合-藍色分量部分
	//============================================

	//【1】讀入圖片
	logoImage = imread("dota_logo.png", 0);
	srcImage = imread("dota.png");

	if (!logoImage.data) { printf("Oh,no,讀取logoImage錯誤~!\n"); return false; }
	if (!srcImage.data) { printf("Oh,no,讀取srcImage錯誤~!\n"); return false; }
	//data  uchar型的指標。Mat類分為了兩個部分:矩陣頭和指向矩陣資料部分的指標,data就是指向矩陣資料的指標
	//指向矩陣資料的指標不為0,則說明成功讀取影象了,否則讀取錯誤

	//【2】把一個3通道影象轉換成3個單通道影象
	split(srcImage, channels);//分離色彩通道
	//第一個引數,InputArray型別的m或者const Mat&型別的src,填我們需要進行分離的多通道陣列。
	//第二個引數,OutputArrayOfArrays型別的mv,填函式的輸出陣列或者輸出的vector容器。
	//矩陣與陣列沒有本質區別,前者一般用於數學描述,後者一般用於程式設計描述。
	//影象資料以矩陣的形式存在

	//【3】將原圖的藍色通道引用返回給imageBlueChannel,注意是引用,相當於兩者等價,修改其中一個另一個跟著變
	//下標操作返回的是元素的引用,at()和[]等同,都是下標操作
	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)));
	//dst = src1[I]*alpha+ src2[I]*beta + gamma;
	//void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1); 

	//【5】將三個單通道重新合併成一個三通道
	merge(channels, srcImage);

	//【6】顯示效果圖
	namedWindow("<1>遊戲原畫+logo藍色通道");
	imshow("<1>遊戲原畫+logo藍色通道 ", srcImage);


	//=================【綠色通道部分】=================
	//     描述:多通道混合-綠色分量部分
	//============================================

	//【0】定義相關變數
	Mat  imageGreenChannel;

	//【1】重新讀入圖片
	logoImage = imread("dota_logo.png", 0);
	srcImage = imread("dota.png");

	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,注意是引用,相當於兩者等價,修改其中一個另一個跟著變
	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.png", 0);
	srcImage = imread("dota.png");

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