Ubuntu环境中利用OpenCV进行相机标定
本文初衷
查了很多博客,发现大部分都是在windows环境中利用vs来实现摄像机标定的,其中有篇博客是在Ubuntu界面下操作的,如下:
https://blog.csdn.net/u012926144/article/details/81047728
他的博客由来实际上是源于VS上的一个张正友标定法,想要了解摄像机标定一定要看看该代码,标注很清晰。
[https://blog.csdn.net/dcrmg/article/details/52939318#t4]
Ubuntu文件生成和编译如下:
参考第一篇的博客:
(1)建立文件夹 iamge 保存标定所需的图片
src 保存程序
(2)创建文件 CMakeLists.txt,并写入
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
PROJECT( calibration )
SET(CMAKE_CXX_COMPILER “g++”)
SET( CMAKE_BUILD_TYPE Debug )
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/include )
LINK_DIRECTORIES( ${PROJECT_SOURCE_DIR}/lib)
ADD_SUBDIRECTORY( ${PROJECT_SOURCE_DIR}/src )
现在cameraCalibration文件夹内应该有image src CmakeLists.txt
(3)在src中创建calibration.cpp,内容也就是下面提到的主程序
(4) 在src中创建CMakeLists.txt文件,内容如下:(这里在我的电脑需要将FIND_PACKAGE( OpenCV REQUIRED )移动到ADD_EXECUTABLE前面,并去掉3.4)
增加一个可执行的二进制
FIND_PACKAGE( OpenCV REQUIRED )
ADD_EXECUTABLE(calibration calibration.cpp )
增加opencv的依赖
INCLUDE_DIRECTORIES( ${OpenCV_INCLUDE_DIRS} )
TARGET_LINK_LIBRARIES( calibration ${OpenCV_LIBS})
(5)编译运行
cd ./cameraCalibration
mkdir build
cd build
cmake … make
会生成bin文件夹,里面有可执行文件,运行后,会得到结果文件都在bin里面保存着。程序有错误的时候可以先检查路径是否正确。
但是我在实际操作过程中遇到文件路径问题`,我卡在这里一上午,都快崩溃了。
OpenCV Error: Assertion failed (nimages > 0) in calibrateCamera, file /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/calib3d/src/calibration.cpp, line 3357
terminate called after throwing an instance of 'cv::Exception'
what(): /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/calib3d/src/calibration.cpp:3357: error: (-215) nimages > 0 in function calibrateCamera
Aborted (core dumped)
查看其代码写入图片的程序段(片段):
int main()
{
ifstream fin("calibration.txt"); /* 标定所用图像文件的路径为避免出错最后是绝对路径 */
ofstream fout("calibration_result.txt"); /* 保存标定结果的文件 */
// 读取每一幅图像,从中提取出角点,然后对角点进行亚像素精确化
cout<<"开始提取角点………………"<<endl;
int image_count = 0; /* 图像数量 */
Size image_size; /* 图像的尺寸 */
Size board_size = Size(4, 6); /* 标定板上每行、列的角点数 */
vector<Point2f> image_points_buf; /* 缓存每幅图像上检测到的角点 */
vector<vector<Point2f> > image_points_seq; /* 保存检测到的所有角点 */
string filename; // 图片名
vector<string> filenames;
while (getline(fin, filename))
{
++image_count;
// 用于观察检验输出
cout<<"image_count = "<<image_count<<endl;
cout<<"filename: "<<filename<<endl;
Mat imageInput = imread(filename);
filenames.push_back(filename);
————————————————
版权声明:本文为CSDN博主「huawwenwnewn」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012926144/article/details/81047728
注意到他是用ifstream
实现文件读取的,这里我想到的是改用c++11新的读取方式boost::foramt
,而且这种方式不需要路径文件,只要在代码中写入相对路径即可。像下面这样,第一个chessboard代表图像存放文件夹(这里你需要和src在同一个地方,然后从bin中运行),第二个chessboard代表图像的名称,i+1代表第几章图片(从1开始):
boost::format fmt("../%s/%s%d.%s"); //图像文件文件格式
Mat imageInput = cv::imread((fmt % "chessboard" % "chessboard" % (i + 1) % "jpg").str());
一定要注意这里的相对路径前面是双引号(我们新手的坑,我又踩了),后面可能还会出现错误,需要修改vector<string> filenames;
为vector<cv::Ma