mirror of
https://github.com/opencv/opencv.git
synced 2025-08-06 06:26:29 +08:00
Merge pull request #16625 from D-Alex:findChessboard
This commit is contained in:
commit
27b71d6368
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 33 KiB |
@ -268,7 +268,9 @@ enum { CALIB_CB_ADAPTIVE_THRESH = 1,
|
||||
CALIB_CB_FILTER_QUADS = 4,
|
||||
CALIB_CB_FAST_CHECK = 8,
|
||||
CALIB_CB_EXHAUSTIVE = 16,
|
||||
CALIB_CB_ACCURACY = 32
|
||||
CALIB_CB_ACCURACY = 32,
|
||||
CALIB_CB_LARGER = 64,
|
||||
CALIB_CB_MARKER = 128
|
||||
};
|
||||
|
||||
enum { CALIB_CB_SYMMETRIC_GRID = 1,
|
||||
@ -1248,7 +1250,16 @@ CV_EXPORTS_W bool checkChessboard(InputArray img, Size size);
|
||||
- **CALIB_CB_NORMALIZE_IMAGE** Normalize the image gamma with equalizeHist before detection.
|
||||
- **CALIB_CB_EXHAUSTIVE** Run an exhaustive search to improve detection rate.
|
||||
- **CALIB_CB_ACCURACY** Up sample input image to improve sub-pixel accuracy due to aliasing effects.
|
||||
- **CALIB_CB_LARGER** The detected pattern is allowed to be larger than patternSize (see description).
|
||||
- **CALIB_CB_MARKER** The detected pattern must have a marker (see description).
|
||||
This should be used if an accurate camera calibration is required.
|
||||
@param meta Optional output arrray of detected corners (CV_8UC1 and size = cv::Size(columns,rows)).
|
||||
Each entry stands for one corner of the pattern and can have one of the following values:
|
||||
- 0 = no meta data attached
|
||||
- 1 = left-top corner of a black cell
|
||||
- 2 = left-top corner of a white cell
|
||||
- 3 = left-top corner of a black cell with a white marker dot
|
||||
- 4 = left-top corner of a white cell with a black marker dot (pattern origin in case of markers otherwise first corner)
|
||||
|
||||
The function is analog to findchessboardCorners but uses a localized radon
|
||||
transformation approximated by box filters being more robust to all sort of
|
||||
@ -1259,6 +1270,15 @@ Calibration" demonstrating that the returned sub-pixel positions are more
|
||||
accurate than the one returned by cornerSubPix allowing a precise camera
|
||||
calibration for demanding applications.
|
||||
|
||||
In the case, the flags **CALIB_CB_LARGER** or **CALIB_CB_MARKER** are given,
|
||||
the result can be recovered from the optional meta array. Both flags are
|
||||
helpful to use calibration patterns exceeding the field of view of the camera.
|
||||
These oversized patterns allow more accurate calibrations as corners can be
|
||||
utilized, which are as close as possible to the image borders. For a
|
||||
consistent coordinate system across all images, the optional marker (see image
|
||||
below) can be used to move the origin of the board to the location where the
|
||||
black circle is located.
|
||||
|
||||
@note The function requires a white boarder with roughly the same width as one
|
||||
of the checkerboard fields around the whole board to improve the detection in
|
||||
various environments. In addition, because of the localized radon
|
||||
@ -1268,7 +1288,48 @@ a sample checkerboard optimized for the detection. However, any other checkerboa
|
||||
can be used as well.
|
||||

|
||||
*/
|
||||
CV_EXPORTS_W bool findChessboardCornersSB(InputArray image,Size patternSize, OutputArray corners,int flags=0);
|
||||
CV_EXPORTS_AS(findChessboardCornersSBWithMeta)
|
||||
bool findChessboardCornersSB(InputArray image,Size patternSize, OutputArray corners,
|
||||
int flags,OutputArray meta);
|
||||
/** @overload */
|
||||
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 );
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -36,7 +36,7 @@ class FastX : public cv::Feature2D
|
||||
branches = 2;
|
||||
min_scale = 2;
|
||||
max_scale = 5;
|
||||
super_resolution = 1;
|
||||
super_resolution = true;
|
||||
filter = true;
|
||||
}
|
||||
};
|
||||
@ -96,7 +96,7 @@ class FastX : public cv::Feature2D
|
||||
void detectImpl(const cv::Mat& _src, std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask)const;
|
||||
virtual void detectImpl(cv::InputArray image, std::vector<cv::KeyPoint>& keypoints, cv::InputArray mask=cv::noArray())const;
|
||||
|
||||
void rotate(float angle,const cv::Mat &img,cv::Size size,cv::Mat &out)const;
|
||||
void rotate(float angle,cv::InputArray img,cv::Size size,cv::OutputArray out)const;
|
||||
void calcFeatureMap(const cv::Mat &images,cv::Mat& out)const;
|
||||
|
||||
private:
|
||||
@ -111,6 +111,8 @@ class Ellipse
|
||||
public:
|
||||
Ellipse();
|
||||
Ellipse(const cv::Point2f ¢er, const cv::Size2f &axes, float angle);
|
||||
Ellipse(const Ellipse &other);
|
||||
|
||||
|
||||
void draw(cv::InputOutputArray img,const cv::Scalar &color = cv::Scalar::all(120))const;
|
||||
bool contains(const cv::Point2f &pt)const;
|
||||
@ -149,16 +151,18 @@ class Chessboard: public cv::Feature2D
|
||||
int max_tests; //!< maximal number of tested hypothesis
|
||||
bool super_resolution; //!< use super-repsolution for chessboard detection
|
||||
bool larger; //!< indicates if larger boards should be returned
|
||||
bool marker; //!< indicates that valid boards must have a white and black cirlce marker used for orientation
|
||||
|
||||
Parameters()
|
||||
{
|
||||
chessboard_size = cv::Size(9,6);
|
||||
min_scale = 2;
|
||||
min_scale = 3;
|
||||
max_scale = 4;
|
||||
super_resolution = true;
|
||||
max_points = 400;
|
||||
max_tests = 100;
|
||||
max_points = 200;
|
||||
max_tests = 50;
|
||||
larger = false;
|
||||
marker = false;
|
||||
}
|
||||
|
||||
Parameters(int scale,int _max_points):
|
||||
@ -386,6 +390,14 @@ class Chessboard: public cv::Feature2D
|
||||
*/
|
||||
std::vector<cv::Point2f> getCellCenters() const;
|
||||
|
||||
/**
|
||||
* \brief Returns all cells as mats of four points each describing their corners.
|
||||
*
|
||||
* The left top cell has index 0
|
||||
*
|
||||
*/
|
||||
std::vector<cv::Mat> getCells(float shrink_factor = 1.0,bool bwhite=true,bool bblack = true) const;
|
||||
|
||||
/**
|
||||
* \brief Estimates the homography between an ideal board
|
||||
* and reality based on the already recovered points
|
||||
@ -405,6 +417,12 @@ class Chessboard: public cv::Feature2D
|
||||
*/
|
||||
cv::Mat estimateHomography(int field_size = DUMMY_FIELD_SIZE)const;
|
||||
|
||||
/**
|
||||
* \brief Warp image to match ideal checkerboard
|
||||
*
|
||||
*/
|
||||
cv::Mat warpImage(cv::InputArray image)const;
|
||||
|
||||
/**
|
||||
* \brief Returns the size of the board
|
||||
*
|
||||
@ -431,6 +449,11 @@ class Chessboard: public cv::Feature2D
|
||||
*/
|
||||
std::vector<cv::Point2f> getContour()const;
|
||||
|
||||
/**
|
||||
* \brief Masks the found board in the given image
|
||||
*
|
||||
*/
|
||||
void maskImage(cv::InputOutputArray img,const cv::Scalar &color=cv::Scalar::all(0))const;
|
||||
|
||||
/**
|
||||
* \brief Grows the board in all direction until no more corners are found in the feature map
|
||||
@ -467,6 +490,27 @@ class Chessboard: public cv::Feature2D
|
||||
*/
|
||||
bool validateContour()const;
|
||||
|
||||
|
||||
/**
|
||||
\brief delete left column of the board
|
||||
*/
|
||||
bool shrinkLeft();
|
||||
|
||||
/**
|
||||
\brief delete right column of the board
|
||||
*/
|
||||
bool shrinkRight();
|
||||
|
||||
/**
|
||||
\brief shrink first row of the board
|
||||
*/
|
||||
bool shrinkTop();
|
||||
|
||||
/**
|
||||
\brief delete last row of the board
|
||||
*/
|
||||
bool shrinkBottom();
|
||||
|
||||
/**
|
||||
* \brief Grows the board to the left by adding one column.
|
||||
*
|
||||
@ -567,6 +611,12 @@ class Chessboard: public cv::Feature2D
|
||||
*/
|
||||
void normalizeOrientation(bool bblack=true);
|
||||
|
||||
/**
|
||||
* \brief Flips and rotates the board so that the marker
|
||||
* is normalized
|
||||
*/
|
||||
bool normalizeMarkerOrientation();
|
||||
|
||||
/**
|
||||
* \brief Exchanges the stored board with the board stored in other
|
||||
*/
|
||||
@ -594,16 +644,69 @@ class Chessboard: public cv::Feature2D
|
||||
*/
|
||||
std::map<int,int> getMapping()const;
|
||||
|
||||
/**
|
||||
* \brief Estimates rotation of the board around the camera axis
|
||||
*/
|
||||
double estimateRotZ()const;
|
||||
|
||||
/**
|
||||
* \brief Returns true if the cell is black
|
||||
*
|
||||
*/
|
||||
bool isCellBlack(int row,int cola)const;
|
||||
bool isCellBlack(int row,int col)const;
|
||||
|
||||
/**
|
||||
* \brief Returns true if the cell has a round marker at its
|
||||
* center
|
||||
*
|
||||
*/
|
||||
bool hasCellMarker(int row,int col);
|
||||
|
||||
/**
|
||||
* \brief Detects round markers in the chessboard fields based
|
||||
* on the given image and the already recoverd board corners
|
||||
*
|
||||
* \returns Returns the number of found markes
|
||||
*
|
||||
*/
|
||||
int detectMarkers(cv::InputArray image);
|
||||
|
||||
/**
|
||||
* \brief Calculates the average edge sharpness for the chessboard
|
||||
*
|
||||
* \param[in] image The image where the chessboard was detected
|
||||
* \param[in] rise_distante Rise distance 0.8 means 10% ... 90%
|
||||
* \param[in] vertical by default only edge response for horiontal lines are calculated
|
||||
*
|
||||
* \returns Scalar(sharpness, average min_val, average max_val)
|
||||
*
|
||||
* \author aduda@krakenrobotik.de
|
||||
*/
|
||||
cv::Scalar calcEdgeSharpness(cv::InputArray image,float rise_distance=0.8,bool vertical=false,cv::OutputArray sharpness=cv::noArray());
|
||||
|
||||
|
||||
/**
|
||||
* \brief Gets the 3D objects points for the chessboard
|
||||
* assuming the left top corner is located at the origin. In
|
||||
* case the board as a marker, the white marker cell is at position zero
|
||||
*
|
||||
* \param[in] cell_size Size of one cell
|
||||
*
|
||||
* \returns Returns the object points as CV_32FC3
|
||||
*/
|
||||
cv::Mat getObjectPoints(float cell_size)const;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns the angle the board is rotated agains the x-axis of the image plane
|
||||
* \returns Returns the object points as CV_32FC3
|
||||
*/
|
||||
float getAngle()const;
|
||||
|
||||
/**
|
||||
* \brief Returns true if the main direction of the board is close to the image x-axis than y-axis
|
||||
*/
|
||||
bool isHorizontal()const;
|
||||
|
||||
/**
|
||||
* \brief Updates the search angles
|
||||
*/
|
||||
void setAngles(float white,float black);
|
||||
|
||||
private:
|
||||
// stores one cell
|
||||
@ -616,10 +719,13 @@ class Chessboard: public cv::Feature2D
|
||||
cv::Point2f *top_left,*top_right,*bottom_right,*bottom_left; // corners
|
||||
Cell *left,*top,*right,*bottom; // neighbouring cells
|
||||
bool black; // set to true if cell is black
|
||||
bool marker; // set to true if cell has a round marker in its center
|
||||
Cell();
|
||||
bool empty()const; // indicates if the cell is empty (one of its corners has NaN)
|
||||
int getRow()const;
|
||||
int getCol()const;
|
||||
cv::Point2f getCenter()const;
|
||||
bool isInside(const cv::Point2f &pt)const; // check if point is inside the cell
|
||||
};
|
||||
|
||||
// corners
|
||||
@ -666,8 +772,8 @@ class Chessboard: public cv::Feature2D
|
||||
std::vector<Cell*> cells; // storage for all board cells
|
||||
std::vector<cv::Point2f*> corners; // storage for all corners
|
||||
Cell *top_left; // pointer to the top left corner of the board in its local coordinate system
|
||||
int rows; // number of row cells
|
||||
int cols; // number of col cells
|
||||
int rows; // number of inner pattern rows
|
||||
int cols; // number of inner pattern cols
|
||||
float white_angle,black_angle;
|
||||
};
|
||||
public:
|
||||
|
@ -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<size_t>(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() );
|
||||
|
Loading…
Reference in New Issue
Block a user