設置圖片ROI(OpenCV學習筆記之二)

ROI相關簡介

ROI是什么

ROI是region of interest首字母的簡寫宴凉,翻譯為感性趣的區(qū)域。其實在寫本篇之前應該寫一篇關于圖片是什么的學習筆記恬口,但又感覺里面沒多少東西還不能承載一篇學習筆記校读,所以這里只簡單提一下。

圖片是什么

其實大家也應該能猜到圖片就是一個二維數(shù)組祖能,只不過這個二維數(shù)組有點特殊歉秫,它有頭信息,在頭信息里會有描述這個二維數(shù)組的大小养铸、圖片類型和數(shù)組元素的數(shù)據(jù)類型等雁芙。下面是一張從官方教程里獲取的一張輔助理解的圖片轧膘。

圖片就是一個二維數(shù)組

上面的圖片只是一張灰色的圖片而我們經(jīng)常用的圖片彩色的圖片,在灰圖片中一個像素我們用一個值就可以表示了却特,但在彩色的圖片中一個像素要用3個值或4個值(有的圖片有alpha通道)來表示扶供。下面就是一個由三個值表示一個像素的輔助理解圖筛圆。

BGR格式的圖片

這張圖片是從官網(wǎng)獲取的裂明。是不是覺得顏色的排序有點不對呀,我們想的應該是紅在前才對太援,其實在OpenCV中很多圖片都是BGR格式的和我們常見的到RGB格式的存儲方式是相反的闽晦。具體為什么要用BGR格式還不清楚如有大神知道還請科普。其他圖片的格式有很多種如,HVS提岔、CyCbCr仙蛉、HSI等格式,后續(xù)可能會專門寫一篇關于圖片格式的學習筆記碱蒙,這里先對圖片格式的介紹寫這么多荠瘪。

為什么要設置ROI

上面我已經(jīng)介紹過圖片是一個二維數(shù)組,而我們有時處理圖片的時候只對其中的一部分圖片的區(qū)域進行處理赛惩,例如我們想在圖片某個區(qū)域打馬賽克哀墓,為了性能考慮我們可以只讓程序?qū)@一部分信息進行處理而將其他部分忽略,這時我們就要設置圖片感性趣的區(qū)域喷兼。設置完感性趣的區(qū)域后其實是指針指到了ROI區(qū)域的左上角篮绰,好像我們截取了一張小圖片一樣,我們只對這張小圖片進行處理就可以了季惯,因其ROI指向的還是原圖只在告訴它圖片的起始位置和大小變了吠各,所以在對ROI區(qū)操作會影響原圖。

設置ROI

在OpenCV中有C和C++的代碼勉抓,最早OpenCV是用C寫的贾漏,在開發(fā)中C的代碼寫起來不太方便在版本進入2.0之后后續(xù)加入的代碼改用C++,所以設置ROI的方法有兩種即C和C++的藕筋,C的已不常用不過這里還會列出已方便了解纵散。
C++

- (void)setImageROI:(cv::Mat)image{
    
    // 設置ROI
    // 方法一
    cv::Mat roiImage = image(cv::Rect(100, 100, 200, 100));
    // 方法二,第一個range表示起始行和終止行念逞,第二個range是起始列和終止列
    //cv::Mat roiImage = testImage(cv::Range(100, 100 + 100), cv::Range(100, 200 + 100));
    // 畫一個矩形
    cv::rectangle(roiImage, cv::Rect(0, 0, 200, 100), cv::Scalar(255, 0, 0), 10);
}

設置ROI其實就是在原來圖片上指定一個區(qū)域困食,而這個區(qū)域只是新創(chuàng)建了一個圖片文件的頭信息而已并沒有產(chǎn)生新的圖片,文件頭里的圖片區(qū)域的起始位置指向了ROI區(qū)域的左上角位置翎承,所以在ROI上做的任何操作都會影響原圖片硕盹。

C

- (void)setImageROI:(IplImage *)image{
    
    // 記錄圖片的大小和區(qū)域
    CvRect currentRect = cvGetImageROI(image);
    // 設置ROI區(qū)域
    cvSetImageROI(image, cvRect(100, 100, 200, 100));
    
    // 畫一個矩形
    cvRectangleR(image, cvRect(0, 0, 200, 100), CvScalar(255, 0, 0), 10);
    
    // 還原ROI區(qū)域
    cvSetImageROI(image, currentRect);
    // 上面的還原ROI區(qū)域要一個臨時變量,也可通過下面的方法叨咖,還原ROI區(qū)域而不用創(chuàng)建臨時變量
    //cvResetImageROI(image);
}

對于C的代碼沒有生成一個文件頭信息而是修改原來的文件頭信息瘩例,所以要把文件頭信息改回去“〗海現(xiàn)在是不是覺得C++比C簡單多了。

代碼實戰(zhàn)

一垛贤、設置ROI并畫矩形

以下代碼是核心代碼焰坪,其他簡單的顯示代碼將不再列出。首先請導入以下頭文件聘惦。

#import <opencv2/opencv.hpp>
#import <opencv2/imgproc/types_c.h>
#import <opencv2/imgcodecs/ios.h>

然后下面是具體的ROI代碼都有注釋某饰,原理上面已說明。

- (UIImage *)getOpenCVImage{
    
    // 獲取測試用的圖片路徑
    NSString * path = [[NSBundle mainBundle] pathForResource:@"test" ofType:nil];
    // 讀取圖片
    cv::Mat testImage = cv::imread([path cStringUsingEncoding:NSUTF8StringEncoding]);
    // 設置ROI
    cv::Mat roiImage = testImage(cv::Rect(100, 100, 100, 100));
    // 在ROI區(qū)域做操作善绎,畫一個矩形
    cv::rectangle(roiImage, cv::Rect(5, 5, 50, 50), cv::Scalar(255, 255, 255), 10);
    
    // 將圖片的格式從BGR轉換成RGB黔漂,如果不轉會造成顯示的圖片顏色出錯
    cv::cvtColor(testImage, testImage, cv::COLOR_BGR2RGB);
    // 返回UIImage類型的圖片
    return MatToUIImage(testImage);
}

運行結果如下第一張是原圖,第二張是處理后的圖片:

原始圖

可以看到我們在ROI的(0,0)位置開始畫矩形禀酱,但在大圖中實際效果卻不在左上角炬守,這就是設置ROI的效果。


運行結果
超出ROI的效果

我們將上面代碼改成正以下代碼剂跟,讓畫矩形區(qū)域的高度大于ROI的高度减途。

// 放大矩形的高度,讓其超出ROI的區(qū)域
cv::rectangle(roiImage, cv::Rect(0, 0, 200, 150), cv::Scalar(255, 0, 0), 10);
超出ROI操作的效果

可以看出曹洽,超出ROI的操作是被丟棄的鳍置。

二、設置ROI實現(xiàn)圖片移位

上面說過設置ROI后我們就可以只對該區(qū)域進行操作衣洁。我們練習一下將一ROI區(qū)域的數(shù)據(jù)放到另一個ROI區(qū)域墓捻。

- (UIImage *)getOpenCVImage{
    // 獲取測試用的圖片路徑
    NSString * path = [[NSBundle mainBundle] pathForResource:@"test" ofType:nil];
    // 讀取圖片
    cv::Mat testImage = cv::imread([path cStringUsingEncoding:NSUTF8StringEncoding]);
    // 設置ROI區(qū)域A
    cv::Mat roiImageA = testImage(cv::Rect(100, 100, 200, 100));
    // 設置ROI區(qū)域B
    cv::Mat roiImageB = testImage(cv::Rect(300, 30, 200, 100));
    
    // 將roiImageB數(shù)據(jù)放到roiImageA的區(qū)域以實現(xiàn)圖片區(qū)域移動效果
    roiImageB.copyTo(roiImageA);

    // 將圖片的格式從BGR轉換成RGB,如果不轉會造成顯示的圖片顏色出錯
    cv::cvtColor(testImage, testImage, cv::COLOR_BGR2RGB);
    // 將圖片轉成UIImage并返回
    return MatToUIImage(testImage);
}

代碼運行后結果:

實現(xiàn)圖片區(qū)域移動

以上是我學習后的個人總結,如有錯誤還請大神指出。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毯侦,一起剝皮案震驚了整個濱河市相寇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異羽杰,居然都是意外死亡,警方通過查閱死者的電腦和手機到推,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門考赛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人莉测,你說我怎么就攤上這事颜骤。” “怎么了捣卤?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵忍抽,是天一觀的道長八孝。 經(jīng)常有香客問我,道長鸠项,這世上最難降的妖魔是什么干跛? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮祟绊,結果婚禮上楼入,老公的妹妹穿的比我還像新娘。我一直安慰自己久免,他們只是感情好浅辙,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布扭弧。 她就那樣靜靜地躺著阎姥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鸽捻。 梳的紋絲不亂的頭發(fā)上呼巴,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天,我揣著相機與錄音御蒲,去河邊找鬼衣赶。 笑死,一個胖子當著我的面吹牛厚满,可吹牛的內(nèi)容都是我干的府瞄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼碘箍,長吁一口氣:“原來是場噩夢啊……” “哼遵馆!你這毒婦竟也來了?” 一聲冷哼從身側響起丰榴,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤货邓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后四濒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體换况,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年盗蟆,在試婚紗的時候發(fā)現(xiàn)自己被綠了戈二。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡喳资,死狀恐怖觉吭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情骨饿,我是刑警寧澤亏栈,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布台腥,位于F島的核電站,受9級特大地震影響绒北,放射性物質(zhì)發(fā)生泄漏黎侈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一闷游、第九天 我趴在偏房一處隱蔽的房頂上張望峻汉。 院中可真熱鬧,春花似錦脐往、人聲如沸休吠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘤礁。三九已至,卻和暖如春梅尤,著一層夾襖步出監(jiān)牢的瞬間柜思,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工巷燥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赡盘,地道東北人。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓缰揪,卻偏偏與公主長得像陨享,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子钝腺,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容