findChessboardCornersSB: performance + support for full FOV boards with markers

Changes:

* UMat for blur + rotate resulting in a speedup of around 2X on an i7
* support for boards larger than specified allowing to cover full FOV
* support for markers moving the origin into the center of the board
* increase detection accuracy

The main change is for supporting boards that are larger than the FOV of
the camera and have their origin in the board center. This allows
building OEM calibration targets similar to the one from intel real
sense utilizing corner points as close as possible to the image border.
This commit is contained in:
Alexander Duda 2020-02-19 23:33:20 +01:00
parent bda89a6469
commit a41cbbdc99
4 changed files with 1013 additions and 140 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -257,7 +257,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,
@ -1237,7 +1239,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
@ -1248,6 +1259,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
@ -1257,7 +1277,16 @@ a sample checkerboard optimized for the detection. However, any other checkerboa
can be used as well.
![Checkerboard](pics/checkerboard_radon.png)
*/
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 static inline
bool findChessboardCornersSB(InputArray image, Size patternSize, OutputArray corners,
int flags = 0)
{
return findChessboardCornersSB(image, patternSize, corners, flags, 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

View File

@ -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 &center, 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: