本文共 4952 字,大约阅读时间需要 16 分钟。
作为一开始接触opencv的小伙伴们,自然要先搞清楚opencv的框架了,我们就从他的模块框架来了解一下好了。
首先,最总的,就是incluce
这个头文件了,他包含了opencv所有的模块的头文件,理论上我们写opencv程序,就包含一个这个头文件就万事大吉了,但这样会极大的降低我们程序的编译速度,因此我们还是希望可以了解各个模块的头文件,写程序是仅包含用到的头文件。
include
core模块包含了新式C++风格的结构和数学运算
include
imgproc模块包含了C++风格的图像处理函数
include
此头文件包含了最近邻搜索匹配函数
include
video模块包含了视觉追踪以及背景分割
include
用于追踪的二维特征
include
级联人脸分类器,latent SVM分类器,HoG特征和平面检测器
include
校准以及双目视觉相关
include
机器学习,聚类,以及模式识别相关
include
新式C++风格的显示,滑动条,鼠标操作以及输入输出相关
include
用户贡献的代码,皮肤检测,模糊Mean-Shift追踪,spin image算法及自相似特征
我们看了上面的介绍,自然知道,显示,读取图片这些操作,自然是在highgui模块中了。下面写程序:
#include "pch.h"#include#include using namespace std;using namespace cv;int main(){ Mat img = imread("1.jpg"); if (img.empty()) { printf("没有找到照片!"); return -1; } namedWindow("example1", WINDOW_AUTOSIZE); imshow("example1", img); waitKey(); return 0;}
我们来逐行分析这个程序,
第一行: Mat img = imread(“1.jpg”); 定义了一个Mat图像类型img来接收读取的图片,用到函数imread(const string& filename, int flags = 1);
该函数第一个参数为图片路径名,如果图片在此工程目录下,则只需要写图片名“1.jpg”,
第二个参数为表示符,默认为1,将图像转换为彩色再返回,若为0,则转换为灰度图再返回。 第二行:if (img.empty()) { printf("没有找到照片!"); return -1; }
此代码段为判断读取图片是否存在。
第三行:namedWindow("example1", WINDOW_AUTOSIZE);
运用namedWindow()函数创建一个名为example1的窗口,用来存储图像。第二个参数为标识符。
- WINDOW_NORMAL 用户可以随意改变窗口大小 - WINDOW_AUTOSIZE 窗口可根据突变大小自行调整,用户不可随意改变 - WINDOW_OPENGL 窗口创建时会支持OpenGL
第四行:
imshow("example1", img);
该代码将图片img显示于窗口example1中。
第五行:waitKey();
代码可以防止程序运行窗口闪退,waitKey()括号内,如果为0或空,则程序会暂停等待键盘事件,如果大于0,则会等待相同时长的毫秒时间。
运行结果:#include "pch.h"#include#include #include using namespace std;using namespace cv;int main(){ namedWindow("Example2", WINDOW_AUTOSIZE); VideoCapture cap; cap.open("1.mp4"); Mat frame; while(1) { cap >> frame; if (frame.empty()) break; imshow("Example2", frame); waitKey(30); } return 0;}
首先,我们使用VideoCapture cap;定义了一个视频对象,使用该对象的成员函数open()来打开工程目录下的一段程序。
Mat frame;定义了一个Mat类型的图像frame来存储每一帧。 if (frame.empty()) break;用来检测读取帧是否为空,若为空,即视频播放完毕。 imshow(“Example2”, frame);用来显示该视频帧 waitKey(30); 用来延时30mm如果我们想让视频完成跳转,则需要添加一个滑动条,程序中多处用到了cap.set()函数,该函数经常与cap.get()函数配合使用/
#include "pch.h"#include#include #include //按下S键来执行单步模式,按下R恢复视频连续播放using namespace std;using namespace cv;int g_slider_position = 0; //定义视频位置变量int g_run = 1, g_dontset = 0; //设置视频模式标志位VideoCapture cap;void on_TrackbarSlide(int pos, void*) //滑动条响应函数{ cap.set(CAP_PROP_POS_FRAMES, pos); //设置帧 if (!g_dontset) g_run = 1; g_dontset = 0;}
首先创建了一些全局变量和回调函数,回调函数内设置了帧的跳转和一些标志位的置换
int main(){ namedWindow("Example3", WINDOW_AUTOSIZE); cap.open("1.mp4"); int frames = (int)cap.get(CAP_PROP_FRAME_COUNT); //帧数 int tmpw = (int)cap.get(CAP_PROP_FRAME_WIDTH); //宽 int tmph = (int)cap.get(CAP_PROP_FRAME_HEIGHT); //高 cout << "Video has " << frames << "frames of dimensions( " << tmpw << " ," << tmph << " )." << endl;
然后是主函数,创建了一个窗口来显示视频,定义了帧数,视频宽度,高度。
createTrackbar("Position", "Example3", &g_slider_position, frames, on_TrackbarSlide);
创建了一个滑动条函数,该函数原型和用法如下:
/*int createTrackbar( conststring& trackbarname, #轨迹条名称 conststring& winname, #窗口名称 int* value, #指向整型的指针,表示当前滑块的位置 int count, #最大位置 TrackbarCallback onChange = 0, //回调函数,每次滑块改变位置时,这个函数就会回调 void* userdata = 0 );
*/
Mat frame; while(1) { if (g_run != 0) { //运行单步模式 cap >> frame; if(frame.empty()) break; int current_pos = (int)cap.get(CAP_PROP_POS_FRAMES); //获取的帧索引 g_dontset = 1; setTrackbarPos("Position", "Example3", current_pos); //使进度条跟着视频运 imshow("Example3", frame); g_run -= 1; } char c = (char)waitKey(10); if (c == 's'){ g_run = 1; cout << "Single step, run = " << g_run << endl; } if (c == 'r'){ g_run = -1; cout << "Run mode ,run = " << g_run << endl; } if (c == 27) break; } return 0;}
最后是视频的显示,其中用到了一个setTrackbarPos()函数,该函数用法如下:
设置trackbar位置void setTrackbarPos( const char& trackbar_name, //trackbar 的名字 const char* window_name, //trackbar 父窗口的名字 int pos //新的位置 );
#include "pch.h"#include#include using namespace std;using namespace cv;int main(){ Mat img = imread("1.jpg"); int x = 32, y = 64; //第一种访问方式 cout << "第一种方法:" << endl; Vec3b intensity = img.at (y, x); uchar blue = intensity[0]; uchar green = intensity[1]; uchar red = intensity[2]; cout << "At (x,y)=(" << x << "," << y << "):(blue,green,red)=(" << (unsigned int)blue << ',' << (unsigned int)green << ',' << (unsigned int)red << ")" << endl; //第二种访问方式 cout << "第二种方法:" << endl; blue = img.at (y, x)[0]; green = img.at (y, x)[1]; red = img.at (y, x)[2]; cout << "At (x,y)=(" << x << "," << y << "):(blue,green,red)=(" << (unsigned int)blue << ',' << (unsigned int)green << ',' << (unsigned int)red << ")" << endl; waitKey(); return 0;}
这儿有两种访问像素点的方法,两种方法是等价的,运行结果如下:
转载地址:http://mdewi.baihongyu.com/