01
什麼是ROI?

在圖像處理領域,有一個非常重要的名詞ROI。
它的英文全稱是Region Of Interest,對應的中文解釋就是感興趣區域。
感興趣區域,就是我們從圖像中選擇一個圖像區域,這個區域就是圖像分析所關注的焦點。我們圈定這個區域,那麼我們要處理的圖像就從大圖像變為一個小圖像區域了,這樣以便進行進一步處理,可以大大減小處理時間。
定義ROI區域有兩種方法:
第一種,指定矩形的坐标,并且規定好他的長寬。
Mat img = imread("1.jpg");
Mat roi = img(Rect(500, 200, 100, 300));//Rect四個形參分别是:x坐标,y坐标,長,高;注意(x,y)指的是矩形的左上角點
複制
第二種,指定感興趣的行或列的範圍。
Mat img = imread("1.jpg");
Mat roi = img(Range(250, 250 + 100), Range(200, 200 + 100));//Range兩個形參分别是:起始行或列,起始行或列+偏移量
複制
簡單看一下ROI區域的使用方法,下面的程式定義了ROI,并且我用綠框标記出來。
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat srcImage = imread("lol0.jpg");
if (!srcImage.data)
{
cout << "讀取原始圖失敗!" << endl;
return -1;
}
rectangle(srcImage, Rect(0, 0, 600, 200), Scalar(0, 255, 0),2); //将感興趣區域框出來
imshow("ROI", srcImage);
waitKey();
return 0;
}
複制
綠框位置就是我們選的感興趣區域。
有時候我們不僅想把ROI标記出來,還想把ROI提取出來,成為一幅單獨圖檔,那我們代碼可以這麼寫:
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
//導入圖像
Mat img1 = imread("lol0.jpg", 1);
Mat img2(img1.rows, img1.cols, CV_8UC3);
//設定感興趣區域,拷貝
img1(Rect(500, 31, 200, 250)).copyTo(img2);
//當然也可以這樣
//Mat roi = img1(Rect(0,0,100,100));
//imshow("roi",roi);
//顯示
imshow("img1", img1);
imshow("img2", img2);
waitKey(0);
}
複制
這樣子,ROI就被提取出來了。
02
圖像加LOGO

現在我想在一幅好看的圖像上在給定的一個位置上加上下面這個酷炫的LOGO,有什麼方法嗎?
有兩種方法。
方法一:
先定義好ROI區域(也就是你要在哪裡加這個LOGO),然後進行線性疊加,使用addWeigthed函數。
這裡有必要介紹一下線性混合操作。
線性混合操作是一種典型的二進制(兩個輸入)的像素操作,它的理論公式如下:
我們通過在範圍0到1之間改變alpha值,來對兩幅圖像(如上述公式中的fa和f3)進行畫面疊代效果。OpenCV的相關操作如下:
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat srcImage = imread("lol.jpg");
if (!srcImage.data)
{
cout << "讀取原始圖失敗!" << endl;
return -1;
}
namedWindow("srcImage", WINDOW_NORMAL);// 注意這個宏,使用WINDOW_NORMAL可以允許使用者自由伸縮視窗大小
imshow("srcImage", srcImage);
Mat logo = imread("dota2.jpg");
if (!logo.data)
{
cout << "讀取原始logo圖失敗!" << endl;
return -1;
}
Mat imageROI = srcImage(Rect(28, 41, logo.cols, logo.rows)); //從原圖中摳出矩形區域,Rect第一二參數表示矩形左上角定點的坐标,用于定位,後兩個參數表示舉行的寬和高
imshow("ROI", imageROI);
addWeighted(imageROI, 0.2, logo, 0.8, 0., imageROI);//dst = src1[I]*alpha+ src2[I]*beta + gamma;第一第四個參數就是各自權重,第5個參數就是公式中的偏執因子gamma。
namedWindow("原圖加logo", WINDOW_NORMAL);
imshow("原圖加logo", srcImage);
waitKey();
return 0;
}
複制
效果如下,可以看出,我們的logo變得模糊了,也可以認為我們logo跟原圖水乳交融在一起了,我們可以不斷調整上面addWeighted()的參數,來獲得自己喜歡的效果。
方法二:
定義ROI區域,使用copyTo實作直接拷貝覆寫
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat srcImage = imread("lol.jpg");
if (!srcImage.data)
{
cout << "讀取原始圖失敗!" << endl;
return -1;
}
namedWindow("srcImage", WINDOW_NORMAL);// 注意這個宏,使用WINDOW_NORMAL可以允許使用者自由伸縮視窗大小
imshow("srcImage", srcImage);
Mat logo = imread("dota2.jpg");
Mat mask = imread("dota2.jpg",0); // 加載掩模(必須是灰階圖)
if (!logo.data)
{
cout << "讀取原始logo圖失敗!" << endl;
return -1;
}
Mat imageROI = srcImage(Rect(28, 41, logo.cols, logo.rows)); //從原圖中摳出矩形區域,Rect第一二參數表示矩形左上角定點的坐标,用于定位,後兩個參數表示舉行的寬和高
imshow("ROI", imageROI);
logo.copyTo(imageROI,mask);//注意兩個參數,一個是ROI,一個是掩模
namedWindow("原圖加logo", WINDOW_NORMAL);
imshow("原圖加logo", srcImage);
waitKey();
return 0;
}
複制
從效果看出,logo被原汁原味地拷貝到原圖上了。
主要借鑒”Madcola“和”Micheal超“兩位大神的文章。兩位大神的部落格首頁是:
https://www.cnblogs.com/skyfsm/(Madcola)
https://blog.csdn.net/qq_42887760(Micheal超)