ROI感兴趣区的提取方法
使用line,ellipse,ellipse,rectangle,fillPoly等函数绘制线、矩形、圆、椭圆等基本图形提取感兴趣区域
ROI感兴趣区的提取方法——鼠标操作提取方法
我们通过鼠标交互地提取ROI。OpenCV中鼠标操作依赖鼠标的回调函数和响应函数实现。主函数中调用鼠标的回调函数,将鼠标操作与程序的窗口绑定,产生鼠标操作时回调函数调用鼠标响应函数执行。
回调函数setMouseCallback
void setMouseCallback( const string& winname,
MouseCallback onMouse,
void* userdata=0 )
Parameters:
第一个参数winname,windows视窗名称,对名为winname的视窗进行鼠标监控;
第二个参数onMouse,鼠标响应处理函数,监听鼠标的点击,移动,松开,判断鼠标的操作类型,并进行响应的函数处理;
第三个参数 userdata,鼠标响应处理函数的ID,与鼠标相应处理函数相匹配就行,暂时只用到默认为0的情况。
鼠标响应处理函数onMouse
OpenCV中,鼠标相应处理函数一般默认形参和返回参数。
void onMouse(int event,int x,int y,int flags,void *ustc)
Parameters:
第一个参数event,鼠标操作时间的整数代号,在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,代表鼠标位于窗口的(x,y)坐标位置,窗口左上角默认为原点,向右为x轴,向下为y轴;
第三个参数y,代表鼠标的拖拽事件,以及键盘鼠标联合事件,总共有32种事件,这里不再赘述。
第四个参数flags,函数参数的编号。
=========================================================================
#include"stdafx.h"
#include
#include
#include
#include
using namespace cv;
using namespace std;
Point startp(-1, -1);
Point endp(-1, -1);
//绘制圆,需要中心坐标和半径
Point centerp(-1, -1);
int radius = 0;
Mat temp;
void MouseDraw(int event, int x, int y, int flag, void* usedata) {
Mat image = *((Mat*)usedata);
Mat roi;
if (event == EVENT_LBUTTONDOWN) {//左键按下
centerp.x = x;
centerp.y = y;
cout << "center point: " << centerp << endl;
}
else if (event == EVENT_MOUSEMOVE) {//鼠标移动
if ((centerp.x > 0 )& (centerp.y > 0)) {
//得有这个判断条件,不然一开始 不按下鼠标左键时就已经有起始点了
endp.x = x;
endp.y = y;
int w = endp.x - centerp.x;
int h = endp.y - centerp.y;
radius = (int)sqrt(pow(w, 2) + pow(h, 2));
temp.copyTo(image);
//矩形可利用rectangle来实现
circle(image, centerp, radius, Scalar(0, 0, 255), 2);
namedWindow("mousedrawing", 0);
resizeWindow("mousedrawing", 350, 350);
imshow("mousedrawing", image);
}
}
else if (event == EVENT_LBUTTONUP) {//左键抬起
endp.x = x;
endp.y = y;
int w = endp.x - centerp.x;
int h = endp.y - centerp.y;
radius = (int)sqrt(pow(w, 2) + pow(h, 2));
circle(image, centerp, radius, Scalar(0, 0, 255), 2);
namedWindow("mousedrawing", 0);
resizeWindow("mousedrawing", 350, 350);
imshow("mousedrawing", image);
//截取该部分图像
//先截取矩形的部分,再用模取出圆形
Rect rec;
rec.x = centerp.x - radius;
rec.y = centerp.y - radius;
rec.width = 2 * radius;
rec.height = 2 * radius;
Mat Rec_roi = image(rec);//矩形的ROI区域
Mat roi = Mat::zeros(Rec_roi.size(), Rec_roi.type());
roi = Scalar(255, 255, 255);//将目标ROI背景置白
//利用mask提取圆形的ROI
Mat mask = Mat::zeros(Rec_roi.size(), Rec_roi.type());
circle(mask, Point(radius, radius), radius, Scalar(255, 255, 255), -1);
cvtColor(mask, mask, COLOR_BGR2GRAY);
namedWindow("mask", 0);
resizeWindow("mask", 350, 350);
imshow("mask", mask);
Rec_roi.copyTo(roi, mask);
namedWindow("ROI", 0);
resizeWindow("ROI", 350, 350);
imshow("ROI", roi);
//清空中心坐标,这样才会停止掉这一次的绘制
centerp.x = -1;
centerp.y = -1;
}
}
int main(int argc, char*argv) {
Mat image = imread("F:/photo/c.jpg",-1);
namedWindow("mousedrawing",0);
setMouseCallback("mousedrawing", MouseDraw, &image);
resizeWindow("mousedrawing", 350, 350);
imshow("mousedrawing", image);
temp = image.clone();
waitKey(0);
destroyAllWindows();
return 0;
}
=========================================================================