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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

转载:【OpenCV入门教程之四】 ROI区域图像叠加初级图像混合 全剖析

發布時間:2025/3/13 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 转载:【OpenCV入门教程之四】 ROI区域图像叠加初级图像混合 全剖析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【OpenCV入門教程之四】 ROI區域圖像疊加&初級圖像混合 全剖析

淺墨_毛星云 2014-03-10 12:48:05 157425 收藏 19 最后發布:2014-03-10 12:48:05首發:2014-03-10 12:48:05 分類專欄: 【OpenCV】 【OpenCV】入門教程 版權聲明:本文為博主原創文章,遵循CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。 本文鏈接:https://blog.csdn.net/zhmxy555/article/details/20911629 展開


?

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

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

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

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


?

在這篇文章里,我們一起學習了在OpenCV中如何定義感興趣區域ROI,如何使用addWeighted函數進行圖像混合操作,以及將ROI和addWeighted函數結合起來使用,對指定區域進行圖像混合操作。

PS:文章末尾提供了博文配套程序源代碼的下載。


文章開頭,依舊是先放一張截圖:


?

?





一、設定感興趣區域——ROI(region of interest)




在圖像處理領域,我們常常需要設置感興趣區域(ROI,region of interest),來專注或者簡化我們的工作過程 。也就是從圖像中選擇的一個圖像區域,這個區域是我們圖像分析所關注的重點。我們圈定這個區域,以便進行進一步處理。而且,使用ROI指定我們想讀入的目標,可以減少處理時間,增加精度,給圖像處理來帶不小的便利。

?

?


ROI區域定義的兩種方法

?


定義ROI區域有兩種方法,第一種是使用cv:Rect.顧名思義,cv::Rect表示一個矩形區域。指定矩形的左上角坐標(構造函數的前兩個參數)和矩形的長寬(構造函數的后兩個參數)就可以定義一個矩形區域。

?

  • //定義一個Mat類型并給其設定ROI區域
  • Mat imageROI;
  • //方法一
  • imageROI=image(Rect(500,250,logo.cols,logo.rows));

  • 另一種定義ROI的方式是指定感興趣行或列的范圍(Range)。Range是指從起始索引到終止索引(不包括終止索引)的一連段連續序列。cv::Range可以用來定義Range。如果使用cv::Range來定義ROI,那么前例中定義ROI的代碼可以重寫為:

  • //方法二
  • imageROI=srcImage3(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));


  • 好了,下面我們來看一個實例,顯示如何利用ROI將一幅圖加到另一幅圖的指定位置。大家如果需要拷貝如下的函數中的代碼直接運行的話,自己建一個基于console的程序,然后把函數體中的內容拷貝到main函數中,然后找兩幅大小合適的圖片,加入到工程目錄下,并和代碼中讀取的文件名一致即可。

    在下面的代碼中,我們通過一個圖像掩膜(mask),直接將插入處的像素設置為logo圖像的像素值,這樣效果會很贊很逼真:

    ?

  • //----------------------------------【ROI_AddImage( )函數】----------------------------------
  • // 函數名:ROI_AddImage()
  • // 描述:利用感興趣區域ROI實現圖像疊加
  • //----------------------------------------------------------------------------------------------
  • bool ROI_AddImage()
  • {
  • //【1】讀入圖像
  • Mat srcImage1= imread("dota_pa.jpg");
  • Mat logoImage= imread("dota_logo.jpg");
  • if(!srcImage1.data ) { printf("你妹,讀取srcImage1錯誤~! \n"); return false; }
  • if(!logoImage.data ) { printf("你妹,讀取logoImage錯誤~! \n"); return false; }
  • //【2】定義一個Mat類型并給其設定ROI區域
  • Mat imageROI= srcImage1(Rect(200,250,logoImage.cols,logoImage.rows));
  • //【3】加載掩模(必須是灰度圖)
  • Mat mask= imread("dota_logo.jpg",0);
  • //【4】將掩膜拷貝到ROI
  • logoImage.copyTo(imageROI,mask);
  • //【5】顯示結果
  • namedWindow("<1>利用ROI實現圖像疊加示例窗口");
  • imshow("<1>利用ROI實現圖像疊加示例窗口",srcImage1);
  • return true;
  • }


  • 這個函數首先是載入了兩張jpg圖片到srcImage1和logoImage中,然后定義了一個Mat類型的imageROI,并使用cv::Rect設置其感興趣區域為srcImage1中的一塊區域,將imageROI和srcImage1關聯起來。接著定義了一個Mat類型的的mask并讀入dota_logo.jpg,順勢使用Mat:: copyTo把mask中的內容拷貝到imageROI中,于是就得到了最終的效果圖,namedWindow和imshow配合使用,顯示出最終的結果。


    運行結果如下:


    ?

    這里白色的dota2 logo,就是通過操作之后加上去的圖像。

    ?

    ?

    ?



    ?

    二、初級圖像混合——線性混合操作

    ?



    ?

    線性混合操作是一種典型的二元(兩個輸入)的像素操作,它的理論公式是這樣的:

    ??

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

    ?

    如果看過我之前寫的游戲編程Alpha混合那篇文章的朋友們應該有些熟悉,其實他們是差不多的:

    ?

    【Visual C++】游戲開發五十五淺墨 DirectX教程二十二水乳交融的美學:alpha混合技術


    ?

    我們通過在范圍0到1之間改變alpha值,來對兩幅圖像(f0(x)和f1(x))或兩段視頻(同樣為(f0(x)和f1(x))產生時間上的畫面疊化(cross-dissolve)效果,就像幻燈片放映和電影制作中的那樣。即在幻燈片翻頁時設置的前后頁緩慢過渡疊加效果,以及電影情節過渡時經常出現的畫面疊加效果。

    實現方面,我們主要運用了OpenCV中addWeighted函數,我們來全面的了解一下它:

    ?


    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()。

    ?

    如果用數學公式來表達,addWeighted函數計算如下兩個數組(src1和src2)的加權和,得到結果輸出給第四個參數。即addWeighted函數的作用可以被表示為為如下的矩陣表達式為:

    ?

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dst = src1[I]*alpha+ src2[I]*beta + gamma;

    ?

    其中的I,是多維數組元素的索引值。而且,在遇到多通道數組的時候,每個通道都需要獨立地進行處理。另外需要注意的是,當輸出數組的深度為CV_32S時,這個函數就不適用了,這時候就會內存溢出或者算出的結果壓根不對。

    ?

    ?

    理論和函數的講解就是上面這些,接著我們來看代碼實例,以融會貫通。

    ?

  • //---------------------------------【LinearBlending()函數】-------------------------------------
  • // 函數名:LinearBlending()
  • // 描述:利用cv::addWeighted()函數實現圖像線性混合
  • //--------------------------------------------------------------------------------------------
  • bool LinearBlending()
  • {
  • //【0】定義一些局部變量
  • double alphaValue = 0.5;
  • double betaValue;
  • Mat srcImage2, srcImage3, dstImage;
  • //【1】讀取圖像 ( 兩幅圖片需為同樣的類型和尺寸 )
  • srcImage2= imread("mogu.jpg");
  • srcImage3= imread("rain.jpg");
  • if(!srcImage2.data ) { printf("你妹,讀取srcImage2錯誤~! \n"); return false; }
  • if(!srcImage3.data ) { printf("你妹,讀取srcImage3錯誤~! \n"); return false; }
  • //【2】做圖像混合加權操作
  • betaValue= ( 1.0 - alphaValue );
  • addWeighted(srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);
  • //【3】創建并顯示原圖窗口
  • namedWindow("<2>線性混合示例窗口【原圖】 by淺墨", 1);
  • imshow("<2>線性混合示例窗口【原圖】 by淺墨", srcImage2 );
  • namedWindow("<3>線性混合示例窗口【效果圖】 by淺墨", 1);
  • imshow("<3>線性混合示例窗口【效果圖】 by淺墨", dstImage );
  • return true;
  • }



  • 代碼解析:


    <0>首先當然是定義一些局部變量,alpha值beta值,三個Mat類型的變量。

    ?

  • //【0】定義一些局部變量
  • double alphaValue = 0.5;
  • double betaValue;
  • Mat srcImage2, srcImage3, dstImage;
  • ? ? ? ?

    在這里我們設置alpha值為0.5。

    ?

    <1>讀取兩幅圖像并作錯誤處理

    這步很簡單,直接上代碼:

    ? ? ? ?

  • //讀取圖像 ( 兩幅圖片需為同樣的類型和尺寸 )
  • srcImage2= imread("mogu.jpg");
  • srcImage3= imread("rain.jpg");
  • if(!srcImage2.data ) { printf("你妹,讀取srcImage2錯誤~! \n"); return false; }
  • if(!srcImage3.data ) { printf("你妹,讀取srcImage3錯誤~! \n"); return false; }

  • 在這里需要注意的是,因為我們是對 srcImage1和srcImage2求和,所以它們必須要有相同的尺寸(寬度和高度)和類型,不然多余的部分沒有對應的“伴”,肯定會出問題。


    <2> 進行圖像混合加權操作

    載入圖像后,我們就可以來生成混合圖像,也就是之前公式中的g(x)。為此目的,使用函數 addWeighted 可以很方便地實現,也就是因為 addWeighted 進行了如下計算:

    ?

    這里的對應于addWeighted的第2個參數alpha

    這里的對應于addWeighted的第4個參數beta

    這里的對應于addWeighted的第5個參數,在上面代碼中被我們設為0.0。

    代碼其實很簡單,就是這樣:?

  • //【2】進行圖像混合加權操作
  • betaValue = ( 1.0 - alphaValue );
  • addWeighted( srcImage2, alphaValue, srcImage3,betaValue, 0.0, dstImage);
  • 其中beta值為1-alpha,gamma值為0


  • <3>創建顯示窗口,顯示圖像。

  • // 【3】創建并顯示原圖窗口
  • namedWindow("<2>線性混合示例窗口【原圖】 by淺墨", 1);
  • imshow("<2>線性混合示例窗口【原圖】 by淺墨", srcImage2 );
  • namedWindow("<3>線性混合示例窗口【效果圖】 by淺墨", 1);
  • imshow("<3>線性混合示例窗口【效果圖】 by淺墨", dstImage );


  • 接著來看一下運行效果圖,首先是原圖:



    然后是效果圖:

    ?

    ?





    三、綜合示例

    ?



    在前面分別介紹的設定感興趣區域ROI和使用addWeighted函數進行圖像線性混合的基礎上,我們還將他們兩者中和起來使用,也就是先指定ROI,并用addWeighted函數對我們指定的ROI區域的圖像進行混合操作,我們將其封裝在了一個名為ROI_LinearBlending的函數中,方便大家分塊學習。

    ?


  • //---------------------------------【ROI_LinearBlending()】-------------------------------------
  • // 函數名:ROI_LinearBlending()
  • // 描述:線性混合實現函數,指定區域線性圖像混合.利用cv::addWeighted()函數結合定義
  • // 感興趣區域ROI,實現自定義區域的線性混合
  • //--------------------------------------------------------------------------------------------
  • bool ROI_LinearBlending()
  • {
  • //【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區域
  • Mat imageROI;
  • //方法一
  • imageROI=srcImage4(Rect(200,250,logoImage.cols,logoImage.rows));
  • //方法二
  • //imageROI=srcImage4(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));
  • //【3】將logo加到原圖上
  • addWeighted(imageROI,0.5,logoImage,0.3,0.,imageROI);
  • //【4】顯示結果
  • namedWindow("<4>區域線性圖像混合示例窗口 by淺墨");
  • imshow("<4>區域線性圖像混合示例窗口 by淺墨",srcImage4);
  • return true;
  • }



  • 從這篇文章開始,如果不出意外的話,為了方便大家分塊各個擊破學習,每講一個部分,示例代碼都將封裝在一個函數中,免得大家像學習各種不是特別地道的OpenCV教程時一樣,看到代碼全放在main函數中,心都碎了。

    ?

    好了,下面放出詳細注釋的本篇文章的全部示例源代碼:

    ?

  • //-----------------------------------【程序說明】----------------------------------------------
  • // 程序名稱::【OpenCV入門教程之四】 ROI區域圖像疊加&初級圖像混合 全剖析 配套源碼
  • // VS2010版 OpenCV版本:2.4.8
  • // 2014年3月10日 Create by 淺墨
  • // 圖片素材出處:dota2原畫 dota2logo
  • // 淺墨的微博:@淺墨_毛星云
  • //------------------------------------------------------------------------------------------------
  • //-----------------------------------【頭文件包含部分】---------------------------------------
  • // 描述:包含程序所依賴的頭文件
  • //----------------------------------------------------------------------------------------------
  • #include <cv.h>
  • #include <highgui.h>
  • #include <iostream>
  • //-----------------------------------【命名空間聲明部分】---------------------------------------
  • // 描述:包含程序所使用的命名空間
  • //-----------------------------------------------------------------------------------------------
  • using namespace cv;
  • using namespace std;
  • //-----------------------------------【全局函數聲明部分】--------------------------------------
  • // 描述:全局函數聲明
  • //-----------------------------------------------------------------------------------------------
  • bool ROI_AddImage();
  • bool LinearBlending();
  • bool ROI_LinearBlending();
  • //-----------------------------------【main( )函數】--------------------------------------------
  • // 描述:控制臺應用程序的入口函數,我們的程序從這里開始
  • //-----------------------------------------------------------------------------------------------
  • int main( )
  • {
  • system("color 5E");
  • if(ROI_AddImage()&& LinearBlending( )&&ROI_LinearBlending( ))
  • {
  • cout<<endl<<"嗯。好了,得出了你需要的圖像~! : )";
  • }
  • waitKey(0);
  • return 0;
  • }
  • //----------------------------------【ROI_AddImage( )函數】----------------------------------
  • // 函數名:ROI_AddImage()
  • // 描述:利用感興趣區域ROI實現圖像疊加
  • //----------------------------------------------------------------------------------------------
  • bool ROI_AddImage()
  • {
  • //【1】讀入圖像
  • Mat srcImage1= imread("dota_pa.jpg");
  • Mat logoImage= imread("dota_logo.jpg");
  • if(!srcImage1.data ) { printf("你妹,讀取srcImage1錯誤~! \n"); return false; }
  • if(!logoImage.data ) { printf("你妹,讀取logoImage錯誤~! \n"); return false; }
  • //【2】定義一個Mat類型并給其設定ROI區域
  • Mat imageROI= srcImage1(Rect(200,250,logoImage.cols,logoImage.rows));
  • //【3】加載掩模(必須是灰度圖)
  • Mat mask= imread("dota_logo.jpg",0);
  • //【4】將掩膜拷貝到ROI
  • logoImage.copyTo(imageROI,mask);
  • //【5】顯示結果
  • namedWindow("<1>利用ROI實現圖像疊加示例窗口");
  • imshow("<1>利用ROI實現圖像疊加示例窗口",srcImage1);
  • return true;
  • }
  • //---------------------------------【LinearBlending()函數】-------------------------------------
  • // 函數名:LinearBlending()
  • // 描述:利用cv::addWeighted()函數實現圖像線性混合
  • //--------------------------------------------------------------------------------------------
  • bool LinearBlending()
  • {
  • //【0】定義一些局部變量
  • double alphaValue = 0.5;
  • double betaValue;
  • Mat srcImage2, srcImage3, dstImage;
  • //【1】讀取圖像 ( 兩幅圖片需為同樣的類型和尺寸 )
  • srcImage2= imread("mogu.jpg");
  • srcImage3= imread("rain.jpg");
  • if(!srcImage2.data ) { printf("你妹,讀取srcImage2錯誤~! \n"); return false; }
  • if(!srcImage3.data ) { printf("你妹,讀取srcImage3錯誤~! \n"); return false; }
  • //【2】進行圖像混合加權操作
  • betaValue= ( 1.0 - alphaValue );
  • addWeighted(srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);
  • //【3】創建并顯示原圖窗口
  • namedWindow("<2>線性混合示例窗口【原圖】 by淺墨", 1);
  • imshow("<2>線性混合示例窗口【原圖】 by淺墨", srcImage2 );
  • namedWindow("<3>線性混合示例窗口【效果圖】 by淺墨", 1);
  • imshow("<3>線性混合示例窗口【效果圖】 by淺墨", dstImage );
  • return true;
  • }
  • //---------------------------------【ROI_LinearBlending()】-------------------------------------
  • // 函數名:ROI_LinearBlending()
  • // 描述:線性混合實現函數,指定區域線性圖像混合.利用cv::addWeighted()函數結合定義
  • // 感興趣區域ROI,實現自定義區域的線性混合
  • //--------------------------------------------------------------------------------------------
  • bool ROI_LinearBlending()
  • {
  • //【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區域
  • Mat imageROI;
  • //方法一
  • imageROI=srcImage4(Rect(200,250,logoImage.cols,logoImage.rows));
  • //方法二
  • //imageROI=srcImage4(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));
  • //【3】將logo加到原圖上
  • addWeighted(imageROI,0.5,logoImage,0.3,0.,imageROI);
  • //【4】顯示結果
  • namedWindow("<4>區域線性圖像混合示例窗口 by淺墨");
  • imshow("<4>區域線性圖像混合示例窗口 by淺墨",srcImage4);
  • return true;
  • }


  • 最后看一下整體的運行效果圖。

    首先是經過背景顏色修改的console窗口:



    然后依次是四張效果圖:









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



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



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



    OK,本節的內容大概就是這些,我們下篇文章見:)



    <div class="person-messagebox"><div class="left-message"><a href="https://blog.csdn.net/zhmxy555"><img src="https://profile.csdnimg.cn/0/4/9/3_zhmxy555" class="avatar_pic" username="zhmxy555"></a></div><div class="middle-message"><div class="title"><span class="tit "><a href="https://blog.csdn.net/zhmxy555" data-report-click="{&quot;mod&quot;:&quot;popu_379&quot;,&quot;ab&quot;:&quot;new&quot;}" target="_blank">淺墨_毛星云</a></span><!-- 等級,level --><img class="identity-icon" src="https://csdnimg.cn/identity/blog8.png"> <span class="flag expert"><a href="https://blog.csdn.net/home/help.html#classicfication" target="_blank"><img src="https://csdnimg.cn/release/phoenix/template/new_img/identityExpert.png" alt="">博客專家</a></span></div><div class="text"><span>原創文章 159</span><span>獲贊 9891</span><span>訪問量 755萬+</span></div></div><div class="right-message"><a class="btn btn-sm attented bt-button personal-watch" data-report-click="{&quot;mod&quot;:&quot;popu_379&quot;,&quot;ab&quot;:&quot;new&quot;,&quot;extend1&quot;:&quot;個人信息已關注&quot;}">已關注</a><a href="https://bbs.csdn.net/topics/395528843" target="_blank" class="btn btn-sm bt-button personal-messageboard">他的留言板</a></div></div></div> </article>

    總結

    以上是生活随笔為你收集整理的转载:【OpenCV入门教程之四】 ROI区域图像叠加初级图像混合 全剖析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。