设置图片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 <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区域做操作,画一个矩形
    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);
}

代码运行后结果:

实现图片区域移动

以上是我学习后的个人总结,如有错误还请大神指出。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容