openCV学习
-
filter2D卷积
filter2D卷积是根据卷积核进行卷积运算的,卷积核的中心经过图像的每一个点,然后卷积核与覆盖下的每个像素相乘,所得到的结果相加,最后赋值给中心点,从而完成卷积,对于边缘有两种方式解决,第一种是边缘填充0,第二种是边缘填充和边缘大小一样的值。
-
基于hessian矩阵的steger算法提取激光线中心的算法:
利用的是直线的各向异性,在X方向Y方向的二阶导不同,比较哪个方向的特征值比较大,就说明各向异性比较强,也是光线的法线方向,然后根据steger算法,求出此坐标点的亚像素坐标,即时光线的中心点。
博客链接是: https://blog.csdn.net/Dangkie/article/details/78996761 -
访问图像像素的几个简单方法,指针和at
at访问方式:
指针访问的速度要比at快几十倍,同时还需要注意Mat定义的图像访问时(i,j)坐标要反过来,行和列是正确的但是访问时要反过来,比如要访问第10行7列,那么就是src.at(6,9);
单通道图像: Mat.at<存储类型名称>(列,行)
多通道图像: Mat.at<存储类型名称>(列,行)[通道]
Mat image;
image.at(25,43); //若image为单通道影像
image.at(25,43)[2]; //若image为多通道影像
访问时通道顺序是BGR指针访问方式:
for(int row = 0; row < src.rows; row++) { uchar *pValue = src.ptr<uchar>(row); for (int col = 0; col < src.cols; col++) { uchar bValue = pValue[3*col + 0]; uchar gValue = pValue[3*col + 1]; uchar rValue = pValue[3*col + 2]; } }
-
opencv的速率问题:vetor和pushback
在debug模式下,debug还原了很多调试信息,所以慢很多。使用vetor时很方便,不用去声明大小,而且可以随时往里面添加数据,用pushback便可以添加数据,但是在for循环里面添加或者取数据非常的慢,比普通数组慢很多。慢的原因是数据存储的局部性问题(data locality):
1、使用二位数组Depart[500][21]的时候,所有数据在内存中是连续存放的。访问内存时,内存访问的局部性较强,Cache命中的概率较大。L1 Cache访问延迟只有几个指令周期,而内存访问延迟则达到几百个指令周期。
2、Vector中的数据是连续存放的,但是Vector本身只保存指向数据块的指针。Vector建立在栈上,保存数据的数据块在堆上。因此二位动态数组Vector <Vector>中,指向行的所有指针是连续存放的。每个行的数据是连续存放的,但是行与行之间是不连续存放的。因此跨行访问时局部性降低,Cache命中率下降。所以用时间更多。
改进方案。提升数据局部性:
typedef int line[21];
VectorDepart; -
opencv读摄像头和视频
读取摄像头: cout << CV_VERSION << endl; //输出opencv的版本号 VideoCapture cap(0); //VideoCapture是打开摄像头的命名空间,cap(0)是打开摄像头,如果有两个摄像头要看0还是1能读取出来了。 if (!cap.isOpened()) { cout << "视频文件打开失败" << endl; } 读取相关信息: cout << "视频相关信息如下" << endl; cout << "宽度:" << cap.get(CV_CAP_PROP_FRAME_WIDTH) << endl; cout << "高度:" << cap.get(CV_CAP_PROP_FRAME_HEIGHT) << endl; cout << "总帧数:" << cap.get(CV_CAP_PROP_FRAME_COUNT) << endl; cout << "帧率(fps):" << cap.get(CV_CAP_PROP_FPS) << endl; 读取视频: VideoCapture cap("c://dev//res//out.avi");只需要地址拉进来就可以。
读取摄像头的一些API:
cv.VideoCapture() 初始化摄像头,0开启第一个摄像头,1开启第2个摄像头,返回摄像头对象,一般会自动打开摄像头
cap.read() 读取摄像头帧,返回值1表示是否成功读取帧,返回值2表示该帧
cv.cvtColor(frame,mode) 转换图片的色彩空间
cap.release() 关闭摄像头
cap.isOpened() 检查摄像头是否打开
cap.open() 打开摄像头
cap.get(propld) 获得该帧的大小
cap.set(propld,value) 设置该帧的大小waitKey(20); 一般用在视频中,演示20ms然后显示一帧。
if ((char)waitKey(1) == ‘q’) break; 判断如果按键按下q则视频停止,鼠标要点击在图上,并且是英文输入才可以停止。
保存视频://设置保存的视频帧数目 int frameNum = 100; //保存视频的路径 string outputVideoPath = "..\\test.avi"; //获取当前摄像头的视频信息 cv::Size sWH = cv::Size((int)cap.get(CV_CAP_PROP_FRAME_WIDTH), (int)cap.get(CV_CAP_PROP_FRAME_HEIGHT)); VideoWriter outputVideo; outputVideo.open(outputVideoPath, CV_FOURCC('M', 'P', '4', '2'), 25.0, sWH); while (cap.isOpened() && frameNum > 0) { cap >> Frame; if (Frame.empty()) break; outputVideo << Frame; frameNum--; imshow("img", Frame); waitKey(10); if ((char)waitKey(10) == 'q') break; } outputVideo.release();