这里介绍opencv基本绘图工具,包括直线line(),圆形circle(),矩形recangle(),椭圆ellipse(),多边形fillPoly(),添加文字putText()等,然后后面还有opencv鼠标操作的一些方法,详见示例代码:
1.基本绘图工具:
void drawTool()//1.基本绘图工具
{
Mat img(600, 600, CV_8UC3, Scalar(0, 0, 0));
//画线
line(img, Point(10, 10), Point(10, 200), Scalar(0, 255, 255),//黄色
10,//线宽
8); //线型
//画圆
circle(img, Point(120, 200), 100, Scalar(255, 255, 0),//青色
-1, //线宽为-1,向内填充
8);
//画矩形
rectangle( img, Point(400, 100), //左上点
Point(240, 200),//右下点
Scalar(0, 0, 255), 2, 8
);
rectangle( img,
Rect(150, 500,//左上坐标
100, 150),//宽高
Scalar(0, 0, 255), -1, 8); //线宽为-1,向内填充
//画椭圆
ellipse(img, Point(500, 300), Size(100, 50), //size类型,长轴和短轴
45,//旋转角度
0,//起始角度
360, Scalar(0, 255, 255), -1, 8);
ellipse(img, RotatedRect(Point(400, 150),//旋转矩形的中心坐标
Size(100, 50),//旋转矩形的大小
0), //旋转矩形的角度
Scalar(0,255,0), 2, 8);//颜色线宽
//画多边形
//定义Point类型数组,按顺序存放六边形的点,其实就多条line连接
Point ppt[] = {Point(120, 50), Point(180, 50), Point(210, 100), Point(180, 150), Point(120, 150), Point(90, 100)};
const Point* pts[] = {ppt};//ppt类型为Point*,pts类型为Point**,需定义成const类型
int npt[] ={6}; //npt的类型即为int*
//填充多边形
fillPoly(img, pts, npt, 1,//绘制多边形的个数,1个
Scalar(0, 255, 255), 8); //画填充多边形
//非填充多边形
polylines(img, pts, npt, 1, true, //是否闭合,改为false则不闭合
Scalar(0, 154, 209), 2, //它不能改为-1来进行填充
8);
//添加文字
putText(img, "opencv", Point(10, 400),//起始点
CV_FONT_HERSHEY_COMPLEX, //字体
2, //字体大小
Scalar(0, 255, 255), 2, 8);
imshow("img", img); //显示图片
waitKey(0);
}
效果如下:
2.鼠标点击绘制圆形(下面两个函数要加载到main前声明):
////////////2鼠标点击基本绘图工具
void OnMouse(int event, int x, int y, int flags, void* param) //10.鼠标绘图
{
Mat img = *(Mat*)param;
if(event == CV_EVENT_LBUTTONDOWN)
{
cout<<"Mouse down"<<endl;
circle(img, Point(x, y), 20, Scalar(0, 255, 0), 2, 8);
}
}
void drawTool2()//.基本绘图工具
{
Mat img(500, 500, CV_8UC3, Scalar(255, 255, 255));
namedWindow("Mouse", CV_WINDOW_AUTOSIZE);
setMouseCallback("Mouse", OnMouse, &img);
while(1) //为了不断循环地imshow(),使图像刷新.
{
imshow("Mouse", img);
if(27==waitKey(10)) //按下Esc跳出
break; }
}
效果如下:
3.鼠标绘制矩形,下面这个代码绘制时候鼠标起点和末尾点结束后才会显示所画矩形:
void drawTool3()//3.基本绘图工具-矩形
{
Mat img(500, 500, CV_8UC3, Scalar(255, 255, 255));
namedWindow("Mouse", CV_WINDOW_AUTOSIZE);
setMouseCallback("Mouse", OnMouse2, &img);
while(1) //为了不断imshow(),使图像刷新
{
imshow("Mouse", img);
if(27==waitKey(10)) //按下Esc跳出
break; }
}
void OnMouse2(int event, int x, int y, int flags, void* param) //11.鼠标事件
{
Mat img = *(Mat*)param;
switch(event)
{ case CV_EVENT_LBUTTONDOWN:
pt.x = x;
pt.y = y;
break;
case CV_EVENT_LBUTTONUP:
rectangle(img, pt, Point(x, y), Scalar(0, 0, 255), 2, 8);
break;
default:
break;}
}
效果如下:
4.绘制矩形,改进上面的代码,使得鼠标绘制时一直可以看到矩形大小,效果同上:
void drawTool4()//4.基本绘图工具,双缓冲绘画
{
Mat img5(500, 500, CV_8UC3, Scalar(255, 255, 255));
img4=img5.clone();
namedWindow("Mouse", CV_WINDOW_AUTOSIZE);
setMouseCallback("Mouse", OnMouse4, &img4);
while(1) //为了不断imshow(),使图像刷新
{
imshow("Mouse", img4);
if(27==waitKey(10)) //按下Esc跳出
break;}
}
void OnMouse4(int event, int x, int y, int flags, void* param) //11.鼠标事件
{
// Mat img4 = *(Mat*)param;
switch(event)
{
case CV_EVENT_LBUTTONDOWN:
flag = true;//flag标记置为真,触发鼠标移动画矩形
pt4.x = x;
pt4.y = y;
break;
case CV_EVENT_MOUSEMOVE: //鼠标移动
//cout<<"mouse move"<<endl;
if(flag)
{
temp4=img4.clone();
rectangle(temp4, pt4, Point(x, y), Scalar(0, 0,255), 2, 8);//画矩形
imshow("Mouse", temp4);
}
break;
case CV_EVENT_LBUTTONUP:
rectangle(img4, pt4, Point(x, y), Scalar(0, 0, 255), 2, 8);
imshow("Mouse", img4);
flag = false;//flag标记置为假,关闭鼠标移动画矩形
break;
default:
break;
}
}
5.用鼠标绘制矩形选择感兴趣的ROI区域:
Mat img_mouse = imread("D:/2.jpg",CV_LOAD_IMAGE_COLOR);
Mat temp = img_mouse.clone(); //Mat类型变量temp深拷贝原图
Mat ROI;//设置感兴趣区域ROI
Point pt2;//记录鼠标左键按下时的坐标
bool flag = false;////flag用来标记鼠标移动是否画矩形
//上面的全局变量要提前加载
void drawROI()//鼠标选ROI
{
namedWindow("Mouse", CV_WINDOW_AUTOSIZE);
setMouseCallback("Mouse", OnMouse3, 0); //设置鼠标回调函数
while(1)
{
imshow("Mouse", img_mouse); //每10ms刷新一次图像,不在onMouse()里显示图像,因为太快会有拖动重影
if(27 == waitKey(10)) //Esc跳出循环
break;
}
}
void OnMouse3(int event, int x, int y, int flags, void* param)
{
switch(event)
{
case CV_EVENT_LBUTTONDOWN: //鼠标左键按下
//cout<<"left button down"<<endl;
flag = true;//flag标记置为真,触发鼠标移动画矩形
pt2.x = x; //记录当前点坐标
pt2.y = y;
break;
case CV_EVENT_MOUSEMOVE: //鼠标移动
//cout<<"mouse move"<<endl;
if(flag)
{
temp.copyTo(img_mouse);//通过temp将img更新为原图
rectangle(img_mouse, pt2, Point(x, y), Scalar(0, 255, 0), 2, 8);//画矩形
}
break;
case CV_EVENT_LBUTTONUP: //鼠标左键弹起
//cout<<"left button up"<<endl;
flag = false;//flag标记置为假,关闭鼠标移动画矩形
ROI = temp(Rect(pt2.x, pt2.y, x-pt2.x, y-pt2.y)); //确定ROI区域
imshow("ROI", ROI); //显示ROI
imwrite("ROI.bmp", ROI);//保存ROI
break;
default:
break;
}
}
效果如下: