一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

opencv學習筆記圖像疊加混合

 mediatv 2020-03-05

在圖像處理中,目標區(qū)域定義為感興趣區(qū)域ROI(region of Interest),這是后期圖像處理的基礎,在獲取ROI后,進行一些列的處理。ROI區(qū)域在Opencv中就是Rect,先構建Rect,然后給予ROI一些特點,形成了圖像掩膜。

一、ROI創(chuàng)建

復制代碼
//定義一個Mat類型并給其設定ROI區(qū)域

Mat imageROI;

//方法一

imageROI=image(Rect(500,250,logo.cols,logo.rows));
//方法二 
imageROI=Image(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));
復制代碼

代碼中定義了一個Mat類型,是一種類似指針的引用,然后指向Image(Mat)中制定區(qū)域,這樣就創(chuàng)建了一個ROI區(qū)域,這個區(qū)域在Image中。

二、圖像掩膜

圖像掩膜,在ROI區(qū)域中導入一張圖像,然后在image中進行加載

復制代碼
Mat Image1= imread("dota_pa.jpg"); 
//定義一個Mat類型并給其設定ROI區(qū)域  ,指向Image中坐標點200,250,長寬為cols和rows
       Mat imageROI= Image1(Rect(200,250,logoImage.cols,logoImage.rows));  
   
       //加載掩模(必須是灰度圖)  
       Mat mask= imread("dota_logo.jpg",0);  
   
       //將掩膜拷貝到ROI  
       logoImage.copyTo(imageROI,mask);
復制代碼

三、線性混合

線性混合就是,對兩幅圖像(f0(x)和f1(x))或兩段視頻(同樣為(f0(x)和f1(x))產生時間上的畫面疊化(cross-dissolve)效果,就像幻燈片放映和電影制作中的那樣。函數表示為:

1、opencv函數-addWeighted函數

復制代碼
void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1);  
//第一個參數,InputArray類型的src1,表示需要加權的第一個數組,常常填一個Mat。
//第二個參數,alpha,表示第一個數組的權重
//第三個參數,src2,表示第二個數組,它需要和第一個數組擁有相同的尺寸和通道數。
//第四個參數,beta,表示第二個數組的權重值。
//第五個參數,dst,輸出的數組,它和輸入的兩個數組擁有相同的尺寸和通道數。
//第六個參數,gamma,一個加到權重總和上的標量值。看下面的式子自然會理解。
//第七個參數,dtype,輸出陣列的可選深度,有默認值-1。;當兩個輸入數組具有相同的深度時,個參數設置為-1(默認值),即等同于src1.depth()。dst = src1 
復制代碼

addWeighted函數計算如下兩個數組(src1和src2)的加權和,得到結果輸出給第四個參數。即addWeighted函數的作用可以被表示為為如下的矩陣表達式為: dst = src1[I]*alpha+ src2[I]*beta + gamma;

2、實例代碼

復制代碼
//【1】讀取圖像  
       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; }  
   
       //【2】定義一個Mat類型并給其設定ROI區(qū)域  
       Mat imageROI;  
              //方法一  
       imageROI=srcImage4(Rect(200,250,logoImage.cols,logoImage.rows));  
       
       //【3】將logo加到原圖上  ,利用線性混合構建掩膜,其中l(wèi)ogo權重是0.3,原圖中的ROI區(qū)域圖像是0.5
       addWeighted(imageROI,0.5,logoImage,0.3,0.,imageROI);  
   
       //【4】顯示結果  
       namedWindow("<4>區(qū)域線性圖像混合示例窗口 by淺墨");  
       imshow("<4>區(qū)域線性圖像混合示例窗口 by淺墨",srcImage4);  
        
       return true;
復制代碼

四、多通道顏色混合

彩色圖像是三通道圖像,當然灰度圖像是單通道圖像,在圖像應用中需要對某一通道混合,或者幾個通道顏色混合,這就是多通道顏色混合。在多通道顏色混合應用中在opencv需要split函數和merge函數。

1、分離顏色通道

復制代碼
C++: void split(const Mat& src, Mat*mvbegin);

C++: void split(InputArray m,OutputArrayOfArrays mv);
//第一個參數,InputArray類型的m或者const Mat&類型的src,填我們需要進行分離的多通道數組。
//第二個參數,OutputArrayOfArrays類型的mv,填函數的輸出數組或者輸出的vector容器
復制代碼

split函數分割多通道數組轉換成獨立的單通道數組,按公式來講:

復制代碼
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
};
復制代碼

上面函數講解是OutputArray類原型,其中是模板類為主,注意類對象的創(chuàng)建。

split函數應用

復制代碼
vector<Mat> channels;
Mat imageBlueChannel;
Mat imageGreenChannel;
Mat imageRedChannel;
srcImage4= imread("dota.jpg");
// 把一個3通道圖像轉換成3個單通道圖像
split(srcImage4,channels);//分離色彩通道
imageBlueChannel = channels.at(0);
imageGreenChannel = channels.at(1);
imageRedChannel = channels.at(2);
復制代碼

載入的3通道圖像轉換成3個單通道圖像,放到vector<Mat>類型的channels中,接著進行引用賦值。

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

2、圖像混合

圖像混合中通過組合一些給定的單通道數組,將這些孤立的單通道數組合并成一個多通道的數組,從而創(chuàng)建出一個由多個單通道陣列組成的多通道陣列。

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

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

五、圖像混合綜合代碼及解析

復制代碼
//-----------------------------------【程序說明】----------------------------------------------
//  程序名稱::【OpenCV入門教程之四】分離顏色通道&多通道圖像混合   配套源碼 
// VS2010版   OpenCV版本:2.4.8
//     2014年3月13 日 Create by 淺墨
//  圖片素材出處:dota2原畫 dota2logo  
//     配套博文鏈接:http://blog.csdn.net/poem_qianmo/article/details/20537737
//     淺墨的微博:@淺墨_毛星云
//------------------------------------------------------------------------------------------------

//-----------------------------------【頭文件包含部分】---------------------------------------
//    描述:包含程序所依賴的頭文件
//----------------------------------------------------------------------------------------------   

#include <cv.hpp>
#include <highgui.hpp>
#include <iostream>

//-----------------------------------【命名空間聲明部分】---------------------------------------
//    描述:包含程序所使用的命名空間
//-----------------------------------------------------------------------------------------------   
using namespace cv;
using namespace std;


//-----------------------------------【全局函數聲明部分】--------------------------------------
//    描述:全局函數聲明
//-----------------------------------------------------------------------------------------------
bool  MultiChannelBlending();

//-----------------------------------【main( )函數】--------------------------------------------
//    描述:控制臺應用程序的入口函數,我們的程序從這里開始
//-----------------------------------------------------------------------------------------------
int main(   )
{
    system("color 5E");

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

    waitKey(0);
    return 0;
}


//-----------------------------【MultiChannelBlending( )函數】--------------------------------
//    描述:多通道混合的實現函數
//-----------------------------------------------------------------------------------------------
bool  MultiChannelBlending()
{
    //【0】定義相關變量
    Mat srcImage,greSrcImage,redSrcImage;    
    Mat logoImage;
    vector<Mat> channels;
    Mat  imageBlueChannel;
    //【0】定義相關變量
    Mat  imageGreenChannel;
    //【0】定義相關變量
    Mat  imageRedChannel,redTempImage,greTempImage,blueTempImage;

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

    // 【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; }
    srcImage.copyTo(greSrcImage);
    srcImage.copyTo(redSrcImage);
    //【2】把一個3通道圖像轉換成3個單通道圖像
    split(srcImage,channels);//分離色彩通道

    //【3】將原圖的藍色通道引用返回給imageBlueChannel,注意是引用,相當于兩者等價,修改其中一個另一個跟著變
    imageBlueChannel= channels.at(0);
    //這是引用,指向channels,后面調用clear,這樣數據清空了
    //imageGreenChannel = channels.at(1);    
    
    

    ////展示單通道圖像
    //imshow("單通道藍色圖像",imageBlueChannel);
    //imshow("單通道紅色圖像",imageRedChannel);
    //imshow("單通道綠色圖像",imageGreenChannel);    

    //【4】將原圖的藍色通道的(500,250)坐標處右下方的一塊區(qū)域和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)));
    imshow("加載log后的藍色圖像",imageBlueChannel);

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

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


    //=================【綠色通道部分】=================
    //    描述:多通道混合-綠色分量部分
    //============================================
//    imshow("綠色圖像原圖像",greSrcImage);
    //因為同道中藍色通道已經加載logo進去,所以此時logo會有變化的,重新分離通道
    channels.clear();
    split(greSrcImage,channels);
    imageGreenChannel = channels.at(1);    
    //【4】將原圖的綠色通道的(500,250)坐標處右下方的一塊區(qū)域和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】將三個獨立的單通道重新合并成一個三通道,如果繼續(xù)這樣,因為同道中藍色通道已經加載logo進去,所以此時logo會有變化的
    merge(channels,greSrcImage);
    
    

    //【6】顯示效果圖    
    imshow("<2>游戲原畫+logo綠色通道",greSrcImage);



    //=================【紅色通道部分】=================
    //    描述:多通道混合-紅色分量部分
    //============================================
    channels.clear();
        split(redSrcImage,channels);
        imageRedChannel = channels.at(2);    
    //【4】將原圖的紅色通道的(500,250)坐標處右下方的一塊區(qū)域和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,redSrcImage);

    //【6】顯示效果圖    
    imshow("<3>游戲原畫+logo紅色通道",redSrcImage);

    return true;
}
復制代碼

imageimageimageimageimageimage

image

六、結果分析

1、上述代碼中有ROI,就是創(chuàng)建感興趣區(qū)域,在代碼中直接用addweight函數直接完成了,實現mask的創(chuàng)建,是在SrcImage中ROI通過加權,將想要的圖像加載其中,實現mask的創(chuàng)建。

2、代碼中對split和merge進行演示、講解,split函數用于獲取單通道圖像,程序中對單通道圖像進行展示,發(fā)現單通道圖像都是灰度圖像,只是各個單通道圖像亮度不同,說明了在彩色圖像中red各占的比例大小。同時對于進行mask處理后的圖像進行展示,當然也是灰度圖像。

3、程序中分別是在srcImage中獲取到紅綠藍的logo進行處理,就是先將需要的通道獲取到,將logo按照一定比例添加其中(通道圖像權重要高一點,才能讓在roi中夜色占據主動),然后再合并。

4、程序一定注意到mat類型的應用,在程序大部分操作時引用,要記得保留未修改的數據。

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    久久精品国产亚洲av久按摩| 好东西一起分享老鸭窝| 亚洲中文字幕在线视频频道| 国产亚洲神马午夜福利| 国产级别精品一区二区视频 | 日本免费一区二区三女| 欧美av人人妻av人人爽蜜桃 | 老熟妇乱视频一区二区| 国产精品欧美激情在线| 亚洲av日韩av高潮无打码| 欧美日韩国产午夜福利| 99热九九热这里只有精品| 日韩中文字幕欧美亚洲| 精品人妻精品一区二区三区| 狠色婷婷久久一区二区三区| 尹人大香蕉一级片免费看| 国产欧美日韩精品自拍| 欧美日韩国产午夜福利| 亚洲国产av国产av| 久久99国产精品果冻传媒| 午夜精品成年人免费视频| 熟女高潮一区二区三区| 国产欧美另类激情久久久| 国产成人亚洲综合色就色| 亚洲精品国产精品日韩| 午夜福利在线观看免费| 亚洲品质一区二区三区| 精品综合欧美一区二区三区| 亚洲国产欧美久久精品| 日本高清一区免费不卡| 老外那个很粗大做起来很爽| 91亚洲人人在字幕国产| 懂色一区二区三区四区| 色狠狠一区二区三区香蕉蜜桃| 久久亚洲精品成人国产| 99日韩在线视频精品免费| 婷婷色香五月综合激激情| 亚洲一区二区精品久久av| 在线免费不卡亚洲国产| 东京热一二三区在线免| 99热在线精品视频观看|