mat opencv 修改roi_设置图片ROI(OpenCV学习笔记之二)
ROI相關簡介
ROI是什么
ROI是region of interest首字母的簡寫,翻譯為感性趣的區域。其實在寫本篇之前應該寫一篇關于圖片是什么的學習筆記,但又感覺里面沒多少東西還不能承載一篇學習筆記,所以這里只簡單提一下。
圖片是什么
其實大家也應該能猜到圖片就是一個二維數組,只不過這個二維數組有點特殊,它有頭信息,在頭信息里會有描述這個二維數組的大小、圖片類型和數組元素的數據類型等。下面是一張從官方教程里獲取的一張輔助理解的圖片。
圖片就是一個二維數組
上面的圖片只是一張灰色的圖片而我們經常用的圖片彩色的圖片,在灰圖片中一個像素我們用一個值就可以表示了,但在彩色的圖片中一個像素要用3個值或4個值(有的圖片有alpha通道)來表示。下面就是一個由三個值表示一個像素的輔助理解圖。
BGR格式的圖片
這張圖片是從官網獲取的。是不是覺得顏色的排序有點不對呀,我們想的應該是紅在前才對,其實在OpenCV中很多圖片都是BGR格式的和我們常見的到RGB格式的存儲方式是相反的。具體為什么要用BGR格式還不清楚如有大神知道還請科普。其他圖片的格式有很多種如,HVS、CyCbCr、HSI等格式,后續可能會專門寫一篇關于圖片格式的學習筆記,這里先對圖片格式的介紹寫這么多。
為什么要設置ROI
上面我已經介紹過圖片是一個二維數組,而我們有時處理圖片的時候只對其中的一部分圖片的區域進行處理,例如我們想在圖片某個區域打馬賽克,為了性能考慮我們可以只讓程序對這一部分信息進行處理而將其他部分忽略,這時我們就要設置圖片感性趣的區域。設置完感性趣的區域后其實是指針指到了ROI區域的左上角,好像我們截取了一張小圖片一樣,我們只對這張小圖片進行處理就可以了,因其ROI指向的還是原圖只在告訴它圖片的起始位置和大小變了,所以在對ROI區操作會影響原圖。
設置ROI
在OpenCV中有C和C++的代碼,最早OpenCV是用C寫的,在開發中C的代碼寫起來不太方便在版本進入2.0之后后續加入的代碼改用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其實就是在原來圖片上指定一個區域,而這個區域只是新創建了一個圖片文件的頭信息而已并沒有產生新的圖片,文件頭里的圖片區域的起始位置指向了ROI區域的左上角位置,所以在ROI上做的任何操作都會影響原圖片。
C
- (void)setImageROI:(IplImage *)image{
// 記錄圖片的大小和區域
CvRect currentRect = cvGetImageROI(image);
// 設置ROI區域
cvSetImageROI(image, cvRect(100, 100, 200, 100));
// 畫一個矩形
cvRectangleR(image, cvRect(0, 0, 200, 100), CvScalar(255, 0, 0), 10);
// 還原ROI區域
cvSetImageROI(image, currentRect);
// 上面的還原ROI區域要一個臨時變量,也可通過下面的方法,還原ROI區域而不用創建臨時變量
//cvResetImageROI(image);
}
對于C的代碼沒有生成一個文件頭信息而是修改原來的文件頭信息,所以要把文件頭信息改回去。現在是不是覺得C++比C簡單多了。
代碼實戰
一、設置ROI并畫矩形
以下代碼是核心代碼,其他簡單的顯示代碼將不再列出。首先請導入以下頭文件。
#import
#import
#import
然后下面是具體的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區域做操作,畫一個矩形
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的效果
我們將上面代碼改成正以下代碼,讓畫矩形區域的高度大于ROI的高度。
// 放大矩形的高度,讓其超出ROI的區域
cv::rectangle(roiImage, cv::Rect(0, 0, 200, 150), cv::Scalar(255, 0, 0), 10);
超出ROI操作的效果
可以看出,超出ROI的操作是被丟棄的。
二、設置ROI實現圖片移位
上面說過設置ROI后我們就可以只對該區域進行操作。我們練習一下將一ROI區域的數據放到另一個ROI區域。
- (UIImage *)getOpenCVImage{
// 獲取測試用的圖片路徑
NSString * path = [[NSBundle mainBundle] pathForResource:@"test" ofType:nil];
// 讀取圖片
cv::Mat testImage = cv::imread([path cStringUsingEncoding:NSUTF8StringEncoding]);
// 設置ROI區域A
cv::Mat roiImageA = testImage(cv::Rect(100, 100, 200, 100));
// 設置ROI區域B
cv::Mat roiImageB = testImage(cv::Rect(300, 30, 200, 100));
// 將roiImageB數據放到roiImageA的區域以實現圖片區域移動效果
roiImageB.copyTo(roiImageA);
// 將圖片的格式從BGR轉換成RGB,如果不轉會造成顯示的圖片顏色出錯
cv::cvtColor(testImage, testImage, cv::COLOR_BGR2RGB);
// 將圖片轉成UIImage并返回
return MatToUIImage(testImage);
}
代碼運行后結果:
實現圖片區域移動
以上是我學習后的個人總結,如有錯誤還請大神指出。
總結
以上是生活随笔為你收集整理的mat opencv 修改roi_设置图片ROI(OpenCV学习笔记之二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 22元可买入一个豆瓣账号进行评论!专家:
- 下一篇: 马斯克:自称美国纳税第一人 超过历史上任