diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index b05808367b..3fb4b7d42a 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -1281,13 +1281,45 @@ CV_EXPORTS_AS(findChessboardCornersSBWithMeta) bool findChessboardCornersSB(InputArray image,Size patternSize, OutputArray corners, int flags,OutputArray meta); /** @overload */ -CV_EXPORTS_W static inline +CV_EXPORTS_W inline bool findChessboardCornersSB(InputArray image, Size patternSize, OutputArray corners, int flags = 0) { return findChessboardCornersSB(image, patternSize, corners, flags, noArray()); } +/** @brief Estimates the sharpness of a detected chessboard. + +Image sharpness, as well as brightness, are a critical parameter for accuracte +camera calibration. For accessing these parameters for filtering out +problematic calibraiton images, this method calculates edge profiles by traveling from +black to white chessboard cell centers. Based on this, the number of pixels is +calculated required to transit from black to white. This width of the +transition area is a good indication of how sharp the chessboard is imaged +and should be below ~3.0 pixels. + +@param image Gray image used to find chessboard corners +@param patternSize Size of a found chessboard pattern +@param corners Corners found by findChessboardCorners(SB) +@param rise_distance Rise distance 0.8 means 10% ... 90% of the final signal strength +@param vertical By default edge responses for horizontal lines are calculated +@param sharpness Optional output array with a sharpness value for calculated edge responses (see description) + +The optional sharpness array is of type CV_32FC1 and has for each calculated +profile one row with the following five entries: +* 0 = x coordinate of the underlying edge in the image +* 1 = y coordinate of the underlying edge in the image +* 2 = width of the transition area (sharpness) +* 3 = signal strength in the black cell (min brightness) +* 4 = signal strength in the white cell (max brightness) + +@return Scalar(average sharpness, average min brightness, average max brightness,0) +*/ +CV_EXPORTS_W Scalar estimateChessboardSharpness(InputArray image, Size patternSize, InputArray corners, + float rise_distance=0.8F,bool vertical=false, + OutputArray sharpness=noArray()); + + //! finds subpixel-accurate positions of the chessboard corners CV_EXPORTS_W bool find4QuadCornerSubpix( InputArray img, InputOutputArray corners, Size region_size ); diff --git a/modules/calib3d/src/chessboard.cpp b/modules/calib3d/src/chessboard.cpp index 2b0b0a5eb8..04a3bbe6c0 100644 --- a/modules/calib3d/src/chessboard.cpp +++ b/modules/calib3d/src/chessboard.cpp @@ -725,19 +725,19 @@ void FastX::detectImpl(const cv::Mat& _gray_image, // calc images // for each angle step int scale_id = scale-parameters.min_scale; - int scale_size = int(pow(2.0,scale+1+super_res)-1); - int scale_size2 = int((scale_size/10)*2+1); + int scale_size = int(pow(2.0,scale+1+super_res)); + int scale_size2 = int((scale_size/7)*2+1); std::vector images; images.resize(2*num); cv::UMat rotated,filtered_h,filtered_v; - cv::blur(gray_image,images[0],cv::Size(scale_size,scale_size2)); - cv::blur(gray_image,images[num],cv::Size(scale_size2,scale_size)); + cv::boxFilter(gray_image,images[0],-1,cv::Size(scale_size,scale_size2)); + cv::boxFilter(gray_image,images[num],-1,cv::Size(scale_size2,scale_size)); for(int i=1;i points; + corners.reshape(2,corners.rows).convertTo(points,CV_32FC2); + if(int(points.size()) != patternSize.width * patternSize.height) + CV_Error(Error::StsBadArg, "Size mismatch between patternSize and number of provided corners."); + + Mat img; + if (image_.channels() != 1) + cvtColor(image_, img, COLOR_BGR2GRAY); + else + img = image_.getMat(); + + details::Chessboard::Board board(patternSize,points); + return board.calcEdgeSharpness(img,rise_distance,vertical,sharpness); +} + + } // namespace cv diff --git a/modules/calib3d/test/test_chesscorners.cpp b/modules/calib3d/test/test_chesscorners.cpp index 0dfd0b75c1..3d730f6bfd 100644 --- a/modules/calib3d/test/test_chesscorners.cpp +++ b/modules/calib3d/test/test_chesscorners.cpp @@ -235,11 +235,13 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename ) String _filename = folder + (String)board_list[idx * 2 + 1]; bool doesContatinChessboard; + float sharpness; Mat expected; { FileStorage fs1(_filename, FileStorage::READ); fs1["corners"] >> expected; fs1["isFound"] >> doesContatinChessboard; + fs1["sharpness"] >> sharpness ; fs1.release(); } size_t count_exp = static_cast(expected.cols * expected.rows); @@ -259,6 +261,17 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename ) flags = 0; } bool result = findChessboardCornersWrapper(gray, pattern_size,v,flags); + if(result && sharpness && (pattern == CHESSBOARD_SB || pattern == CHESSBOARD)) + { + Scalar s= estimateChessboardSharpness(gray,pattern_size,v); + if(fabs(s[0] - sharpness) > 0.1) + { + ts->printf(cvtest::TS::LOG, "chessboard image has a wrong sharpness in %s. Expected %f but measured %f\n", img_file.c_str(),sharpness,s[0]); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + show_points( gray, expected, v, result ); + return; + } + } if(result ^ doesContatinChessboard || (doesContatinChessboard && v.size() != count_exp)) { ts->printf( cvtest::TS::LOG, "chessboard is detected incorrectly in %s\n", img_file.c_str() );