目录
- 鼠标操作与响应
- 图像像素归一化
- 类型转换
- 图像放缩插值
鼠标操作与响应
static void on_draw(int event, int x, int y, int flags, void* userobj)
{Mat image = *(Mat*)userobj;if (event == EVENT_LBUTTONDOWN) {//鼠标点击时 sp.x = x;sp.y = y;std::cout << "start:" << sp << std::endl;}if (event == EVENT_LBUTTONUP) {//鼠标抬起后ap.x = x;ap.y = y;int dx = ap.x - sp.x;int dy = ap.y - sp.y;if (dx > 0 && dy > 0) {Rect box(sp.x, sp.y, dx, dy);//绘制矩形rectangle(image, box, Scalar(0,0,255), 1, 8, 0);imshow("绘制后", image);}std::cout << "end:" << sp << std::endl;}}void QuickDemo::mouse_drawing_demo(Mat& image)
{namedWindow("绘制前", WINDOW_AUTOSIZE);imshow("绘制前", image);//设置回调机制setMouseCallback("绘制前",on_draw, (void*)(&image));
}
一个屏幕上只绘制一张图像,当鼠标移动的时候自动清空屏幕
Point sp(-1, -1);
Point ap(-1, -1);
Mat tmp;static void on_draw(int event, int x, int y,int flags, void* userobj)
{Mat image = *(Mat*)userobj;if (event == EVENT_LBUTTONDOWN) {sp.x = x;sp.y = y;std::cout << "start: " << sp << std::endl;}//鼠标松开时确定结尾位置,并绘制矩形else if (event == EVENT_LBUTTONUP) {ap.x = x;ap.y = y;int dx = ap.x - sp.x;int dy = ap.y - sp.y;if (sp.x > 0 && sp.y > 0) {Rect box(sp.x, sp.y, dx, dy);rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);imshow("绘制前", image);//绘制完清空sp.x = -1;sp.y = -1;}std::cout << "end: " << ap << std::endl;}//当鼠标移动的时候会清空屏幕else if (event == EVENT_MOUSEMOVE) {tmp.copyTo(image); //清除屏幕}
}void QuickDemo::mouse_drawing_demo(Mat& image)
{namedWindow("绘制前", WINDOW_AUTOSIZE);imshow("绘制前", image);//设置回调机制setMouseCallback("绘制前",on_draw,(void *)(&image));tmp = image.clone();
}
提取图像框选中部分
Point sp(-1, -1);
Point ap(-1, -1);
Mat tmp;static void on_draw(int event, int x, int y,int flags, void* userobj)
{Mat image = *(Mat*)userobj;if (event == EVENT_LBUTTONDOWN) {sp.x = x;sp.y = y;std::cout << "start: " << sp << std::endl;}//鼠标松开时确定结尾位置,并绘制矩形else if (event == EVENT_LBUTTONUP) {ap.x = x;ap.y = y;int dx = ap.x - sp.x;int dy = ap.y - sp.y;if (sp.x > 0 && sp.y > 0) { //防止越界访问Rect box(sp.x, sp.y, dx, dy);rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);imshow("绘制前", image);if (dx > 0 && dy > 0) { //防止越界访问tmp.copyTo(image); //清楚红边框imshow("ROT截取", image(box));}sp.x = -1;sp.y = -1;std::cout << "end: " << ap << std::endl;}}//当鼠标移动的时候会清空屏幕else if (event == EVENT_MOUSEMOVE) {tmp.copyTo(image); //清除屏幕}
}void QuickDemo::mouse_drawing_demo(Mat& image)
{namedWindow("绘制前", WINDOW_AUTOSIZE);imshow("绘制前", image);//设置回调机制setMouseCallback("绘制前",on_draw,(void *)(&image));tmp = image.clone();
}
展示效果:
绘制圆形
Point p(-1, -1);
Mat tmp;
static void on_draw(int event, int x, int y ,int flags, void *userobj)
{Mat image = *(Mat*)userobj;if (event == EVENT_LBUTTONDOWN) {p.x = x;p.y = y;std::cout << "start: " << p << std::endl;}else if (event == EVENT_LBUTTONUP) {circle(image, p, 80, Scalar(0,0,255), -1);imshow("绘制前", image);}else if(event == EVENT_MOUSEMOVE){tmp.copyTo(image); //清空屏幕}
}void QuickDemo::mouse_drawing_demo(Mat& image)
{namedWindow("绘制前", WINDOW_AUTOSIZE);imshow("绘制前", image);//设置回调机制setMouseCallback("绘制前",on_draw,(void *)(&image));tmp = image.clone();
}
鼠标点击某一个点会自动画一个圆形
图像像素归一化
- opencv中提供了四种归一化的方式
- NORM_MINMAX
- NORM_INF
- NORM_L1
- NORM_L2
注:最常用的是NORM_MINMAX归一化方法
void normalize(InputArray src, //输入图像OutputArray dst, //输出图像 double alpha = 1, //NORM_MINMAX时候最低值double beta = 0, //NORM_MINMAX时候最高值 int norm_type = NORM_L2, //只有alphaint dtype = -1, //默认类型与src一致InputArray mask = noArray() //mask默认值为空)
类型转换
- CV_8UC3:3通道每个通道都是RGB 通道 ,每个通道的取值范围是[0, 255],每个通道是8位无符号字节数据类型。
- CV_32F3:3通道每个通道都是RGB 通道 ,每个通道的取值范围是[0, 4294967295],每个通道是32位浮点数数据类型。
void QuickDemo::norm_demo(Mat& image)
{Mat dst; //存储转换后的结果std::cout << image.type() << std::endl; //CV_8UC3image.convertTo(dst, CV_32FC3);std::cout << dst.type() << std::endl; //CV_32FC3
}
使用normalize函数做归一化处理需要先将CV_8UC3字节类型的图像像素转换为浮点型处理, 因为归一化处理之后的数据范围都在[0, 1]之间,需要用到浮点数保存
void QuickDemo::norm_demo(Mat& image)
{Mat dst; //存储转换后的结果std::cout << image.type() << std::endl; //CV_8UC3image.convertTo(image, CV_32FC3);std::cout << image.type() << std::endl; //CV_32FC3normalize(image, dst, 1.0, 0,NORM_MINMAX); //做归一化处理std::cout << dst.type() << std::endl;imshow("类型转换CV_32FC3之后", image);imshow("归一化处理之后", dst);
}
将CV_8UC3类型的数据转换成CV_32FC3数据类型后,可以看出图像的像素类型变了之后,与之前的差异比较大,可是做完归一化处理之后在肉眼观察基本上跟原图没有啥区别。
图像放缩插值
void QuickDemo::resize_demo(Mat& image)
{Mat zoomin, zoomout; //放大缩小对象int h = image.rows; //行int w = image.cols; //列//按照宽高进行缩小resize(image, zoomout, Size(h / 2, w / 2));imshow("缩小", zoomout);//按照宽高进行放大resize(image, zoomin, Size(h * 1.5, w * 1.5));imshow("放大", zoomin);
}
鼠标滚动事件缩小和放大窗口
原理
-
其中scale可以在外部定义为全局变量,通过响应CV_EVENT_MOUSEWHEEL滑轮事件获取Scale的具体值。
-
获取Scale值需要关注两个问题,滑轮滑动的方向和滑动量的大小。滑动方向通过getMouseWheelDelta(flags)获取,
-
当返回值>0时,表示向前滑动;
-
当返回值<0时,表示向后滑动。滑动量根据滑动方向自行设置相应的滑动步长即可。
void call_back(int event, int x, int y, int flags, void*userobj)
{Mat src = *(Mat*)userobj;Mat zoominout;int h = src.rows;int w = src.cols;//获取滚动事件if (event == cv::EVENT_MOUSEWHEEL) {//获取鼠标上下滚动时的值int Scale = getMouseWheelDelta(flags);if (Scale > 0) {Scale = Scale / 120 + 1.5; //放大1.5倍resize(src, zoominout, Size(h * Scale, w * Scale), INTER_LINEAR);}if (Scale < 0) {Scale = abs(Scale / 120) + 1; //缩小2倍resize(src, zoominout, Size(h / Scale, w / Scale), INTER_LINEAR);}imshow("触发后", zoominout);}
}void QuickDemo::mouse_resize_demo(Mat& image)
{namedWindow("鼠标触发事件", WINDOW_AUTOSIZE);setMouseCallback("鼠标触发事件", call_back, (void *)(&image));imshow("鼠标触发事件", image);
}
将鼠标悬浮在鼠标触发事件窗口上,可以使用鼠标的滚轮进行放大和缩小
createTrackbar 创建滚动条的方式调整图片大小
Mat dst, m, src;
void on_track1(int val, void *userobj)
{int h = src.rows;int w = src.cols;resize(src, dst, Size(h + val, w + val), INTER_LINEAR);imshow("调整后", dst);
}void QuickDemo::mycreateTrackbar(Mat& image) {int val = 50;dst = Mat::zeros(image.size(), image.type());m = Mat::zeros(image.size(), image.type());src = image.clone(); //深拷贝namedWindow("调整", WINDOW_AUTOSIZE);//当滚动按钮被拖动的时候,on_track函数会去调整光的亮度createTrackbar("调整", "调整", &val,200, on_track1, (void *)&image);on_track1(50, 0); //固定写法imshow("调整", image);
}