日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【OpenCV入门教程之五】 分离颜色通道多通道图像混合(转)

發(fā)布時間:2024/4/17 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【OpenCV入门教程之五】 分离颜色通道多通道图像混合(转) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本系列文章由@淺墨_毛星云 出品,轉(zhuǎn)載請注明出處。??

?

?

?

文章鏈接:?http://blog.csdn.net/poem_qianmo/article/details/21176257

?

作者:毛星云(淺墨)????郵箱:?happylifemxy@163.com?

寫作當前博文時配套使用的OpenCV版本: 2.4.8

?

?

上篇文章中我們講到了使用addWeighted函數(shù)進行圖像混合操作,以及將ROI和addWeighted函數(shù)結(jié)合起來使用,對指定區(qū)域進行圖像混合操作。

而為了更好的觀察一些圖像材料的特征,有時需要對RGB三個顏色通道的分量進行分別顯示和調(diào)整。通過OpenCV的split和merge方法可以很方便的達到目的。

這就是我們這篇文章的主要內(nèi)容。依然是先看一張截圖吧:

?

?

一、分離顏色通道

?

?

就讓我們來詳細介紹一下這兩個互為冤家的函數(shù)。首先是進行通道分離的split函數(shù)。

?

?

<1>split函數(shù)詳解

?

將一個多通道數(shù)組分離成幾個單通道數(shù)組。ps:這里的array按語境譯為數(shù)組或者陣列。

?

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

?

[cpp]?view plaincopyprint?
  • C++:?void?split(const?Mat&?src,?Mat*mvbegin);??
  • C++:?void?split(InputArray?m,OutputArrayOfArrays?mv);??
  • ?

    ?

    ?

    關于變量介紹:

    ?

    ?

    • 第一個參數(shù),InputArray類型的m或者const Mat&類型的src,填我們需要進行分離的多通道數(shù)組。
    • 第二個參數(shù),OutputArrayOfArrays類型的mv,填函數(shù)的輸出數(shù)組或者輸出的vector容器。

    ?

    ?

    ?

    就如上一節(jié)中講到方法一樣,這里的OutputArrayOfArrays我們通過【轉(zhuǎn)到定義】大法,可以查到它是_OutputArray的引用,那么我們在源代碼中再次通過【轉(zhuǎn)到定義】看到_OutputArray類的原型,即是OutputArrayOfArrays的原型:

    ?

    ?

    [cpp]?view plaincopyprint?
  • class?CV_EXPORTS?_OutputArray?:?public_InputArray??
  • {??
  • public:??
  • ???_OutputArray();??
  • ???
  • ???_OutputArray(Mat&?m);??
  • ???template<typename?_Tp>?_OutputArray(vector<_Tp>&?vec);??
  • ???template<typename?_Tp>?_OutputArray(vector<vector<_Tp>>&?vec);??
  • ???_OutputArray(vector<Mat>&?vec);??
  • ???template<typename?_Tp>?_OutputArray(vector<Mat_<_Tp>>&?vec);??
  • ???template<typename?_Tp>?_OutputArray(Mat_<_Tp>&?m);??
  • ???template<typename?_Tp,?int?m,?int?n>?_OutputArray(Matx<_Tp,?m,n>&?matx);??
  • ???template<typename?_Tp>?_OutputArray(_Tp*?vec,?int?n);??
  • ???_OutputArray(gpu::GpuMat&?d_mat);??
  • ???_OutputArray(ogl::Buffer&?buf);??
  • ???_OutputArray(ogl::Texture2D&?tex);??
  • ???
  • ????_OutputArray(constMat&?m);??
  • ???template<typename?_Tp>?_OutputArray(const?vector<_Tp>&vec);??
  • ???template<typename?_Tp>?_OutputArray(constvector<vector<_Tp>?>&?vec);??
  • ???_OutputArray(const?vector<Mat>&?vec);??
  • ???template<typename?_Tp>?_OutputArray(const?vector<Mat_<_Tp>>&?vec);??
  • ???template<typename?_Tp>?_OutputArray(const?Mat_<_Tp>&?m);??
  • ???template<typename?_Tp,?int?m,?int?n>?_OutputArray(constMatx<_Tp,?m,?n>&?matx);??
  • ???template<typename?_Tp>?_OutputArray(const?_Tp*?vec,?int?n);??
  • ???_OutputArray(const?gpu::GpuMat&?d_mat);??
  • ???_OutputArray(const?ogl::Buffer&?buf);??
  • ???_OutputArray(const?ogl::Texture2D&?tex);??
  • ???
  • ???virtual?bool?fixedSize()?const;??
  • ???virtual?bool?fixedType()?const;??
  • ???virtual?bool?needed()?const;??
  • ???virtual?Mat&?getMatRef(int?i=-1)?const;??
  • ???/*virtual*/?gpu::GpuMat&?getGpuMatRef()?const;??
  • ???/*virtual*/?ogl::Buffer&?getOGlBufferRef()?const;??
  • ???/*virtual*/?ogl::Texture2D&?getOGlTexture2DRef()?const;??
  • ???virtual?void?create(Size?sz,?int?type,?int?i=-1,?bool?allowTransposed=false,int?fixedDepthMask=0)?const;??
  • ???virtual?void?create(int?rows,?int?cols,?int?type,?int?i=-1,?boolallowTransposed=false,?int?fixedDepthMask=0)?const;??
  • ???virtual?void?create(int?dims,?const?int*?size,?int?type,?int?i=-1,?boolallowTransposed=false,?int?fixedDepthMask=0)?const;??
  • ???virtual?void?release()?const;??
  • ???virtual?void?clear()?const;??
  • ???
  • #ifdefOPENCV_CAN_BREAK_BINARY_COMPATIBILITY??
  • ???virtual?~_OutputArray();??
  • #endif??
  • };??


  • ?

    ?

    類體中還是有不少內(nèi)容的,其實注意到里面是定義的各種模板,重載的各種構(gòu)造函數(shù)就可以了。

    ?

    好了,穿越完OutputArrayOfArrays的介紹,我們繼續(xù)講解split。

    ?

    split函數(shù)分割多通道數(shù)組轉(zhuǎn)換成獨立的單通道數(shù)組,按公式來看就是這樣:

    ?

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    ?

    ?

    ?

    ?

    最后看一個示例吧:

    ?

    [cpp]?view plaincopyprint?
  • Mat?srcImage;??
  • Mat?imageROI;??
  • vector<Mat>?channels;??
  • srcImage=?cv::imread("dota.jpg");??
  • //?把一個3通道圖像轉(zhuǎn)換成3個單通道圖像??
  • split(srcImage,channels);//分離色彩通道??
  • ???????imageROI=channels.at(0);??
  • ???????addWeighted(imageROI(Rect(385,250,logoImage.cols,logoImage.rows)),1.0,??
  • ??????????????logoImage,0.5,0.,imageROI(Rect(385,250,logoImage.cols,logoImage.rows)));??
  • ???
  • ???????merge(channels,srcImage4);??
  • ???
  • ???????namedWindow("sample");??
  • ???????imshow("sample",srcImage);??
  • ?

    ?

    ?

    將一個多通道數(shù)組分離成幾個單通道數(shù)組的split()函數(shù)的內(nèi)容大概就是這些了,下面我們來看一下和他親如手足或者說是他的死對頭——merge()函數(shù)。

    ?

    ?

    <2>merge函數(shù)詳解

    ?

    merge()函數(shù)的功能是split()函數(shù)的逆向操作,將多個數(shù)組組合合并成一個多通道的數(shù)組。

    它通過組合一些給定的單通道數(shù)組,將這些孤立的單通道數(shù)組合并成一個多通道的數(shù)組,從而創(chuàng)建出一個由多個單通道陣列組成的多通道陣列。它有兩個基于C++的函數(shù)原型:

    ?

    [cpp]?view plaincopyprint?
  • C++:?void?merge(const?Mat*?mv,?size_tcount,?OutputArray?dst)??
  • C++:?void?merge(InputArrayOfArrays?mv,OutputArray?dst)??
  • ?

    ?

    ?

    ?

    • 第一個參數(shù),mv,填需要被合并的輸入矩陣或vector容器的陣列,這個mv參數(shù)中所有的矩陣必須有著一樣的尺寸和深度。
    • 第二個參數(shù),count,當mv為一個空白的C數(shù)組時,代表輸入矩陣的個數(shù),這個參數(shù)顯然必須大于1.
    • 第三個參數(shù),dst,即輸出矩陣,和mv[0]擁有一樣的尺寸和深度,并且通道的數(shù)量是矩陣陣列中的通道的總數(shù)。

    ?

    ?

    函數(shù)解析:

    merge函數(shù)的功能是將一些數(shù)組合并成一個多通道的數(shù)組。關于組合的細節(jié),輸出矩陣中的每個元素都將是輸出數(shù)組的串接,其中,第i個輸入數(shù)組的元素被視為mv[i]。 c一般用其中的Mat::at()方法對某個通道進行存取,也就是這樣用channels.at(0)。

    PS: Mat::at()方法,返回一個引用到指定的數(shù)組元素。注意是引用,相當于兩者等價,修改其中一個另一個跟著變。

    ?

    來一個示例吧:

    ?

    [cpp]?view plaincopyprint?
  • vector<Mat>?channels;??
  • Mat?imageBlueChannel;??
  • Mat?imageGreenChannel;??
  • Mat?imageRedChannel;??
  • srcImage4=?imread("dota.jpg");??
  • //?把一個3通道圖像轉(zhuǎn)換成3個單通道圖像??
  • split(srcImage4,channels);//分離色彩通道??
  • imageBlueChannel?=?channels.at(0);??
  • imageGreenChannel?=?channels.at(1);??
  • imageRedChannel?=?channels.at(2);??
  • ?

    ?

    ?

    上面的代碼先做了相關的類型聲明,然后把載入的3通道圖像轉(zhuǎn)換成3個單通道圖像,放到vector<Mat>類型的channels中,接著進行引用賦值。

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

    ?

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

    ?

    ?

    ?

    ?

    ?

    二、多通道圖像混合示例程序

    ?

    ?

    ?

    依然是每篇文章都會配給大家的一個詳細注釋的示例程序,把這篇文章中介紹的知識點以代碼為載體,展現(xiàn)給大家。

    ?

    本篇文章中,我們把多通道圖像混合的實現(xiàn)代碼封裝在了名為MultiChannelBlending()的函數(shù)中。直接上代碼吧:

    ?

    ?

    [cpp]?view plaincopyprint?
  • //-----------------------------------【程序說明】----------------------------------------------??
  • //??程序名稱::【OpenCV入門教程之四】分離顏色通道&多通道圖像混合???配套源碼??
  • //?VS2010版???OpenCV版本:2.4.8??
  • //?????2014年3月13?日?Create?by?淺墨??
  • //??圖片素材出處:dota2原畫?dota2logo???
  • //?????淺墨的微博:@淺墨_毛星云??
  • //------------------------------------------------------------------------------------------------??
  • ???
  • //-----------------------------------【頭文件包含部分】---------------------------------------??
  • //?????描述:包含程序所依賴的頭文件??
  • //----------------------------------------------------------------------------------------------??????????????????????????????????????????????????????????????????????????????????????
  • #include?<cv.h>??
  • #include?<highgui.h>??
  • #include?<iostream>??
  • ???
  • //-----------------------------------【命名空間聲明部分】---------------------------------------??
  • //?????描述:包含程序所使用的命名空間??
  • //-----------------------------------------------------------------------------------------------????
  • using?namespace?cv;??
  • using?namespace?std;??
  • ???
  • ???
  • //-----------------------------------【全局函數(shù)聲明部分】--------------------------------------??
  • //?????描述:全局函數(shù)聲明??
  • //-----------------------------------------------------------------------------------------------??
  • bool?MultiChannelBlending();??
  • ???
  • //-----------------------------------【main(?)函數(shù)】--------------------------------------------??
  • //?????描述:控制臺應用程序的入口函數(shù),我們的程序從這里開始??
  • //-----------------------------------------------------------------------------------------------??
  • int?main(??)??
  • {??
  • ???????system("color5E");??
  • ???
  • ???????if(MultiChannelBlending())??
  • ???????{??
  • ??????????????cout<<endl<<"嗯。好了,得出了你需要的混合值圖像~";??
  • ???????}??
  • ???
  • ???????waitKey(0);??
  • ???????return?0;??
  • }??
  • ???
  • ???
  • //-----------------------------【MultiChannelBlending(?)函數(shù)】--------------------------------??
  • //?????描述:多通道混合的實現(xiàn)函數(shù)??
  • //-----------------------------------------------------------------------------------------------??
  • 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通道圖像轉(zhuǎn)換成3個單通道圖像??
  • ???????split(srcImage,channels);//分離色彩通道??
  • ???
  • ???????//【3】將原圖的藍色通道引用返回給imageBlueChannel,注意是引用,相當于兩者等價,修改其中一個另一個跟著變??
  • ???????imageBlueChannel=channels.at(0);??
  • ???????//【4】將原圖的藍色通道的(500,250)坐標處右下方的一塊區(qū)域和logo圖進行加權操作,將得到的混合結(jié)果存到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藍色通道?by淺墨");??
  • ???????imshow("<1>游戲原畫+logo藍色通道?by淺墨",srcImage);??
  • ???
  • ???
  • ???????//=================【綠色通道部分】=================??
  • ???????//?????描述:多通道混合-綠色分量部分??
  • ???????//============================================??
  • ???
  • ???????//【0】定義相關變量??
  • ???????Mat??imageGreenChannel;??
  • ???
  • ???????//【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】將一個三通道圖像轉(zhuǎn)換成三個單通道圖像??
  • ???????split(srcImage,channels);//分離色彩通道??
  • ???
  • ???????//【3】將原圖的綠色通道的引用返回給imageBlueChannel,注意是引用,相當于兩者等價,修改其中一個另一個跟著變??
  • ???????imageGreenChannel=channels.at(1);??
  • ???????//【4】將原圖的綠色通道的(500,250)坐標處右下方的一塊區(qū)域和logo圖進行加權操作,將得到的混合結(jié)果存到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綠色通道?by淺墨");??
  • ???????imshow("<2>游戲原畫+logo綠色通道?by淺墨",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】將一個三通道圖像轉(zhuǎn)換成三個單通道圖像??
  • ???????split(srcImage,channels);//分離色彩通道??
  • ???
  • ???????//【3】將原圖的紅色通道引用返回給imageBlueChannel,注意是引用,相當于兩者等價,修改其中一個另一個跟著變??
  • ???????imageRedChannel=channels.at(2);??
  • ???????//【4】將原圖的紅色通道的(500,250)坐標處右下方的一塊區(qū)域和logo圖進行加權操作,將得到的混合結(jié)果存到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紅色通道?by淺墨");??
  • ???????imshow("<3>游戲原畫+logo紅色通道?by淺墨",srcImage);??
  • ???
  • ???????return?true;??
  • }??
  • ?

    ?

    ?

    可以發(fā)現(xiàn),其實多通道混合的實現(xiàn)函數(shù)中的代碼大體分成三部分,分別對藍綠紅三個通道進行處理,唯一不同的地方是在取通道分量時取的是channels.at(0),channels.at(1)還是channels.at(2)。

    嗯,下面看一下運行截圖:

    ?

    ?

    ?

    ?

    ?嗯,本篇文章到這里就基本結(jié)束了,最后放出本篇文章配套示例程序的下載地址。

    ?

    ?

    本篇文章的配套源代碼請點擊這里下載:

    ?

    ?

    【淺墨OpenCV入門教程之五】配套源代碼下載

    ?

    ?

    OK,本節(jié)的內(nèi)容大概就是這些,我們下篇文章見:)

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/wobuchouyan/p/5059135.html

    總結(jié)

    以上是生活随笔為你收集整理的【OpenCV入门教程之五】 分离颜色通道多通道图像混合(转)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。