首先是关于opencv的坐标系:
Mat类:和数组一样,原点在左上,竖直为x,水平为y
bool matrix_debug()
{
uchar m[9]={0,1,2,3,4,5,6,7,8};
Mat A(3,2,CV_8UC1,m);
cout<<A<<endl;
printf("%d",A.at<uchar>(2,0));
return 1;
}
产生一个600*800的窗口
src=Mat(600,800,CV_8UC3,Scalar::all(0));
但是rect类和mat不一样,比如取上述窗口的四个角的坐标,依次为:左上(0,0)、右上(800,0),右下(800,600),左下(0,600),和mat类坐标正好相反。
rectangle函数的理解:
Mat A(600,800,CV_8UC3,Scalar(255,255,255));
int i;
for(i=1;i<4;i++)
{
Rect B(0+i*20,0,300+i*20,400);
rectangle(A,B.tl(),B.br(),Scalar(g_rng.uniform(0,256),g_rng.uniform(0,256),g_rng.uniform(0,256)));
}
imshow("2",A);
该函数可以理解为一张简单的图片,可以由无数个矩形组成,因为每次矩形平移后,都没有消除原先的矩形,而是在后面添加。
大神的源代码消化之后:
//鼠标交互全局变量
Mat src,tempImage;
Rect g_rectangle;
bool g_Drawing=0;
RNG g_rng;
void on_MouseHandle(int event,int x,int y,int flags,void* param)
{
Mat& image=*(Mat*) param;
switch(event)
{
case EVENT_MOUSEMOVE:
{
if (g_Drawing)//记录长和宽
{
g_rectangle.width=x-g_rectangle.x;//当前坐标减去鼠标左键按下时的坐标,时时更新
g_rectangle.height=y-g_rectangle.y;
}
}
break;
case EVENT_LBUTTONDOWN://左键按下
{
g_Drawing=1;
g_rectangle=Rect(x,y,0,0);//记录鼠标此时的坐标
}
break;
case EVENT_LBUTTONUP://左键抬起,画矩形
{
g_Drawing=0;
//DrawRectangle(image,g_rectangle);
//没有下一条语句,左键抬起后矩形会消失,因为没有变量传递给src,src为初始状态,再复制给temp。
rectangle(image,g_rectangle.tl(),g_rectangle.br(),Scalar(g_rng.uniform(0,256),g_rng.uniform(0,256),g_rng.uniform(0,256)));
}
break;
}
}
//鼠标交互程序
bool MouseInteraction()
{
g_rectangle=Rect(-1,-1,0,0);//TopLeft,BottomRight
src=Mat(600,800,CV_8UC3,Scalar::all(0));
//src.copyTo(tempImage);
namedWindow("2");
setMouseCallback("2",on_MouseHandle,(void*)&src);//第3个参数用于读取回调函数中的数据
while(1)
{
src.copyTo(tempImage);
if(g_Drawing)//当鼠标左键不抬起的时候总是显示矩形,闪烁表明一直在执行语句
//DrawRectangle(tempImage,g_rectangle);
rectangle(tempImage,g_rectangle.tl(),g_rectangle.br(),Scalar(g_rng.uniform(0,256),g_rng.uniform(0,256),g_rng.uniform(0,256)));
// cout<<g_rectangle.tl()<<endl;
imshow("2",tempImage);
if(waitKey(10)==27) break;
}
return 1;
}
int main()
{
if(MouseInteraction())
cout<<"success"<<endl;
waitKey(0);
return 0;
}