领导给的第一个任务是学习怎么利用角点检测做棋盘标定,学完了以后就敲一段代码实现长度测量,估计是想让我借此练练手罢。于是我花了一个下午和一个晚上把这个任务搞定了, 结果今天上班领导不在,那就先做一下笔记好了,也不算偷懒吧。
##功能要求
##设计分析
那么程序设计就可以大概分成两步:标定和测量。
####标定:
翻了一下Learning OpenCV
这本堪称经典的书,里面第11章介绍了如何进行摄像机标定,但是它的标定目的是为了消除摄像机畸变和坐标旋转,而老板给我说的是相机成像质量很高,无需做校正处理。也就是说,相机内参数为理想值,而坐标旋转对于我要实现的测量并无影响。这样一来,事情就简单多了,我只需要建立像素点和实际长度之间的对应关系,即可实现测量。
如何求取像素点和实际长度的对应关系呢?OpenCV里面有一个非常方便的方法:棋盘(Chessboard)。
给定一个棋盘图像,可以用findChessboardCorners()
来定位棋盘角点。
bool findChessboardCorners(
InputArray image,
Size patternSize,
OutputArray corners,
int flag = CALIB_CB_ADAPTIVE_THRESH
+ CALIB_CB_NORMALIZE_IMAGE
+ CALIB_CB_FAST_CHECK)
patternSize = cvSize(points_per_row,points_per_colum) = cvSize(columns,rows)
vector<Point2f> corners;
使用这个函数,可以将所有的角点坐标值都存储在corners
当中,可以通过corners[i].x
和corners[i].y
调用,真是非常方便。
角标坐标找到后,剩下的就只是建立映射关系了,这都是很简单的东西。
####测量:
在这部分遇到的问题主要是如何获取鼠标点击事件的像素坐标值。
######在OpenCV中提供了这样一个函数
void setMouseCallback(
const string& winname,
MouseCallback onMouse,
void* userdata=0 )
使用这个函数,我们需要定义onMouse()
函数,每当鼠标点击事件发生时,再结合CvScalar cvGet2D(const CvArr* arr, int idx0, int idx1)
即可获得像素坐标,剩下的就只是把这些像素值转换为长度值。更详细的使用方法请看OpenCV响应鼠标函数cvSetMouseCallback()和其副程式onMouse()的使用(OpenCV2.4.5)
那么到此基本思路就搞定了。可以发现,根本就没什么算法上面的难点,只是一些C++的语法和OpenCV库函数的使用而已,非常简单。但是在做这个任务的过程中,我看了很多OpenCv的API文档,直接相关的间接相关的都看了一眼,收获还是蛮大的。