视觉图像:OpenCV感兴趣区域ROI
1、定义ROI区域的两种方法:
①指定矩形坐标,并规定好长宽;
Mat img = imread("1.jpg");
Mat roi = img(Rect(500, 200, 100, 300));
//Rect四个形参分别是:x坐标,y坐标,长,高;注(x,y)指矩形的左上角点;
②指定感兴趣行或列的范围(Range),Range是指从起始索引到终止索引的一段联系序列:
Mat img = imread("1.jpg");
Mat roi = img(Range(250, 250 +xleng), Range(200, 200 + yleng));
//Range两个形参分别是:起始行或列,起始行或列+偏移量
示例:
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat srcImage = imread("test.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;
}

2、有时,不仅要把ROI标记出来,还要把ROI提取出来,成为一幅单独图片;
示例如下:
int main()
{
Mat img1 = imread("0.jpg", 1);
Mat img2(img1.rows, img1.cols, CV_8UC3);
//设置感兴趣区域,拷贝
img1(Rect(200, 100, 150, 100)).copyTo(img2);
//或
//Mat roi = img1(Rect(200, 100, 150, 100));
//imshow("roi",roi);
imshow("img1", img1);
imshow("img2", img2);
waitKey(0);
}

3、图像上添加logo:
两种方法:
①:首先定义ROI区域,然后进行线性叠加,使用addWeighted();
线性混合操作是一种典型的二元像素操作,理论公式如下:
g(x)=(1-a)f1(x)+af2(x);
a:0~1;改变两幅图像混合效果;
int main()
{
Mat srcImage = imread("0.jpg");
if (!srcImage.data) {
cout << "读取原始图失败!" << endl;
return -1;
}
namedWindow("srcImage", WINDOW_NORMAL);//WINDOW_NORMAL允许用户自由伸缩窗口
imshow("srcImage", srcImage);
Mat logo = imread("1.jpg");
if (!logo.data)
{
cout << "读取原始logo图失败!" << endl;
return -1;
}
Mat imageROI = srcImage(Rect(120, 50, logo.cols, logo.rows)); //从原图中抠出矩形区域,Rect第一二参数表示矩形左上角定点的坐标,用于定位,后两个参数表示举行的宽和高
imshow("ROI", imageROI);
addWeighted(imageROI, 0.65, logo, 0.35, 0., imageROI);//dst = src1[I]*alpha+ src2[I]*beta + gamma;第5参数就是偏执因子gamma。
namedWindow("原图加logo", WINDOW_NORMAL);
imshow("原图加logo", srcImage);
waitKey();
return 0;
}


4、②方法二:定义ROI区域,使用copyTo实现直接拷贝覆盖
int main()
{
Mat srcImage = imread("0.jpg");
if (!srcImage.data)
{
cout << "读取原始图失败!" << endl;
return -1;
}
namedWindow("srcImage", WINDOW_NORMAL);
imshow("srcImage", srcImage);
Mat logo = imread("3.jpg");
Mat mask = imread("3.jpg",0); // 加载掩模(必须是灰度图)
if (!logo.data)
{
cout << "读取原始logo图失败!" << endl;
return -1;
}
Mat imageROI = srcImage(Rect(205, 10, logo.cols, logo.rows)); //从原图中抠出矩形区域,Rect第一二参数表示矩形左上角定点的坐标,用于定位,后两个参数表示举行的宽和高
imshow("ROI", imageROI);
logo.copyTo(imageROI,mask);//注意两个参数,一个是ROI,一个是掩模
namedWindow("原图加logo", WINDOW_NORMAL);
imshow("原图加logo", srcImage);
waitKey();
return 0;
}

5、利用鼠标交互提取ROI;
主函数中调用鼠标的回调函数,将鼠标操作与程序的窗口绑定,产生鼠标操作时回调函数调用鼠标响应函数执行;
回调函数setMouseCallback():
形式:
void setMouseCallback(const string& winname,
MouseCallback onMouse,
void* userdata=0 )
参数:
第一个参数,windows视窗名称,对名为winname的视窗进行鼠标监控;
第二个参数,鼠标响应处理函数,监听鼠标的点击,移动,松开,判断鼠标的操作类型,并进行响应的函数处理;
第三个参数,鼠标响应处理函数的ID,与鼠标相应处理函数相匹配就行,暂时只用到默认为0的情况。
鼠标响应处理函数onMouse():
OpenCV中,鼠标相应处理函数一般默认形参和返回参数。
格式:
void onMouse(int event,int x,int y,int flags,void *ustc)
第一个参数,鼠标操作时间的整数代号,在opencv中,event鼠标事件总共有10中,从0-9依次代表如下:
EVENT_MOUSEMOVE =0, //滑动
EVENT_LBUTTONDOWN =1, //左键点击
EVENT_RBUTTONDOWN =2, //右键点击
EVENT_MBUTTONDOWN =3, //中间点击
EVENT_LBUTTONUP =4, //左键释放
EVENT_RBUTTONUP =5, //右键释放
EVENT_MBUTTONUP =6, //中间释放
EVENT_LBUTTONDBLCLK =7, //左键双击
EVENT_RBUTTONDBLCLK =8, //右键双击
EVENT_MBUTTONDBLCLK =9 //中间释放
第二个参数,代表鼠标位于窗口的(x,y)坐标位置,窗口左上角默认为原点,向右为x轴,向下为y轴;
第三个参数,代表鼠标的拖拽事件,以及键盘鼠标联合事件,总共有32种事件,这里不再赘述。
第四个参数,函数参数的编号。

6、图像感兴趣区域剪切:
①将需要剪切的图像图像不部分设置为ROI
cvSetImageROI(src , cvRect(x,y,width,height));
②新建一个与需要剪切的图像部分同样大小的新图像
cvCreateImage(cvSize(width,height),IPL_DEPTH,nchannels);
③将源图像复制到新建的图像中
cvCopy(src,dst,0);
④释放ROI区域
cvResetIamgeROI(src);
示例:
#include "stdafx.h"
#include <opencv2\opencv.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\features2d\features2d.hpp>
#include <opencv2\core\core.hpp>
using namespace std;
using namespace cv;
IplImage* src;
IplImage* dst;
int main(int argc , char** argv )
{
src = cvLoadImage("0.jpg",1);
cvNamedWindow("源图像",1);
cvShowImage("源图像",src);
cvSetImageROI(src,cvRect(0,0,0.5*src->width,0.5*src->height));
dst = cvCreateImage(cvSize(0.5*src->width,0.5*src->height), IPL_DEPTH_8U,src->nChannels);
cvCopy(src,dst,0);
cvResetImageROI(src);
cvNamedWindow("操作后的图像",1);
cvShowImage("操作后的图像",dst);
cvWaitKey(0);
cvDestroyWindow("操作后的图像");
cvDestroyWindow("源图像");
cvReleaseImage(&src);
cvReleaseImage(&dst);
return 0;
}
