学习opencv day2
今天是系统学习opencv的第二天
使用工具为opencv4.4.0+vs2019
并已使用cmake配置contrib
参考书目为《opencv计算机视觉编程攻略》+《学习opencv3》
一、day1程序实现原理
1、类和函数的定义
在OpenCV的C++ API中,所有类和函数都在命名空间cv内定义。访问他们的方法有两种。第一种是在定义main函数钱使用如下声明:
using namespace cv;
第二种是根据命名空间规范给所有OpenCV的类和函数加上前缀cv::,接下来学习主要采用此种方法,添加前缀后,代码中OpenCV的类和函数将更容易识别。
2、cv::flip函数
前程序中同时使用了输入和输出图像,可以改成就地处理的方式,即不定义输出图像而直接写入原图像:
cv::flip(image,image,1); //就地处理
扩展阅读
highgui模块中有大量可用来处理图像的函数,他们可以使用程序对鼠标或键盘事件作出响应,也可以在图像上回执形状或写入文本。
1、在图像上点击
采用回调函数的形式,回调函数不会被显式地调用,但是会在响应特定事件(这里是指有关鼠标与 图像窗口交互的事件)的时候被程序调用。为了能被程序识别,回调函数需要具有特定的签名, 并且必须注册。对于鼠标事件处理函数,回调函数必须具有这种签名:
void onMouse( int event, int x, int y, int flags, void* param);
Event是整数,表示出发会点函数的鼠标事件的类型。
X 和 Y为事件发生时鼠标的坐标,用像素坐标表示。
flags表示事件发生的时候按下鼠标的那个键。
param是指向任意对象的指针,作为附件的参数发送给函数。
你可用下面的方法在程序中注册回调函数:
cv::setMouseCallback("Original Image", onMouse,reinterpret_cast<void*>(&image));
原型如下:
void setMousecallback(const string& winname, MouseCallback onMouse, void* userdata=0);
winname:窗口名称
onMouse:鼠标事件的回调函数。指定窗口里每次鼠标时间发生的时候被调用的函数指针。
userdate:传递给回调的可选参数。
鼠标事件
EVENT_MOUSEMOVE 滑动
EVENT_LBUTTONDOWN 左键点击
EVENT_RBUTTONDOWN 右键点击
EVENT_MBUTTONDOWN 中键点击
EVENT_LBUTTONUP 左键放开
EVENT_RBUTTONUP 右键放开
EVENT_MBUTTONUP 中键放开
EVENT_LBUTTONDBLCLK 左键双击
EVENT_RBUTTONDBLCLK 右键双击
EVENT_MBUTTONDBLCLK 中键双击
在本例中,函数 onMouse 与名为 Original Image(原始图像)的图像窗口建立了关联,同时把所显示图像的地址作为附加参数传给函数。现在,只要用下面的代码定义回调函数 onMouse,每当遇到鼠标点击事件时,控制台就会显示对应像素的值(这里假定它是灰度图像):
void onMouse( int event, int x, int y, int flags, void* param) {
cv::Mat *im= reinterpret_cast<cv::Mat*>(param);
switch (event) { // 调度事件
case CV::EVENT_LBUTTONDOWN: // 鼠标左键按下事件
// 显示像素值(x,y)
std::cout << "at (" << x << "," << y << ") value is: "
<< static_cast<int>(
im->at<uchar>(cv::Point(x,y))) << std::endl;
break;
}
}
这里用 cv::Mat 对象的 at 方法来获取(x, y)的像素值:
适用于取具体第i行,第j列的像素,不适用于遍历像素im->at<uchar>(i,j); //取灰度图像中第i行第j列的点 im->at<Vec3b>(i,j)[K] //取彩色图像中第i行第j列第K通道的点
2、在图像上绘图
OpenCV 还提供了几个用于在图像上绘制形状和写入文本的函数。基本的形状绘制函数有circle、ellipse、line 和 rectangle。在 OpenCV 的方法和函数中,我们经常用 cv::Point 结构来表示像素的坐标。这里假定是在灰度图像上进行绘制的,因此用单个整数来表示颜色。
cv::circle(image, // 目标图像
cv::Point(155,110), // 中心点坐标
65, // 半径
0, // 颜色(这里用黑色)
3); // 厚度
在图像上写入文本:
cv::putText(image, // 目标图像
"This is a dog.", // 文本
cv::Point(40,200), // 文本位置
cv::FONT_HERSHEY_PLAIN, // 字体类型
2.0, // 字体大小
255, // 字体颜色(这里用白色)
2); // 文本厚度
注意:需加上顶层模块头文件 opencv2/imgproc.hpp
二、cv::Mat数据结构
cv::Mat ima(500, 500, CV_8U, 50); //500为尺寸,cv_8u表示8位无符号整数(灰度图像),50为灰度值或者颜色
//也可写作 cv::Mat image1(240,320,CV_8U,cv::Scalar(100));
// 所有这些图像都指向同一个数据块
cv::Mat image4(image3);
image1 = image3;
// 这些图像是源图像的副本图像
image3.copyTo(image2);
cv::Mat image5 = image3.clone();
1、image.copyTo(image),作用是把image的内容粘贴到image中;
2、image.copyTo(image,mask),作用是把mask和image重叠以后把mask中像素值为0(black)的点对应的image中的点变为透明,而保留其他点[1]。
可以随时用 create 方法分配或重新分配图像的数据块。如果图像已被分配,其原来的内容
会先被释放。出于对性能的考虑,如果新的尺寸和类型与原来的相同,就不会重新分配内存:
// 重新分配一个新图像
//(仅在大小或类型不同时)
image.create(200,200,CV_8U);
[1] https://blog.csdn.net/dxrose/article/details/89158387