Path: blob/master/modules/calib3d/test/test_chessboardgenerator.cpp
16337 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.13// Copyright (C) 2009, Willow Garage Inc., all rights reserved.14// Third party copyrights are property of their respective owners.15//16// Redistribution and use in source and binary forms, with or without modification,17// are permitted provided that the following conditions are met:18//19// * Redistribution's of source code must retain the above copyright notice,20// this list of conditions and the following disclaimer.21//22// * Redistribution's in binary form must reproduce the above copyright notice,23// this list of conditions and the following disclaimer in the documentation24// and/or other materials provided with the distribution.25//26// * The name of the copyright holders may not be used to endorse or promote products27// derived from this software without specific prior written permission.28//29// This software is provided by the copyright holders and contributors "as is" and30// any express or implied warranties, including, but not limited to, the implied31// warranties of merchantability and fitness for a particular purpose are disclaimed.32// In no event shall the Intel Corporation or contributors be liable for any direct,33// indirect, incidental, special, exemplary, or consequential damages34// (including, but not limited to, procurement of substitute goods or services;35// loss of use, data, or profits; or business interruption) however caused36// and on any theory of liability, whether in contract, strict liability,37// or tort (including negligence or otherwise) arising in any way out of38// the use of this software, even if advised of the possibility of such damage.39//40//M*/4142#include "test_precomp.hpp"43#include "test_chessboardgenerator.hpp"4445namespace cv {4647ChessBoardGenerator::ChessBoardGenerator(const Size& _patternSize) : sensorWidth(32), sensorHeight(24),48squareEdgePointsNum(200), min_cos(std::sqrt(3.f)*0.5f), cov(0.5),49patternSize(_patternSize), rendererResolutionMultiplier(4), tvec(Mat::zeros(1, 3, CV_32F))50{51rvec.create(3, 1, CV_32F);52cvtest::Rodrigues(Mat::eye(3, 3, CV_32F), rvec);53}5455void ChessBoardGenerator::generateEdge(const Point3f& p1, const Point3f& p2, vector<Point3f>& out) const56{57Point3f step = (p2 - p1) * (1.f/squareEdgePointsNum);58for(size_t n = 0; n < squareEdgePointsNum; ++n)59out.push_back( p1 + step * (float)n);60}6162Size ChessBoardGenerator::cornersSize() const63{64return Size(patternSize.width-1, patternSize.height-1);65}6667struct Mult68{69float m;70Mult(int mult) : m((float)mult) {}71Point2f operator()(const Point2f& p)const { return p * m; }72};7374void ChessBoardGenerator::generateBasis(Point3f& pb1, Point3f& pb2) const75{76RNG& rng = theRNG();7778Vec3f n;79for(;;)80{81n[0] = rng.uniform(-1.f, 1.f);82n[1] = rng.uniform(-1.f, 1.f);83n[2] = rng.uniform(0.0f, 1.f);84float len = (float)norm(n);85if (len < 1e-3)86continue;87n[0]/=len;88n[1]/=len;89n[2]/=len;9091if (n[2] > min_cos)92break;93}9495Vec3f n_temp = n; n_temp[0] += 100;96Vec3f b1 = n.cross(n_temp);97Vec3f b2 = n.cross(b1);98float len_b1 = (float)norm(b1);99float len_b2 = (float)norm(b2);100101pb1 = Point3f(b1[0]/len_b1, b1[1]/len_b1, b1[2]/len_b1);102pb2 = Point3f(b2[0]/len_b1, b2[1]/len_b2, b2[2]/len_b2);103}104105106Mat ChessBoardGenerator::generateChessBoard(const Mat& bg, const Mat& camMat, const Mat& distCoeffs,107const Point3f& zero, const Point3f& pb1, const Point3f& pb2,108float sqWidth, float sqHeight, const vector<Point3f>& whole,109vector<Point2f>& corners) const110{111vector< vector<Point> > squares_black;112for(int i = 0; i < patternSize.width; ++i)113for(int j = 0; j < patternSize.height; ++j)114if ( (i % 2 == 0 && j % 2 == 0) || (i % 2 != 0 && j % 2 != 0) )115{116vector<Point3f> pts_square3d;117vector<Point2f> pts_square2d;118119Point3f p1 = zero + (i + 0) * sqWidth * pb1 + (j + 0) * sqHeight * pb2;120Point3f p2 = zero + (i + 1) * sqWidth * pb1 + (j + 0) * sqHeight * pb2;121Point3f p3 = zero + (i + 1) * sqWidth * pb1 + (j + 1) * sqHeight * pb2;122Point3f p4 = zero + (i + 0) * sqWidth * pb1 + (j + 1) * sqHeight * pb2;123generateEdge(p1, p2, pts_square3d);124generateEdge(p2, p3, pts_square3d);125generateEdge(p3, p4, pts_square3d);126generateEdge(p4, p1, pts_square3d);127128projectPoints(Mat(pts_square3d), rvec, tvec, camMat, distCoeffs, pts_square2d);129squares_black.resize(squares_black.size() + 1);130vector<Point2f> temp;131approxPolyDP(Mat(pts_square2d), temp, 1.0, true);132transform(temp.begin(), temp.end(), back_inserter(squares_black.back()), Mult(rendererResolutionMultiplier));133}134135/* calculate corners */136corners3d.clear();137for(int j = 0; j < patternSize.height - 1; ++j)138for(int i = 0; i < patternSize.width - 1; ++i)139corners3d.push_back(zero + (i + 1) * sqWidth * pb1 + (j + 1) * sqHeight * pb2);140corners.clear();141projectPoints(Mat(corners3d), rvec, tvec, camMat, distCoeffs, corners);142143vector<Point3f> whole3d;144vector<Point2f> whole2d;145generateEdge(whole[0], whole[1], whole3d);146generateEdge(whole[1], whole[2], whole3d);147generateEdge(whole[2], whole[3], whole3d);148generateEdge(whole[3], whole[0], whole3d);149projectPoints(Mat(whole3d), rvec, tvec, camMat, distCoeffs, whole2d);150vector<Point2f> temp_whole2d;151approxPolyDP(Mat(whole2d), temp_whole2d, 1.0, true);152153vector< vector<Point > > whole_contour(1);154transform(temp_whole2d.begin(), temp_whole2d.end(),155back_inserter(whole_contour.front()), Mult(rendererResolutionMultiplier));156157Mat result;158if (rendererResolutionMultiplier == 1)159{160result = bg.clone();161drawContours(result, whole_contour, -1, Scalar::all(255), FILLED, LINE_AA);162drawContours(result, squares_black, -1, Scalar::all(0), FILLED, LINE_AA);163}164else165{166Mat tmp;167resize(bg, tmp, bg.size() * rendererResolutionMultiplier, 0, 0, INTER_LINEAR_EXACT);168drawContours(tmp, whole_contour, -1, Scalar::all(255), FILLED, LINE_AA);169drawContours(tmp, squares_black, -1, Scalar::all(0), FILLED, LINE_AA);170resize(tmp, result, bg.size(), 0, 0, INTER_AREA);171}172173return result;174}175176Mat ChessBoardGenerator::operator ()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, vector<Point2f>& corners) const177{178cov = std::min(cov, 0.8);179double fovx, fovy, focalLen;180Point2d principalPoint;181double aspect;182calibrationMatrixValues( camMat, bg.size(), sensorWidth, sensorHeight,183fovx, fovy, focalLen, principalPoint, aspect);184185RNG& rng = theRNG();186187float d1 = static_cast<float>(rng.uniform(0.1, 10.0));188float ah = static_cast<float>(rng.uniform(-fovx/2 * cov, fovx/2 * cov) * CV_PI / 180);189float av = static_cast<float>(rng.uniform(-fovy/2 * cov, fovy/2 * cov) * CV_PI / 180);190191Point3f p;192p.z = cos(ah) * d1;193p.x = sin(ah) * d1;194p.y = p.z * tan(av);195196Point3f pb1, pb2;197generateBasis(pb1, pb2);198199float cbHalfWidth = static_cast<float>(norm(p) * sin( std::min(fovx, fovy) * 0.5 * CV_PI / 180));200float cbHalfHeight = cbHalfWidth * patternSize.height / patternSize.width;201202float cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width;203float cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height;204205vector<Point3f> pts3d(4);206vector<Point2f> pts2d(4);207for(;;)208{209pts3d[0] = p + pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;210pts3d[1] = p + pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;211pts3d[2] = p - pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;212pts3d[3] = p - pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;213214/* can remake with better perf */215projectPoints(Mat(pts3d), rvec, tvec, camMat, distCoeffs, pts2d);216217bool inrect1 = pts2d[0].x < bg.cols && pts2d[0].y < bg.rows && pts2d[0].x > 0 && pts2d[0].y > 0;218bool inrect2 = pts2d[1].x < bg.cols && pts2d[1].y < bg.rows && pts2d[1].x > 0 && pts2d[1].y > 0;219bool inrect3 = pts2d[2].x < bg.cols && pts2d[2].y < bg.rows && pts2d[2].x > 0 && pts2d[2].y > 0;220bool inrect4 = pts2d[3].x < bg.cols && pts2d[3].y < bg.rows && pts2d[3].x > 0 && pts2d[3].y > 0;221222if (inrect1 && inrect2 && inrect3 && inrect4)223break;224225cbHalfWidth*=0.8f;226cbHalfHeight = cbHalfWidth * patternSize.height / patternSize.width;227228cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width;229cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height;230}231232Point3f zero = p - pb1 * cbHalfWidth - cbHalfHeight * pb2;233float sqWidth = 2 * cbHalfWidth/patternSize.width;234float sqHeight = 2 * cbHalfHeight/patternSize.height;235236return generateChessBoard(bg, camMat, distCoeffs, zero, pb1, pb2, sqWidth, sqHeight, pts3d, corners);237}238239240Mat ChessBoardGenerator::operator ()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs,241const Size2f& squareSize, vector<Point2f>& corners) const242{243cov = std::min(cov, 0.8);244double fovx, fovy, focalLen;245Point2d principalPoint;246double aspect;247calibrationMatrixValues( camMat, bg.size(), sensorWidth, sensorHeight,248fovx, fovy, focalLen, principalPoint, aspect);249250RNG& rng = theRNG();251252float d1 = static_cast<float>(rng.uniform(0.1, 10.0));253float ah = static_cast<float>(rng.uniform(-fovx/2 * cov, fovx/2 * cov) * CV_PI / 180);254float av = static_cast<float>(rng.uniform(-fovy/2 * cov, fovy/2 * cov) * CV_PI / 180);255256Point3f p;257p.z = cos(ah) * d1;258p.x = sin(ah) * d1;259p.y = p.z * tan(av);260261Point3f pb1, pb2;262generateBasis(pb1, pb2);263264float cbHalfWidth = squareSize.width * patternSize.width * 0.5f;265float cbHalfHeight = squareSize.height * patternSize.height * 0.5f;266267float cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width;268float cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height;269270vector<Point3f> pts3d(4);271vector<Point2f> pts2d(4);272for(;;)273{274pts3d[0] = p + pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;275pts3d[1] = p + pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;276pts3d[2] = p - pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;277pts3d[3] = p - pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;278279/* can remake with better perf */280projectPoints(Mat(pts3d), rvec, tvec, camMat, distCoeffs, pts2d);281282bool inrect1 = pts2d[0].x < bg.cols && pts2d[0].y < bg.rows && pts2d[0].x > 0 && pts2d[0].y > 0;283bool inrect2 = pts2d[1].x < bg.cols && pts2d[1].y < bg.rows && pts2d[1].x > 0 && pts2d[1].y > 0;284bool inrect3 = pts2d[2].x < bg.cols && pts2d[2].y < bg.rows && pts2d[2].x > 0 && pts2d[2].y > 0;285bool inrect4 = pts2d[3].x < bg.cols && pts2d[3].y < bg.rows && pts2d[3].x > 0 && pts2d[3].y > 0;286287if ( inrect1 && inrect2 && inrect3 && inrect4)288break;289290p.z *= 1.1f;291}292293Point3f zero = p - pb1 * cbHalfWidth - cbHalfHeight * pb2;294295return generateChessBoard(bg, camMat, distCoeffs, zero, pb1, pb2,296squareSize.width, squareSize.height, pts3d, corners);297}298299Mat ChessBoardGenerator::operator ()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs,300const Size2f& squareSize, const Point3f& pos, vector<Point2f>& corners) const301{302cov = std::min(cov, 0.8);303Point3f p = pos;304Point3f pb1, pb2;305generateBasis(pb1, pb2);306307float cbHalfWidth = squareSize.width * patternSize.width * 0.5f;308float cbHalfHeight = squareSize.height * patternSize.height * 0.5f;309310float cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width;311float cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height;312313vector<Point3f> pts3d(4);314vector<Point2f> pts2d(4);315316pts3d[0] = p + pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;317pts3d[1] = p + pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;318pts3d[2] = p - pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;319pts3d[3] = p - pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;320321/* can remake with better perf */322projectPoints(Mat(pts3d), rvec, tvec, camMat, distCoeffs, pts2d);323324Point3f zero = p - pb1 * cbHalfWidth - cbHalfHeight * pb2;325326return generateChessBoard(bg, camMat, distCoeffs, zero, pb1, pb2,327squareSize.width, squareSize.height, pts3d, corners);328}329330} // namespace331332333