1. 程式人生 > >opencv學習(八)之ROI區域和影象混合疊加

opencv學習(八)之ROI區域和影象混合疊加

1.影象線性混合疊加

在進行影象處理時,opencv中提供了addWeighted()實現對兩幅影象的疊加。這是一種線性混合操作,其公式如下:
這裡寫圖片描述
通過改變a的值,可以實現兩幅影象或視訊進行混合時出現不同的效果。
其函式定義如下:

CV_EXPORTS_W void addWeighted(InputArray src1, double alpha, InputArray src2,
                              double beta, double gamma, OutputArray dst, int dtype=-1);

詳細引數說明如下:
src1: 第一幅輸入影象
alpha: 線性混合時第一幅影象的權重
src2: 第二幅輸入影象
beta: 第二幅輸入影象的權重
dst: 影象線性混合後的目標影象
gamma: 新增到每一個線性疊加總和的gamma值
dtype: 目標影象深度,當兩幅影象深度相同時可以將dtype置為-1,這樣目標影象的深度將與輸入影象相同

其中beta - (1.0 - alpha);

對於每個畫素點其計算公式如下:
這裡寫圖片描述

示例程式碼如下:

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

int main()
{
    Mat srcImage1 = imread("forest.jpg");
    Mat srcImage2 = imread("rain.jpg");
    Mat dstImage;

    //檢查檔案是否載入成功
if(srcImage1.empty() || srcImage2.empty()) { cout << "影象載入失敗!" << endl << endl; return -1; } else cout << "影象載入成功!" << endl << endl; double alpha = 0.5; double beta; double input; cout << "Please Input alpha[0-1]: "
; cin >> input; //判斷輸入的alpha是否符合要求 if(input >= 0.0 && input <= 1.0) { alpha = input; } namedWindow("線性混合", WINDOW_NORMAL); beta = (1.0 - alpha); addWeighted(srcImage1, alpha, srcImage2, beta, 0.0, dstImage); imshow("線性混合", dstImage); namedWindow("srcImage1",WINDOW_NORMAL); imshow("srcImage1",srcImage1); namedWindow("srcImage2",WINDOW_NORMAL); imshow("srcImage2",srcImage2); waitKey(0); return 0; }

執行結果如下所示:

這裡寫圖片描述

該執行結果輸入值為0.5.

注意:兩幅影象混合時必須要求兩幅影象的尺寸和型別完全相同。

通過對影象設定ROI區域可以實現不同尺寸影象的混合。
在進行影象處理時,常常需要設定感興趣區域(ROI, region of interest),可以在影象任意位置建立ROI區域,設定ROI區域後可以更有針對性的進行下一步處理。
定義ROI有兩種方法(假定都從影象左上角(100,100)的位置劃定ROI):
第一種是使用表示矩形區域的Rect。它指定矩形的左上角座標和矩形的長寬來劃定ROI區域。

ROIImage = srcImage(Rect(100,100,smallImage.cols,smallImage.rows));

第二種方法是使用Range()指定感興趣區域的行或列的範圍。Range()指定的區域是一個連續的儲存序列。

ROIImage = srcImage(Range(100,smallImage.rows),Range(100,smallImage.cols));

示例程式碼如下:

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace std;
using namespace cv;

int main()
{
    Mat srcImage = imread("space.jpg");
    Mat addImage = imread("astronautB.jpg");

    //判斷檔案是否載入成功
    if(srcImage.data && addImage.data)
        cout << "影象載入成功!" << endl << endl;
    else
    {
        cout << "影象載入失敗!" << endl << endl;
        return -1;
    }
    imshow("srcImage",srcImage);
    imshow("astronaut",addImage);

    //設定srcImage感興趣區域
    //第一種方式,使用Rect()函式設定ROI
    Mat imageROI = srcImage(Rect(50,50,addImage.cols,addImage.rows));
    addWeighted(imageROI,0.7,addImage,0.3,0,imageROI);
    imshow("混合後圖像",srcImage);

    waitKey(0);

    return 0;
}

其執行結果如下所示:
這裡寫圖片描述

還可以利用copyTo()通過影象掩模板直接將影象複製到ROI區域。但是這種方法要求maskImage必須是灰度圖。示例程式碼如下:

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

int main()
{
    Mat srcImage = imread("space.jpg");
    Mat addImage = imread("astronautB.jpg");
    Mat maskImage = imread("astronautB.jpg",IMREAD_GRAYSCALE);  //載入其灰度圖

    //判斷檔案是否載入成功
    if(srcImage.data && addImage.data)
        cout << "影象載入成功!" << endl << endl;
    else
    {
        cout << "影象載入失敗!" << endl << endl;
        return -1;
    }

    //以第二種方式Range()函式設定其ROI區域
    Mat imageROI = srcImage(Range(50,50+maskImage.rows), Range(50,50+maskImage.cols));
    addImage.copyTo(imageROI,maskImage);
    imshow("混合後圖像",srcImage);

    waitKey(0);

    return 0;
}

執行結果如下:
這裡寫圖片描述