C++ Opencv split()通道分離函數 merge()通道合並函數 使用操作詳解


一、 split()通道分離函數

split()函數的C++版本有兩個原型,他們分別是:


C++: void split(const Mat& src, Mat*mvbegin);//&為引用操作符
C++: void split(InputArray m,OutputArrayOfArrays mv);

兩種定義用法相同,第一個參數填待分離的Mat型多通道矩陣(二維),第二個參數填分離后的Mat型單通道數組(三維)或一個vector<Mat>對象。應用實例如下:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	Mat image = imread("colorful.jpg");
	if (image.data == 0)
	{
		cout << "讀取錯誤" << endl;
	}
	imshow("原圖", image);

	//使用Mat容器,用【】訪問
	//vector<Mat> channels;
	//split(image, channels);
	//imshow("B", channels[0]);
	//imshow("G", channels[1]);
	//imshow("R", channels[2]);

	//使用Mat容器,用at訪問
	vector<Mat> channels;
	split(image, channels);
	imshow("B", channels.at(0));
	imshow("G", channels.at(1));
	imshow("R", channels.at(2));

	//使用Mat數組,只能用【】訪問
	//Mat aChannel[3];
	//split(image, aChannel);
	//imshow("B", aChannel[0]);
	//imshow("G", aChannel[1]);
	//imshow("R", aChannel[2]);

	waitKey();
	return 0;
}

如果將分離后的信息填入vector<Mat> channels中,最后channels對象內會有3個元素,每個元素都是大小為image.rows X image.cols的二維Mat型矩陣,依次存放着原圖像對應像素位置的B、G、R分量數據。每個元素(二維矩陣)可以通過【】索引或.at()訪問。

如果將分離后的信息填入Mat aChannel[3]中,最后aChannel數組內會的3個元素也都是大小為image.rows X image.cols的二維Mat型矩陣,依次存放着原圖像對應像素位置的B、G、R分量數據。每個元素(二維矩陣)只能通過【】索引,不能通過.at()訪問。

同時需要注意,vector<Mat> channels和Mat aChannel[3]中的元素均為二維矩陣,因此channels對象和aChannel數組都是三維的矩陣。而輸出操作符“<<”僅能輸出二維矩陣,所以可以用"cout<<"輸出channels對象或aChannel數組中的單個元素,而channels對象和aChannel數組本身不能被輸出。

因為分離出來的3個元素都是大小為image.rows X image.cols的二維Mat型矩陣,所以用imshow()顯示每個元素時,最后顯示出來的都是單通道的灰度圖。

上述程序運行結果如下:

 

二、merge()通道合並函數

merge()函數的C++版本有兩個原型,他們分別是:

C++: void merge(const Mat* mv, size_tcount, OutputArray dst)
C++: void merge(InputArrayOfArrays mv,OutputArray dst)

若待合並通道放在Mat aChannel[ ]這樣的數組里面,則使用第一種定義方法下的merge()函數。第一個參數填要傳入數組的地址,可直接填入數組名aChannel;第二個參數填要合並矩陣的個數,通常情況下圖像大都是單通道的灰度圖或三通道的真彩圖,因此要想合並后的輸出dst能直接用imshow()顯示的話,最好填1或3,填2也能進行數據的合並,但輸出時會報錯;最后一個參數填通道合並后的矩陣。

以下示例中,先用split()將圖像三通道分離,將R紅色分量全部置0后再將三通道用merge()融合。通道分離后,單通道矩陣存放於數組中,代碼如下:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	Mat image = imread("colorful.jpg");
	if (image.data == 0)
	{
		cout << "讀取錯誤" << endl;
	}
	imshow("原圖", image);

	//通道分離
	Mat aChannel[3];
	split(image, aChannel);
	Mat BlueChannel = aChannel[0];
	Mat GreenChannel = aChannel[1];
	Mat RedChannel = aChannel[2];

	//將R通道全部置0
	Mat newAddChannel = aChannel[2].clone();
	newAddChannel.setTo(0);
	Mat newChannels[3] = { BlueChannel , GreenChannel , newAddChannel };

	//通道合並
	Mat mergedImage;
	merge(newChannels, 3, mergedImage);

	imshow("Merged", mergedImage);
	waitKey();
	return 0;
}

若待合並通道放在vector<Mat> channels這樣的Mat型容器對象中,則使用第二種定義方法下的merge()函數。第一個參數填對象名channels,第二個參數填通道合並后的矩陣。相較第一種定義方法來說,本定義方法無需說明需合並矩陣的個數,默認合並容器對象內所有元素。因此可以通過更改容器對象內元素的個數來改變合並矩陣的個數。

以下示例中,先用split()將圖像三通道分離,將B綠色分量全部置0后再將三通道用merge()融合。通道分離后,單通道矩陣存放於容器對象中,代碼如下:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	Mat image = imread("colorful.jpg");
	if (image.data == 0)
	{
		cout << "讀取錯誤" << endl;
	}
	imshow("原圖", image);

	//通道分離
	vector<Mat> channels;
	split(image, channels);
	Mat BlueChannel = channels.at(0);
	Mat GreenChannel = channels.at(1);
	Mat RedChannel = channels.at(2);

	//將B通道全部置0
	Mat newAddChannel = channels.at(0).clone();
	newAddChannel.setTo(0);
	vector<Mat> newChannels;
	newChannels.push_back(newAddChannel);
	newChannels.push_back(GreenChannel);
	newChannels.push_back(RedChannel);

	//通道合並
	Mat mergedImage;
	merge(newChannels, mergedImage);

	imshow("Merged", mergedImage);
	waitKey();
	return 0;
}

注:無論將單通道矩陣放在數組中還是容器對象中,都要按照B、G、R的順序存放。

錯誤之處,敬請雅正!

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM