本文章主要对感兴趣区域ROI的操作(对于ROI区域图像叠加)说明
在图像处理的领域,我们常常需要去设置自己感兴趣的区域(ROI,region of interest),来专注或者简化工作过程。也就是从图像中选择的一个图像区域,这个区域是图像分析所关注的重点。我们圈定这个区域,以便进行下一步的处理.而且,使用ROI指定想读入的目标,可以减少处理时间,增加精度,给图像处理带来不小的便利。
利用opencv库进行编程实现对感兴趣区域ROI的操作
例如:将小图标复制到大图像的指定位置中
使用到的函数:矩形的表示:Rect类----》Rect(x,y,width,heigh)
对Rect类的解释:Rect类的成员变量有x、y、width、height,分别在左上角点的坐标和矩形的宽和高。
上述例题,第一种实现方法:在不使用图像掩码(掩膜)的情况下,通过Rect类去实现
#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat srcImage = imread("dota_pa.jpg");//读取大图像
Mat logoImage = imread("dota_logo.jpg");//读取logo图标
//判断大图像文件是否存在
if (!srcImage.data)
{
cout << "读取srcImage数据由错误~!" << endl;
return false;
}
//判断logo图标是否存在
if (!logoImage.data)
{
cout << "读取srcImage数据由错误~!" << endl;
return false;
}
//使用Rect有两种用法,实现的效果都是一样的
Mat ImageROI(srcImage,Rect(srcImage.cols - logoImage.cols, srcImage.rows - logoImage.rows, logoImage.cols, logoImage.rows));
//Mat ImageROI=srcImage(Rect(srcImage.cols - logoImage.cols, srcImage.rows - logoImage.rows, logoImage.cols, logoImage.rows));
//对上述指令的解释,对于Rect类中x=srcImage.cols- logoImage.cols;
//y = srcImage.rows - logoImage.rows;
//后面logoImage.cols, logoImage.rows为logo的总体的长跟宽(即行跟列)
//**则上述指令指出感兴趣区域ROI,**其实ROI实际上就是一个Mat对象,它与它的父图像指向同一个数据缓冲区,并且有一个头部信息表示ROI的坐标,这时候,往这个感兴趣区域里存放数据点像素(即logo图片),则会自动在大图片srcImage对应的这个感兴趣区域中生成logo图片**
**加粗样式** logoImage.copyTo(ImageROI);//将logo图标拷贝到ImageROI对象中,从而实现将小图标复制到大图像的指定位子中
imshow("效果",srcImage);//显示图像
waitKey(0);
return 0;
}
第一种实现方法:使用图像掩码(掩膜)的情况下,通过Rect类去实现
注释:掩码:掩码是一个8位图像,如果掩码中某个位置的值不为0,在这个位置上的操作就会起作用;如果掩码中某些像素位置的值为0,那么对图像中相应位置的操作将不起作用。
这一句话就是解释下面为什么在logoImage.copyTo(ImageROI,mask);
程序:
#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat srcImage = imread("dota_pa.jpg");//读取大图像
Mat logoImage = imread("dota_logo.jpg");//读取logo图标
//判断大图像文件是否存在
if (!srcImage.data)
{
cout << "读取srcImage数据由错误~!" << endl;
return false;
}
//判断logo图标是否存在
if (!logoImage.data)
{
cout << "读取srcImage数据由错误~!" << endl;
return false;
}
//使用Rect有两种用法,实现的效果都是一样的
Mat ImageROI(srcImage,Rect(srcImage.cols - logoImage.cols, srcImage.rows - logoImage.rows, logoImage.cols, logoImage.rows));
//Mat ImageROI=srcImage(Rect(srcImage.cols - logoImage.cols, srcImage.rows - logoImage.rows, logoImage.cols, logoImage.rows));
//对上述指令的解释,对于Rect类中x=srcImage.cols- logoImage.cols;
//y = srcImage.rows - logoImage.rows;
//后面logoImage.cols, logoImage.rows为logo的总体的长跟宽(即行跟列)
//则上述指令指出感兴趣区域ROI,其实ROI实际上就是一个Mat对象,它与它的父图像指向同一个数据缓冲区,并且有一个头部信息表示ROI的坐标,这时候,往这个感兴趣区域里存放数据点像素(即logo图片),则会自动在大图片srcImage对应的这个感兴趣区域中生成logo图片
Mat mask = imread("dota_logo.jpg", 0);//mask一定要转灰度,这是一定要灰度是让后面根据掩码的定义,对所有像素点操作的时候,能对ROI区域进行所有像素点操作,不会出现极个别点不去操作。
logoImage.copyTo(ImageROI,mask);//将logo图标拷贝到ImageROI对象中,从而实现将小图标复制到大图像的指定位子中
imshow("效果",srcImage);//显示图像
waitKey(0);
return 0;
}
方式三:就是把Rect类转为用Range类
就是把上述程序中Rect指令改一下
改成:ImageROI=srcImage(Range(srcImage.rows-logo.rows,srcImage.rows),Range(srcImage.cols-logo.cols,srcImage.cols;))//也就是求感兴趣区域ROI中的面积区域的长跟宽的值。
总体效果图: