mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 23:33:05 +04:00
Merge pull request #28804 from asmorkalov:as/calib_boards_migration
Migrated chessboard and circles grid detectors to objdetect #28804 OpenCV Contrib: https://github.com/opencv/opencv_contrib/pull/4125 OpenCV Extra: https://github.com/opencv/opencv_extra/pull/1375 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
committed by
GitHub
parent
dafe7cef97
commit
e19b0ebc5c
@@ -4,6 +4,6 @@ set(debug_modules "")
|
||||
if(DEBUG_opencv_calib)
|
||||
list(APPEND debug_modules opencv_highgui)
|
||||
endif()
|
||||
ocv_define_module(calib opencv_imgproc opencv_features opencv_flann opencv_3d opencv_stereo ${debug_modules}
|
||||
ocv_define_module(calib opencv_imgproc opencv_objdetect opencv_flann opencv_3d opencv_stereo ${debug_modules}
|
||||
WRAP java objc python js
|
||||
)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/core/types.hpp"
|
||||
#include "opencv2/features.hpp"
|
||||
#include "opencv2/core/affine.hpp"
|
||||
|
||||
/**
|
||||
@@ -487,22 +486,6 @@ namespace cv {
|
||||
//! @addtogroup calib
|
||||
//! @{
|
||||
|
||||
enum { CALIB_CB_ADAPTIVE_THRESH = 1,
|
||||
CALIB_CB_NORMALIZE_IMAGE = 2,
|
||||
CALIB_CB_FILTER_QUADS = 4,
|
||||
CALIB_CB_FAST_CHECK = 8,
|
||||
CALIB_CB_EXHAUSTIVE = 16,
|
||||
CALIB_CB_ACCURACY = 32,
|
||||
CALIB_CB_LARGER = 64,
|
||||
CALIB_CB_MARKER = 128,
|
||||
CALIB_CB_PLAIN = 256
|
||||
};
|
||||
|
||||
enum { CALIB_CB_SYMMETRIC_GRID = 1,
|
||||
CALIB_CB_ASYMMETRIC_GRID = 2,
|
||||
CALIB_CB_CLUSTERING = 4
|
||||
};
|
||||
|
||||
#define CALIB_NINTRINSIC 18 //!< Maximal size of camera internal parameters (initrinsics) vector
|
||||
|
||||
enum CameraModel {
|
||||
@@ -577,257 +560,6 @@ CV_EXPORTS_W Mat initCameraMatrix2D( InputArrayOfArrays objectPoints,
|
||||
InputArrayOfArrays imagePoints,
|
||||
Size imageSize, double aspectRatio = 1.0 );
|
||||
|
||||
/** @brief Finds the positions of internal corners of the chessboard.
|
||||
|
||||
@param image Source chessboard view. It must be an 8-bit grayscale or color image.
|
||||
@param patternSize Number of inner corners per a chessboard row and column
|
||||
( patternSize = cv::Size(points_per_row,points_per_column) = cv::Size(columns,rows) ).
|
||||
@param corners Output array of detected corners.
|
||||
@param flags Various operation flags that can be zero or a combination of the following values:
|
||||
- @ref CALIB_CB_ADAPTIVE_THRESH Use adaptive thresholding to convert the image to black
|
||||
and white, rather than a fixed threshold level (computed from the average image brightness).
|
||||
- @ref CALIB_CB_NORMALIZE_IMAGE Normalize the image gamma with equalizeHist before
|
||||
applying fixed or adaptive thresholding.
|
||||
- @ref CALIB_CB_FILTER_QUADS Use additional criteria (like contour area, perimeter,
|
||||
square-like shape) to filter out false quads extracted at the contour retrieval stage.
|
||||
- @ref CALIB_CB_FAST_CHECK Run a fast check on the image that looks for chessboard corners,
|
||||
and shortcut the call if none is found. This can drastically speed up the call in the
|
||||
degenerate condition when no chessboard is observed.
|
||||
- @ref CALIB_CB_PLAIN All other flags are ignored. The input image is taken as is.
|
||||
No image processing is done to improve to find the checkerboard. This has the effect of speeding up the
|
||||
execution of the function but could lead to not recognizing the checkerboard if the image
|
||||
is not previously binarized in the appropriate manner.
|
||||
|
||||
The function attempts to determine whether the input image is a view of the chessboard pattern and
|
||||
locate the internal chessboard corners. The function returns a non-zero value if all of the corners
|
||||
are found and they are placed in a certain order (row by row, left to right in every row).
|
||||
Otherwise, if the function fails to find all the corners or reorder them, it returns 0. For example,
|
||||
a regular chessboard has 8 x 8 squares and 7 x 7 internal corners, that is, points where the black
|
||||
squares touch each other. The detected coordinates are approximate, and to determine their positions
|
||||
more accurately, the function calls #cornerSubPix. You also may use the function #cornerSubPix with
|
||||
different parameters if returned coordinates are not accurate enough.
|
||||
|
||||
Sample usage of detecting and drawing chessboard corners: :
|
||||
@code
|
||||
Size patternsize(8,6); //interior number of corners
|
||||
Mat gray = ....; //source image
|
||||
vector<Point2f> corners; //this will be filled by the detected corners
|
||||
|
||||
//CALIB_CB_FAST_CHECK saves a lot of time on images
|
||||
//that do not contain any chessboard corners
|
||||
bool patternfound = findChessboardCorners(gray, patternsize, corners,
|
||||
CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE
|
||||
+ CALIB_CB_FAST_CHECK);
|
||||
|
||||
if(patternfound)
|
||||
cornerSubPix(gray, corners, Size(11, 11), Size(-1, -1),
|
||||
TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
|
||||
|
||||
drawChessboardCorners(img, patternsize, Mat(corners), patternfound);
|
||||
@endcode
|
||||
@note The function requires white space (like a square-thick border, the wider the better) around
|
||||
the board to make the detection more robust in various environments. Otherwise, if there is no
|
||||
border and the background is dark, the outer black squares cannot be segmented properly and so the
|
||||
square grouping and ordering algorithm fails.
|
||||
|
||||
Use the `generate_pattern.py` Python script (@ref tutorial_camera_calibration_pattern)
|
||||
to create the desired checkerboard pattern.
|
||||
*/
|
||||
CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners,
|
||||
int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE );
|
||||
|
||||
/*
|
||||
Checks whether the image contains chessboard of the specific size or not.
|
||||
If yes, nonzero value is returned.
|
||||
*/
|
||||
CV_EXPORTS_W bool checkChessboard(InputArray img, Size size);
|
||||
|
||||
/** @brief Finds the positions of internal corners of the chessboard using a sector based approach.
|
||||
|
||||
@param image Source chessboard view. It must be an 8-bit grayscale or color image.
|
||||
@param patternSize Number of inner corners per a chessboard row and column
|
||||
( patternSize = cv::Size(points_per_row,points_per_column) = cv::Size(columns,rows) ).
|
||||
@param corners Output array of detected corners.
|
||||
@param flags Various operation flags that can be zero or a combination of the following values:
|
||||
- @ref CALIB_CB_NORMALIZE_IMAGE Normalize the image gamma with equalizeHist before detection.
|
||||
- @ref CALIB_CB_EXHAUSTIVE Run an exhaustive search to improve detection rate.
|
||||
- @ref CALIB_CB_ACCURACY Up sample input image to improve sub-pixel accuracy due to aliasing effects.
|
||||
- @ref CALIB_CB_LARGER The detected pattern is allowed to be larger than patternSize (see description).
|
||||
- @ref 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 array 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
|
||||
noise, faster on larger images and is able to directly return the sub-pixel
|
||||
position of the internal chessboard corners. The Method is based on the paper
|
||||
@cite duda2018 "Accurate Detection and Localization of Checkerboard Corners for
|
||||
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 @ref CALIB_CB_LARGER or @ref 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
|
||||
transformation it is beneficial to use round corners for the field corners
|
||||
which are located on the outside of the board. The following figure illustrates
|
||||
a sample checkerboard optimized for the detection. However, any other checkerboard
|
||||
can be used as well.
|
||||
|
||||
Use the `generate_pattern.py` Python script (@ref tutorial_camera_calibration_pattern)
|
||||
to create the corresponding checkerboard pattern:
|
||||
\image html pics/checkerboard_radon.png width=60%
|
||||
*/
|
||||
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 #findChessboardCornersSB
|
||||
@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 );
|
||||
|
||||
/** @brief Renders the detected chessboard corners.
|
||||
|
||||
@param image Destination image. It must be an 8-bit color image.
|
||||
@param patternSize Number of inner corners per a chessboard row and column
|
||||
(patternSize = cv::Size(points_per_row,points_per_column)).
|
||||
@param corners Array of detected corners, the output of #findChessboardCorners.
|
||||
@param patternWasFound Parameter indicating whether the complete board was found or not. The
|
||||
return value of #findChessboardCorners should be passed here.
|
||||
|
||||
The function draws individual chessboard corners detected either as red circles if the board was not
|
||||
found, or as colored corners connected with lines if the board was found.
|
||||
*/
|
||||
CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSize,
|
||||
InputArray corners, bool patternWasFound );
|
||||
|
||||
struct CV_EXPORTS_W_SIMPLE CirclesGridFinderParameters
|
||||
{
|
||||
CV_WRAP CirclesGridFinderParameters();
|
||||
CV_PROP_RW cv::Size2f densityNeighborhoodSize;
|
||||
CV_PROP_RW float minDensity;
|
||||
CV_PROP_RW int kmeansAttempts;
|
||||
CV_PROP_RW int minDistanceToAddKeypoint;
|
||||
CV_PROP_RW int keypointScale;
|
||||
CV_PROP_RW float minGraphConfidence;
|
||||
CV_PROP_RW float vertexGain;
|
||||
CV_PROP_RW float vertexPenalty;
|
||||
CV_PROP_RW float existingVertexGain;
|
||||
CV_PROP_RW float edgeGain;
|
||||
CV_PROP_RW float edgePenalty;
|
||||
CV_PROP_RW float convexHullFactor;
|
||||
CV_PROP_RW float minRNGEdgeSwitchDist;
|
||||
|
||||
enum GridType
|
||||
{
|
||||
SYMMETRIC_GRID, ASYMMETRIC_GRID
|
||||
};
|
||||
CV_PROP_RW GridType gridType;
|
||||
|
||||
CV_PROP_RW float squareSize; //!< Distance between two adjacent points. Used by CALIB_CB_CLUSTERING.
|
||||
CV_PROP_RW float maxRectifiedDistance; //!< Max deviation from prediction. Used by CALIB_CB_CLUSTERING.
|
||||
};
|
||||
|
||||
#ifndef DISABLE_OPENCV_3_COMPATIBILITY
|
||||
typedef CirclesGridFinderParameters CirclesGridFinderParameters2;
|
||||
#endif
|
||||
|
||||
/** @brief Finds centers in the grid of circles.
|
||||
|
||||
@param image grid view of input circles; it must be an 8-bit grayscale or color image.
|
||||
@param patternSize number of circles per row and column
|
||||
( patternSize = Size(points_per_row, points_per_column) ).
|
||||
@param centers output array of detected centers.
|
||||
@param flags various operation flags that can be one of the following values:
|
||||
- @ref CALIB_CB_SYMMETRIC_GRID uses symmetric pattern of circles.
|
||||
- @ref CALIB_CB_ASYMMETRIC_GRID uses asymmetric pattern of circles.
|
||||
- @ref CALIB_CB_CLUSTERING uses a special algorithm for grid detection. It is more robust to
|
||||
perspective distortions but much more sensitive to background clutter.
|
||||
@param blobDetector feature detector that finds blobs like dark circles on light background.
|
||||
If `blobDetector` is NULL then `image` represents Point2f array of candidates.
|
||||
@param parameters struct for finding circles in a grid pattern.
|
||||
|
||||
The function attempts to determine whether the input image contains a grid of circles. If it is, the
|
||||
function locates centers of the circles. The function returns a non-zero value if all of the centers
|
||||
have been found and they have been placed in a certain order (row by row, left to right in every
|
||||
row). Otherwise, if the function fails to find all the corners or reorder them, it returns 0.
|
||||
|
||||
Sample usage of detecting and drawing the centers of circles: :
|
||||
@code
|
||||
Size patternsize(7,7); //number of centers
|
||||
Mat gray = ...; //source image
|
||||
vector<Point2f> centers; //this will be filled by the detected centers
|
||||
|
||||
bool patternfound = findCirclesGrid(gray, patternsize, centers);
|
||||
|
||||
drawChessboardCorners(img, patternsize, Mat(centers), patternfound);
|
||||
@endcode
|
||||
@note The function requires white space (like a square-thick border, the wider the better) around
|
||||
the board to make the detection more robust in various environments.
|
||||
*/
|
||||
CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize,
|
||||
OutputArray centers, int flags,
|
||||
const Ptr<FeatureDetector> &blobDetector,
|
||||
const CirclesGridFinderParameters& parameters);
|
||||
|
||||
/** @overload */
|
||||
CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize,
|
||||
OutputArray centers, int flags = CALIB_CB_SYMMETRIC_GRID,
|
||||
const Ptr<FeatureDetector> &blobDetector = SimpleBlobDetector::create());
|
||||
|
||||
/** @brief Finds the camera intrinsic and extrinsic parameters from several views of a calibration
|
||||
pattern.
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
},
|
||||
"func_arg_fix" : {
|
||||
"initCameraMatrix2D" : { "objectPoints" : {"ctype" : "vector_vector_Point3f"},
|
||||
"imagePoints" : {"ctype" : "vector_vector_Point2f"} },
|
||||
"findChessboardCorners" : { "corners" : {"ctype" : "vector_Point2f"} },
|
||||
"drawChessboardCorners" : { "corners" : {"ctype" : "vector_Point2f"} }
|
||||
"imagePoints" : {"ctype" : "vector_vector_Point2f"} }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,86 +18,6 @@ import org.opencv.imgproc.Imgproc;
|
||||
|
||||
public class CalibTest extends OpenCVTestCase {
|
||||
|
||||
Size size;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
size = new Size(3, 3);
|
||||
}
|
||||
|
||||
public void testFindChessboardCornersMatSizeMat() {
|
||||
Size patternSize = new Size(9, 6);
|
||||
MatOfPoint2f corners = new MatOfPoint2f();
|
||||
Calib.findChessboardCorners(grayChess, patternSize, corners);
|
||||
assertFalse(corners.empty());
|
||||
}
|
||||
|
||||
public void testFindChessboardCornersMatSizeMatInt() {
|
||||
Size patternSize = new Size(9, 6);
|
||||
MatOfPoint2f corners = new MatOfPoint2f();
|
||||
Calib.findChessboardCorners(grayChess, patternSize, corners, Calib.CALIB_CB_ADAPTIVE_THRESH + Calib.CALIB_CB_NORMALIZE_IMAGE
|
||||
+ Calib.CALIB_CB_FAST_CHECK);
|
||||
assertFalse(corners.empty());
|
||||
}
|
||||
|
||||
public void testFind4QuadCornerSubpix() {
|
||||
Size patternSize = new Size(9, 6);
|
||||
MatOfPoint2f corners = new MatOfPoint2f();
|
||||
Size region_size = new Size(5, 5);
|
||||
Calib.findChessboardCorners(grayChess, patternSize, corners);
|
||||
Calib.find4QuadCornerSubpix(grayChess, corners, region_size);
|
||||
assertFalse(corners.empty());
|
||||
}
|
||||
|
||||
public void testFindCirclesGridMatSizeMat() {
|
||||
int size = 300;
|
||||
Mat img = new Mat(size, size, CvType.CV_8U);
|
||||
img.setTo(new Scalar(255));
|
||||
Mat centers = new Mat();
|
||||
|
||||
assertFalse(Calib.findCirclesGrid(img, new Size(5, 5), centers));
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
for (int j = 0; j < 5; j++) {
|
||||
Point pt = new Point(size * (2 * i + 1) / 10, size * (2 * j + 1) / 10);
|
||||
Imgproc.circle(img, pt, 10, new Scalar(0), -1);
|
||||
}
|
||||
|
||||
assertTrue(Calib.findCirclesGrid(img, new Size(5, 5), centers));
|
||||
|
||||
assertEquals(1, centers.rows());
|
||||
assertEquals(25, centers.cols());
|
||||
assertEquals(CvType.CV_32FC2, centers.type());
|
||||
}
|
||||
|
||||
public void testFindCirclesGridMatSizeMatInt() {
|
||||
int size = 300;
|
||||
Mat img = new Mat(size, size, CvType.CV_8U);
|
||||
img.setTo(new Scalar(255));
|
||||
Mat centers = new Mat();
|
||||
|
||||
assertFalse(Calib.findCirclesGrid(img, new Size(3, 5), centers, Calib.CALIB_CB_CLUSTERING
|
||||
| Calib.CALIB_CB_ASYMMETRIC_GRID));
|
||||
|
||||
int step = size * 2 / 15;
|
||||
int offsetx = size / 6;
|
||||
int offsety = (size - 4 * step) / 2;
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 5; j++) {
|
||||
Point pt = new Point(offsetx + (2 * i + j % 2) * step, offsety + step * j);
|
||||
Imgproc.circle(img, pt, 10, new Scalar(0), -1);
|
||||
}
|
||||
|
||||
assertTrue(Calib.findCirclesGrid(img, new Size(3, 5), centers, Calib.CALIB_CB_CLUSTERING
|
||||
| Calib.CALIB_CB_ASYMMETRIC_GRID));
|
||||
|
||||
assertEquals(1, centers.rows());
|
||||
assertEquals(15, centers.cols());
|
||||
assertEquals(CvType.CV_32FC2, centers.type());
|
||||
}
|
||||
|
||||
public void testConstants()
|
||||
{
|
||||
// calib3d.hpp: some constants have conflict with constants from 'fisheye' namespace
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
{
|
||||
"namespaces_dict": {
|
||||
"cv.fisheye": "fisheye"
|
||||
},
|
||||
"func_arg_fix" : {
|
||||
"Calib" : {
|
||||
"findCirclesGrid" : { "blobDetector" : {"defval" : "cv::SimpleBlobDetector::create()"} }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,89 +9,6 @@ import OpenCV
|
||||
|
||||
class CalibTest: OpenCVTestCase {
|
||||
|
||||
var size = Size()
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
size = Size(width: 3, height: 3)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testFindChessboardCornersMatSizeMat() {
|
||||
let patternSize = Size(width: 9, height: 6)
|
||||
let corners = MatOfPoint2f()
|
||||
Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners)
|
||||
XCTAssertFalse(corners.empty())
|
||||
}
|
||||
|
||||
func testFindChessboardCornersMatSizeMatInt() {
|
||||
let patternSize = Size(width: 9, height: 6)
|
||||
let corners = MatOfPoint2f()
|
||||
Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners, flags: Calib.CALIB_CB_ADAPTIVE_THRESH + Calib.CALIB_CB_NORMALIZE_IMAGE + Calib.CALIB_CB_FAST_CHECK)
|
||||
XCTAssertFalse(corners.empty())
|
||||
}
|
||||
|
||||
func testFind4QuadCornerSubpix() {
|
||||
let patternSize = Size(width: 9, height: 6)
|
||||
let corners = MatOfPoint2f()
|
||||
let region_size = Size(width: 5, height: 5)
|
||||
Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners)
|
||||
Calib.find4QuadCornerSubpix(img: grayChess, corners: corners, region_size: region_size)
|
||||
XCTAssertFalse(corners.empty())
|
||||
}
|
||||
|
||||
func testFindCirclesGridMatSizeMat() {
|
||||
let size = 300
|
||||
let img = Mat(rows:Int32(size), cols:Int32(size), type:CvType.CV_8U)
|
||||
img.setTo(scalar: Scalar(255))
|
||||
let centers = Mat()
|
||||
|
||||
XCTAssertFalse(Calib.findCirclesGrid(image: img, patternSize: Size(width: 5, height: 5), centers: centers))
|
||||
|
||||
for i in 0..<5 {
|
||||
for j in 0..<5 {
|
||||
let x = Int32(size * (2 * i + 1) / 10)
|
||||
let y = Int32(size * (2 * j + 1) / 10)
|
||||
let pt = Point(x: x, y: y)
|
||||
Imgproc.circle(img: img, center: pt, radius: 10, color: Scalar(0), thickness: -1)
|
||||
}
|
||||
}
|
||||
|
||||
XCTAssert(Calib.findCirclesGrid(image: img, patternSize:Size(width:5, height:5), centers:centers))
|
||||
|
||||
XCTAssertEqual(25, centers.rows())
|
||||
XCTAssertEqual(1, centers.cols())
|
||||
XCTAssertEqual(CvType.CV_32FC2, centers.type())
|
||||
}
|
||||
|
||||
func testFindCirclesGridMatSizeMatInt() {
|
||||
let size:Int32 = 300
|
||||
let img = Mat(rows:size, cols: size, type: CvType.CV_8U)
|
||||
img.setTo(scalar: Scalar(255))
|
||||
let centers = Mat()
|
||||
|
||||
XCTAssertFalse(Calib.findCirclesGrid(image: img, patternSize: Size(width: 3, height: 5), centers: centers, flags: Calib.CALIB_CB_CLUSTERING | Calib.CALIB_CB_ASYMMETRIC_GRID))
|
||||
|
||||
let step = size * 2 / 15
|
||||
let offsetx = size / 6
|
||||
let offsety = (size - 4 * step) / 2
|
||||
for i:Int32 in 0...2 {
|
||||
for j:Int32 in 0...4 {
|
||||
let pt = Point(x: offsetx + (2 * i + j % 2) * step, y: offsety + step * j)
|
||||
Imgproc.circle(img: img, center: pt, radius: 10, color: Scalar(0), thickness: -1)
|
||||
}
|
||||
}
|
||||
|
||||
XCTAssert(Calib.findCirclesGrid(image: img, patternSize: Size(width: 3, height: 5), centers: centers, flags: Calib.CALIB_CB_CLUSTERING | Calib.CALIB_CB_ASYMMETRIC_GRID))
|
||||
|
||||
XCTAssertEqual(15, centers.rows())
|
||||
XCTAssertEqual(1, centers.cols())
|
||||
XCTAssertEqual(CvType.CV_32FC2, centers.type())
|
||||
}
|
||||
|
||||
func testConstants()
|
||||
{
|
||||
// calib3d.hpp: some constants have conflict with constants from 'fisheye' namespace
|
||||
|
||||
@@ -134,8 +134,6 @@ static inline bool haveCollinearPoints( const Mat& m, int count )
|
||||
return false;
|
||||
}
|
||||
|
||||
int checkChessboardBinary(const Mat & img, const Size & size);
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include "opencv2/stereo.hpp"
|
||||
#include "opencv2/objdetect.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include "test_chessboardgenerator.hpp"
|
||||
#include "opencv2/objdetect.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ set(the_description "Object Detection")
|
||||
ocv_define_module(objdetect
|
||||
opencv_core
|
||||
opencv_imgproc
|
||||
opencv_features
|
||||
opencv_3d
|
||||
OPTIONAL
|
||||
opencv_dnn
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#define OPENCV_OBJDETECT_HPP
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/features.hpp"
|
||||
#include "opencv2/objdetect/aruco_detector.hpp"
|
||||
#include "opencv2/objdetect/graphical_code_detector.hpp"
|
||||
#include "opencv2/objdetect/mcc_checker_detector.hpp"
|
||||
@@ -316,6 +317,269 @@ public:
|
||||
CV_WRAP void setArucoParameters(const aruco::DetectorParameters& params);
|
||||
};
|
||||
|
||||
enum { CALIB_CB_ADAPTIVE_THRESH = 1,
|
||||
CALIB_CB_NORMALIZE_IMAGE = 2,
|
||||
CALIB_CB_FILTER_QUADS = 4,
|
||||
CALIB_CB_FAST_CHECK = 8,
|
||||
CALIB_CB_EXHAUSTIVE = 16,
|
||||
CALIB_CB_ACCURACY = 32,
|
||||
CALIB_CB_LARGER = 64,
|
||||
CALIB_CB_MARKER = 128,
|
||||
CALIB_CB_PLAIN = 256
|
||||
};
|
||||
|
||||
enum { CALIB_CB_SYMMETRIC_GRID = 1,
|
||||
CALIB_CB_ASYMMETRIC_GRID = 2,
|
||||
CALIB_CB_CLUSTERING = 4
|
||||
};
|
||||
|
||||
/** @brief Finds the positions of internal corners of the chessboard.
|
||||
|
||||
@param image Source chessboard view. It must be an 8-bit grayscale or color image.
|
||||
@param patternSize Number of inner corners per a chessboard row and column
|
||||
( patternSize = cv::Size(points_per_row,points_per_column) = cv::Size(columns,rows) ).
|
||||
@param corners Output array of detected corners.
|
||||
@param flags Various operation flags that can be zero or a combination of the following values:
|
||||
- @ref CALIB_CB_ADAPTIVE_THRESH Use adaptive thresholding to convert the image to black
|
||||
and white, rather than a fixed threshold level (computed from the average image brightness).
|
||||
- @ref CALIB_CB_NORMALIZE_IMAGE Normalize the image gamma with equalizeHist before
|
||||
applying fixed or adaptive thresholding.
|
||||
- @ref CALIB_CB_FILTER_QUADS Use additional criteria (like contour area, perimeter,
|
||||
square-like shape) to filter out false quads extracted at the contour retrieval stage.
|
||||
- @ref CALIB_CB_FAST_CHECK Run a fast check on the image that looks for chessboard corners,
|
||||
and shortcut the call if none is found. This can drastically speed up the call in the
|
||||
degenerate condition when no chessboard is observed.
|
||||
- @ref CALIB_CB_PLAIN All other flags are ignored. The input image is taken as is.
|
||||
No image processing is done to improve to find the checkerboard. This has the effect of speeding up the
|
||||
execution of the function but could lead to not recognizing the checkerboard if the image
|
||||
is not previously binarized in the appropriate manner.
|
||||
|
||||
The function attempts to determine whether the input image is a view of the chessboard pattern and
|
||||
locate the internal chessboard corners. The function returns a non-zero value if all of the corners
|
||||
are found and they are placed in a certain order (row by row, left to right in every row).
|
||||
Otherwise, if the function fails to find all the corners or reorder them, it returns 0. For example,
|
||||
a regular chessboard has 8 x 8 squares and 7 x 7 internal corners, that is, points where the black
|
||||
squares touch each other. The detected coordinates are approximate, and to determine their positions
|
||||
more accurately, the function calls #cornerSubPix. You also may use the function #cornerSubPix with
|
||||
different parameters if returned coordinates are not accurate enough.
|
||||
|
||||
Sample usage of detecting and drawing chessboard corners: :
|
||||
@code
|
||||
Size patternsize(8,6); //interior number of corners
|
||||
Mat gray = ....; //source image
|
||||
vector<Point2f> corners; //this will be filled by the detected corners
|
||||
|
||||
//CALIB_CB_FAST_CHECK saves a lot of time on images
|
||||
//that do not contain any chessboard corners
|
||||
bool patternfound = findChessboardCorners(gray, patternsize, corners,
|
||||
CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE
|
||||
+ CALIB_CB_FAST_CHECK);
|
||||
|
||||
if(patternfound)
|
||||
cornerSubPix(gray, corners, Size(11, 11), Size(-1, -1),
|
||||
TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
|
||||
|
||||
drawChessboardCorners(img, patternsize, Mat(corners), patternfound);
|
||||
@endcode
|
||||
@note The function requires white space (like a square-thick border, the wider the better) around
|
||||
the board to make the detection more robust in various environments. Otherwise, if there is no
|
||||
border and the background is dark, the outer black squares cannot be segmented properly and so the
|
||||
square grouping and ordering algorithm fails.
|
||||
|
||||
Use the `generate_pattern.py` Python script (@ref tutorial_camera_calibration_pattern)
|
||||
to create the desired checkerboard pattern.
|
||||
*/
|
||||
CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners,
|
||||
int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE );
|
||||
|
||||
/*
|
||||
Checks whether the image contains chessboard of the specific size or not.
|
||||
If yes, nonzero value is returned.
|
||||
*/
|
||||
CV_EXPORTS_W bool checkChessboard(InputArray img, Size size);
|
||||
|
||||
/** @brief Finds the positions of internal corners of the chessboard using a sector based approach.
|
||||
|
||||
@param image Source chessboard view. It must be an 8-bit grayscale or color image.
|
||||
@param patternSize Number of inner corners per a chessboard row and column
|
||||
( patternSize = cv::Size(points_per_row,points_per_column) = cv::Size(columns,rows) ).
|
||||
@param corners Output array of detected corners.
|
||||
@param flags Various operation flags that can be zero or a combination of the following values:
|
||||
- @ref CALIB_CB_NORMALIZE_IMAGE Normalize the image gamma with equalizeHist before detection.
|
||||
- @ref CALIB_CB_EXHAUSTIVE Run an exhaustive search to improve detection rate.
|
||||
- @ref CALIB_CB_ACCURACY Up sample input image to improve sub-pixel accuracy due to aliasing effects.
|
||||
- @ref CALIB_CB_LARGER The detected pattern is allowed to be larger than patternSize (see description).
|
||||
- @ref 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 array 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
|
||||
noise, faster on larger images and is able to directly return the sub-pixel
|
||||
position of the internal chessboard corners. The Method is based on the paper
|
||||
@cite duda2018 "Accurate Detection and Localization of Checkerboard Corners for
|
||||
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 @ref CALIB_CB_LARGER or @ref 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
|
||||
transformation it is beneficial to use round corners for the field corners
|
||||
which are located on the outside of the board. The following figure illustrates
|
||||
a sample checkerboard optimized for the detection. However, any other checkerboard
|
||||
can be used as well.
|
||||
|
||||
Use the `generate_pattern.py` Python script (@ref tutorial_camera_calibration_pattern)
|
||||
to create the corresponding checkerboard pattern:
|
||||
\image html pics/checkerboard_radon.png width=60%
|
||||
*/
|
||||
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 #findChessboardCornersSB
|
||||
@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 );
|
||||
|
||||
/** @brief Renders the detected chessboard corners.
|
||||
|
||||
@param image Destination image. It must be an 8-bit color image.
|
||||
@param patternSize Number of inner corners per a chessboard row and column
|
||||
(patternSize = cv::Size(points_per_row,points_per_column)).
|
||||
@param corners Array of detected corners, the output of #findChessboardCorners.
|
||||
@param patternWasFound Parameter indicating whether the complete board was found or not. The
|
||||
return value of #findChessboardCorners should be passed here.
|
||||
|
||||
The function draws individual chessboard corners detected either as red circles if the board was not
|
||||
found, or as colored corners connected with lines if the board was found.
|
||||
*/
|
||||
CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSize,
|
||||
InputArray corners, bool patternWasFound );
|
||||
|
||||
struct CV_EXPORTS_W_SIMPLE CirclesGridFinderParameters
|
||||
{
|
||||
CV_WRAP CirclesGridFinderParameters();
|
||||
CV_PROP_RW cv::Size2f densityNeighborhoodSize;
|
||||
CV_PROP_RW float minDensity;
|
||||
CV_PROP_RW int kmeansAttempts;
|
||||
CV_PROP_RW int minDistanceToAddKeypoint;
|
||||
CV_PROP_RW int keypointScale;
|
||||
CV_PROP_RW float minGraphConfidence;
|
||||
CV_PROP_RW float vertexGain;
|
||||
CV_PROP_RW float vertexPenalty;
|
||||
CV_PROP_RW float existingVertexGain;
|
||||
CV_PROP_RW float edgeGain;
|
||||
CV_PROP_RW float edgePenalty;
|
||||
CV_PROP_RW float convexHullFactor;
|
||||
CV_PROP_RW float minRNGEdgeSwitchDist;
|
||||
|
||||
enum GridType
|
||||
{
|
||||
SYMMETRIC_GRID, ASYMMETRIC_GRID
|
||||
};
|
||||
CV_PROP_RW GridType gridType;
|
||||
|
||||
CV_PROP_RW float squareSize; //!< Distance between two adjacent points. Used by CALIB_CB_CLUSTERING.
|
||||
CV_PROP_RW float maxRectifiedDistance; //!< Max deviation from prediction. Used by CALIB_CB_CLUSTERING.
|
||||
};
|
||||
|
||||
/** @brief Finds centers in the grid of circles.
|
||||
|
||||
@param image grid view of input circles; it must be an 8-bit grayscale or color image.
|
||||
@param patternSize number of circles per row and column
|
||||
( patternSize = Size(points_per_row, points_per_column) ).
|
||||
@param centers output array of detected centers.
|
||||
@param flags various operation flags that can be one of the following values:
|
||||
- @ref CALIB_CB_SYMMETRIC_GRID uses symmetric pattern of circles.
|
||||
- @ref CALIB_CB_ASYMMETRIC_GRID uses asymmetric pattern of circles.
|
||||
- @ref CALIB_CB_CLUSTERING uses a special algorithm for grid detection. It is more robust to
|
||||
perspective distortions but much more sensitive to background clutter.
|
||||
@param blobDetector feature detector that finds blobs like dark circles on light background.
|
||||
If `blobDetector` is NULL then `image` represents Point2f array of candidates.
|
||||
@param parameters struct for finding circles in a grid pattern.
|
||||
|
||||
The function attempts to determine whether the input image contains a grid of circles. If it is, the
|
||||
function locates centers of the circles. The function returns a non-zero value if all of the centers
|
||||
have been found and they have been placed in a certain order (row by row, left to right in every
|
||||
row). Otherwise, if the function fails to find all the corners or reorder them, it returns 0.
|
||||
|
||||
Sample usage of detecting and drawing the centers of circles: :
|
||||
@code
|
||||
Size patternsize(7,7); //number of centers
|
||||
Mat gray = ...; //source image
|
||||
vector<Point2f> centers; //this will be filled by the detected centers
|
||||
|
||||
bool patternfound = findCirclesGrid(gray, patternsize, centers);
|
||||
|
||||
drawChessboardCorners(img, patternsize, Mat(centers), patternfound);
|
||||
@endcode
|
||||
@note The function requires white space (like a square-thick border, the wider the better) around
|
||||
the board to make the detection more robust in various environments.
|
||||
*/
|
||||
CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize,
|
||||
OutputArray centers, int flags,
|
||||
const Ptr<FeatureDetector> &blobDetector,
|
||||
const CirclesGridFinderParameters& parameters);
|
||||
|
||||
/** @overload */
|
||||
CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize,
|
||||
OutputArray centers, int flags = CALIB_CB_SYMMETRIC_GRID,
|
||||
const Ptr<FeatureDetector> &blobDetector = cv::SimpleBlobDetector::create());
|
||||
|
||||
//! @}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,5 +65,9 @@
|
||||
"suffix": "Ljava_util_List",
|
||||
"v_type": "vector_NativeByteArray"
|
||||
}
|
||||
},
|
||||
"func_arg_fix" : {
|
||||
"findChessboardCorners" : { "corners" : {"ctype" : "vector_Point2f"} },
|
||||
"drawChessboardCorners" : { "corners" : {"ctype" : "vector_Point2f"} }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package org.opencv.test.objdetect;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.opencv.cv3d.Cv3d;
|
||||
import org.opencv.core.Core;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfDouble;
|
||||
import org.opencv.core.MatOfPoint2f;
|
||||
import org.opencv.core.MatOfPoint3f;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.objdetect.Objdetect;
|
||||
import org.opencv.test.OpenCVTestCase;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
public class ObjdetectTest extends OpenCVTestCase {
|
||||
|
||||
Size size;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
size = new Size(3, 3);
|
||||
}
|
||||
|
||||
public void testFindChessboardCornersMatSizeMat() {
|
||||
Size patternSize = new Size(9, 6);
|
||||
MatOfPoint2f corners = new MatOfPoint2f();
|
||||
Objdetect.findChessboardCorners(grayChess, patternSize, corners);
|
||||
assertFalse(corners.empty());
|
||||
}
|
||||
|
||||
public void testFindChessboardCornersMatSizeMatInt() {
|
||||
Size patternSize = new Size(9, 6);
|
||||
MatOfPoint2f corners = new MatOfPoint2f();
|
||||
Objdetect.findChessboardCorners(grayChess, patternSize, corners, Objdetect.CALIB_CB_ADAPTIVE_THRESH + Objdetect.CALIB_CB_NORMALIZE_IMAGE
|
||||
+ Objdetect.CALIB_CB_FAST_CHECK);
|
||||
assertFalse(corners.empty());
|
||||
}
|
||||
|
||||
public void testFind4QuadCornerSubpix() {
|
||||
Size patternSize = new Size(9, 6);
|
||||
MatOfPoint2f corners = new MatOfPoint2f();
|
||||
Size region_size = new Size(5, 5);
|
||||
Objdetect.findChessboardCorners(grayChess, patternSize, corners);
|
||||
Objdetect.find4QuadCornerSubpix(grayChess, corners, region_size);
|
||||
assertFalse(corners.empty());
|
||||
}
|
||||
|
||||
public void testFindCirclesGridMatSizeMat() {
|
||||
int size = 300;
|
||||
Mat img = new Mat(size, size, CvType.CV_8U);
|
||||
img.setTo(new Scalar(255));
|
||||
Mat centers = new Mat();
|
||||
|
||||
assertFalse(Objdetect.findCirclesGrid(img, new Size(5, 5), centers));
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
for (int j = 0; j < 5; j++) {
|
||||
Point pt = new Point(size * (2 * i + 1) / 10, size * (2 * j + 1) / 10);
|
||||
Imgproc.circle(img, pt, 10, new Scalar(0), -1);
|
||||
}
|
||||
|
||||
assertTrue(Objdetect.findCirclesGrid(img, new Size(5, 5), centers));
|
||||
|
||||
assertEquals(1, centers.rows());
|
||||
assertEquals(25, centers.cols());
|
||||
assertEquals(CvType.CV_32FC2, centers.type());
|
||||
}
|
||||
|
||||
public void testFindCirclesGridMatSizeMatInt() {
|
||||
int size = 300;
|
||||
Mat img = new Mat(size, size, CvType.CV_8U);
|
||||
img.setTo(new Scalar(255));
|
||||
Mat centers = new Mat();
|
||||
|
||||
assertFalse(Objdetect.findCirclesGrid(img, new Size(3, 5), centers, Objdetect.CALIB_CB_CLUSTERING
|
||||
| Objdetect.CALIB_CB_ASYMMETRIC_GRID));
|
||||
|
||||
int step = size * 2 / 15;
|
||||
int offsetx = size / 6;
|
||||
int offsety = (size - 4 * step) / 2;
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 5; j++) {
|
||||
Point pt = new Point(offsetx + (2 * i + j % 2) * step, offsety + step * j);
|
||||
Imgproc.circle(img, pt, 10, new Scalar(0), -1);
|
||||
}
|
||||
|
||||
assertTrue(Objdetect.findCirclesGrid(img, new Size(3, 5), centers, Objdetect.CALIB_CB_CLUSTERING
|
||||
| Objdetect.CALIB_CB_ASYMMETRIC_GRID));
|
||||
|
||||
assertEquals(1, centers.rows());
|
||||
assertEquals(15, centers.cols());
|
||||
assertEquals(CvType.CV_32FC2, centers.type());
|
||||
}
|
||||
}
|
||||
@@ -3,5 +3,10 @@
|
||||
"QRCodeDetectorAruco": {
|
||||
"getDetectorParameters": { "declaration" : [""], "implementation" : [""] }
|
||||
}
|
||||
},
|
||||
"func_arg_fix" : {
|
||||
"Calib" : {
|
||||
"findCirclesGrid" : { "blobDetector" : {"defval" : "cv::SimpleBlobDetector::create()"} }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import XCTest
|
||||
import OpenCV
|
||||
|
||||
class ObjdetectTest: OpenCVTestCase {
|
||||
|
||||
var size = Size()
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
size = Size(width: 3, height: 3)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testFindChessboardCornersMatSizeMat() {
|
||||
let patternSize = Size(width: 9, height: 6)
|
||||
let corners = MatOfPoint2f()
|
||||
Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners)
|
||||
XCTAssertFalse(corners.empty())
|
||||
}
|
||||
|
||||
func testFindChessboardCornersMatSizeMatInt() {
|
||||
let patternSize = Size(width: 9, height: 6)
|
||||
let corners = MatOfPoint2f()
|
||||
Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners, flags: Calib.CALIB_CB_ADAPTIVE_THRESH + Calib.CALIB_CB_NORMALIZE_IMAGE + Calib.CALIB_CB_FAST_CHECK)
|
||||
XCTAssertFalse(corners.empty())
|
||||
}
|
||||
|
||||
func testFind4QuadCornerSubpix() {
|
||||
let patternSize = Size(width: 9, height: 6)
|
||||
let corners = MatOfPoint2f()
|
||||
let region_size = Size(width: 5, height: 5)
|
||||
Calib.findChessboardCorners(image: grayChess, patternSize: patternSize, corners: corners)
|
||||
Calib.find4QuadCornerSubpix(img: grayChess, corners: corners, region_size: region_size)
|
||||
XCTAssertFalse(corners.empty())
|
||||
}
|
||||
|
||||
func testFindCirclesGridMatSizeMat() {
|
||||
let size = 300
|
||||
let img = Mat(rows:Int32(size), cols:Int32(size), type:CvType.CV_8U)
|
||||
img.setTo(scalar: Scalar(255))
|
||||
let centers = Mat()
|
||||
|
||||
XCTAssertFalse(Calib.findCirclesGrid(image: img, patternSize: Size(width: 5, height: 5), centers: centers))
|
||||
|
||||
for i in 0..<5 {
|
||||
for j in 0..<5 {
|
||||
let x = Int32(size * (2 * i + 1) / 10)
|
||||
let y = Int32(size * (2 * j + 1) / 10)
|
||||
let pt = Point(x: x, y: y)
|
||||
Imgproc.circle(img: img, center: pt, radius: 10, color: Scalar(0), thickness: -1)
|
||||
}
|
||||
}
|
||||
|
||||
XCTAssert(Calib.findCirclesGrid(image: img, patternSize:Size(width:5, height:5), centers:centers))
|
||||
|
||||
XCTAssertEqual(25, centers.rows())
|
||||
XCTAssertEqual(1, centers.cols())
|
||||
XCTAssertEqual(CvType.CV_32FC2, centers.type())
|
||||
}
|
||||
|
||||
func testFindCirclesGridMatSizeMatInt() {
|
||||
let size:Int32 = 300
|
||||
let img = Mat(rows:size, cols: size, type: CvType.CV_8U)
|
||||
img.setTo(scalar: Scalar(255))
|
||||
let centers = Mat()
|
||||
|
||||
XCTAssertFalse(Calib.findCirclesGrid(image: img, patternSize: Size(width: 3, height: 5), centers: centers, flags: Calib.CALIB_CB_CLUSTERING | Calib.CALIB_CB_ASYMMETRIC_GRID))
|
||||
|
||||
let step = size * 2 / 15
|
||||
let offsetx = size / 6
|
||||
let offsety = (size - 4 * step) / 2
|
||||
for i:Int32 in 0...2 {
|
||||
for j:Int32 in 0...4 {
|
||||
let pt = Point(x: offsetx + (2 * i + j % 2) * step, y: offsety + step * j)
|
||||
Imgproc.circle(img: img, center: pt, radius: 10, color: Scalar(0), thickness: -1)
|
||||
}
|
||||
}
|
||||
|
||||
XCTAssert(Calib.findCirclesGrid(image: img, patternSize: Size(width: 3, height: 5), centers: centers, flags: Calib.CALIB_CB_CLUSTERING | Calib.CALIB_CB_ASYMMETRIC_GRID))
|
||||
|
||||
XCTAssertEqual(15, centers.rows())
|
||||
XCTAssertEqual(1, centers.cols())
|
||||
XCTAssertEqual(CvType.CV_32FC2, centers.type())
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,7 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "circlesgrid.hpp"
|
||||
#include "opencv2/3d.hpp"
|
||||
#include "opencv2/flann.hpp"
|
||||
|
||||
#include <stack>
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencv2/flann.hpp"
|
||||
#include "opencv2/3d.hpp"
|
||||
#include "chessboard.hpp"
|
||||
#include "math.h"
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "opencv2/3d.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
#ifdef DEBUG_CIRCLES
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "opencv2/objdetect/barcode.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
#include "opencv2/core/utility.hpp"
|
||||
#include "opencv2/core/ocl.hpp"
|
||||
#include "opencv2/core/private.hpp"
|
||||
@@ -56,4 +57,11 @@
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
namespace cv {
|
||||
|
||||
int checkChessboardBinary(const Mat & img, const Size & size);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,331 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include "test_chessboardgenerator.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
ChessBoardGenerator::ChessBoardGenerator(const Size& _patternSize) : sensorWidth(32), sensorHeight(24),
|
||||
squareEdgePointsNum(200), min_cos(std::sqrt(3.f)*0.5f), cov(0.5),
|
||||
patternSize(_patternSize), rendererResolutionMultiplier(4), tvec(Mat::zeros(1, 3, CV_32F))
|
||||
{
|
||||
rvec.create(3, 1, CV_32F);
|
||||
Rodrigues(Mat::eye(3, 3, CV_32F), rvec);
|
||||
}
|
||||
|
||||
void ChessBoardGenerator::generateEdge(const Point3f& p1, const Point3f& p2, vector<Point3f>& out) const
|
||||
{
|
||||
Point3f step = (p2 - p1) * (1.f/squareEdgePointsNum);
|
||||
for(size_t n = 0; n < squareEdgePointsNum; ++n)
|
||||
out.push_back( p1 + step * (float)n);
|
||||
}
|
||||
|
||||
Size ChessBoardGenerator::cornersSize() const
|
||||
{
|
||||
return Size(patternSize.width-1, patternSize.height-1);
|
||||
}
|
||||
|
||||
struct Mult
|
||||
{
|
||||
float m;
|
||||
Mult(int mult) : m((float)mult) {}
|
||||
Point2f operator()(const Point2f& p)const { return p * m; }
|
||||
};
|
||||
|
||||
void ChessBoardGenerator::generateBasis(Point3f& pb1, Point3f& pb2) const
|
||||
{
|
||||
RNG& rng = theRNG();
|
||||
|
||||
Vec3f n;
|
||||
for(;;)
|
||||
{
|
||||
n[0] = rng.uniform(-1.f, 1.f);
|
||||
n[1] = rng.uniform(-1.f, 1.f);
|
||||
n[2] = rng.uniform(0.0f, 1.f);
|
||||
float len = (float)norm(n);
|
||||
if (len < 1e-3)
|
||||
continue;
|
||||
n[0]/=len;
|
||||
n[1]/=len;
|
||||
n[2]/=len;
|
||||
|
||||
if (n[2] > min_cos)
|
||||
break;
|
||||
}
|
||||
|
||||
Vec3f n_temp = n; n_temp[0] += 100;
|
||||
Vec3f b1 = n.cross(n_temp);
|
||||
Vec3f b2 = n.cross(b1);
|
||||
float len_b1 = (float)norm(b1);
|
||||
float len_b2 = (float)norm(b2);
|
||||
|
||||
pb1 = Point3f(b1[0]/len_b1, b1[1]/len_b1, b1[2]/len_b1);
|
||||
pb2 = Point3f(b2[0]/len_b1, b2[1]/len_b2, b2[2]/len_b2);
|
||||
}
|
||||
|
||||
|
||||
Mat ChessBoardGenerator::generateChessBoard(const Mat& bg, const Mat& camMat, const Mat& distCoeffs,
|
||||
const Point3f& zero, const Point3f& pb1, const Point3f& pb2,
|
||||
float sqWidth, float sqHeight, const vector<Point3f>& whole,
|
||||
vector<Point2f>& corners) const
|
||||
{
|
||||
vector< vector<Point> > squares_black;
|
||||
for(int i = 0; i < patternSize.width; ++i)
|
||||
for(int j = 0; j < patternSize.height; ++j)
|
||||
if ( (i % 2 == 0 && j % 2 == 0) || (i % 2 != 0 && j % 2 != 0) )
|
||||
{
|
||||
vector<Point3f> pts_square3d;
|
||||
vector<Point2f> pts_square2d;
|
||||
|
||||
Point3f p1 = zero + (i + 0) * sqWidth * pb1 + (j + 0) * sqHeight * pb2;
|
||||
Point3f p2 = zero + (i + 1) * sqWidth * pb1 + (j + 0) * sqHeight * pb2;
|
||||
Point3f p3 = zero + (i + 1) * sqWidth * pb1 + (j + 1) * sqHeight * pb2;
|
||||
Point3f p4 = zero + (i + 0) * sqWidth * pb1 + (j + 1) * sqHeight * pb2;
|
||||
generateEdge(p1, p2, pts_square3d);
|
||||
generateEdge(p2, p3, pts_square3d);
|
||||
generateEdge(p3, p4, pts_square3d);
|
||||
generateEdge(p4, p1, pts_square3d);
|
||||
|
||||
projectPoints(pts_square3d, rvec, tvec, camMat, distCoeffs, pts_square2d);
|
||||
squares_black.resize(squares_black.size() + 1);
|
||||
vector<Point2f> temp;
|
||||
approxPolyDP(pts_square2d, temp, 1.0, true);
|
||||
transform(temp.begin(), temp.end(), back_inserter(squares_black.back()), Mult(rendererResolutionMultiplier));
|
||||
}
|
||||
|
||||
/* calculate corners */
|
||||
corners3d.clear();
|
||||
for(int j = 0; j < patternSize.height - 1; ++j)
|
||||
for(int i = 0; i < patternSize.width - 1; ++i)
|
||||
corners3d.push_back(zero + (i + 1) * sqWidth * pb1 + (j + 1) * sqHeight * pb2);
|
||||
corners.clear();
|
||||
projectPoints(corners3d, rvec, tvec, camMat, distCoeffs, corners);
|
||||
|
||||
vector<Point3f> whole3d;
|
||||
vector<Point2f> whole2d;
|
||||
generateEdge(whole[0], whole[1], whole3d);
|
||||
generateEdge(whole[1], whole[2], whole3d);
|
||||
generateEdge(whole[2], whole[3], whole3d);
|
||||
generateEdge(whole[3], whole[0], whole3d);
|
||||
projectPoints(whole3d, rvec, tvec, camMat, distCoeffs, whole2d);
|
||||
vector<Point2f> temp_whole2d;
|
||||
approxPolyDP(whole2d, temp_whole2d, 1.0, true);
|
||||
|
||||
vector< vector<Point > > whole_contour(1);
|
||||
transform(temp_whole2d.begin(), temp_whole2d.end(),
|
||||
back_inserter(whole_contour.front()), Mult(rendererResolutionMultiplier));
|
||||
|
||||
Mat result;
|
||||
if (rendererResolutionMultiplier == 1)
|
||||
{
|
||||
result = bg.clone();
|
||||
drawContours(result, whole_contour, -1, Scalar::all(255), FILLED, LINE_AA);
|
||||
drawContours(result, squares_black, -1, Scalar::all(0), FILLED, LINE_AA);
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat tmp;
|
||||
resize(bg, tmp, bg.size() * rendererResolutionMultiplier, 0, 0, INTER_LINEAR_EXACT);
|
||||
drawContours(tmp, whole_contour, -1, Scalar::all(255), FILLED, LINE_AA);
|
||||
drawContours(tmp, squares_black, -1, Scalar::all(0), FILLED, LINE_AA);
|
||||
resize(tmp, result, bg.size(), 0, 0, INTER_AREA);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Mat ChessBoardGenerator::operator ()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, vector<Point2f>& corners) const
|
||||
{
|
||||
cov = std::min(cov, 0.8);
|
||||
double fovx, fovy, focalLen;
|
||||
Point2d principalPoint;
|
||||
double aspect;
|
||||
calibrationMatrixValues( camMat, bg.size(), sensorWidth, sensorHeight,
|
||||
fovx, fovy, focalLen, principalPoint, aspect);
|
||||
|
||||
RNG& rng = theRNG();
|
||||
|
||||
float d1 = static_cast<float>(rng.uniform(0.1, 10.0));
|
||||
float ah = static_cast<float>(rng.uniform(-fovx/2 * cov, fovx/2 * cov) * CV_PI / 180);
|
||||
float av = static_cast<float>(rng.uniform(-fovy/2 * cov, fovy/2 * cov) * CV_PI / 180);
|
||||
|
||||
Point3f p;
|
||||
p.z = std::cos(ah) * d1;
|
||||
p.x = std::sin(ah) * d1;
|
||||
p.y = p.z * std::tan(av);
|
||||
|
||||
Point3f pb1, pb2;
|
||||
generateBasis(pb1, pb2);
|
||||
|
||||
float cbHalfWidth = static_cast<float>(norm(p) * std::sin( std::min(fovx, fovy) * 0.5 * CV_PI / 180));
|
||||
float cbHalfHeight = cbHalfWidth * patternSize.height / patternSize.width;
|
||||
|
||||
float cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width;
|
||||
float cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height;
|
||||
|
||||
vector<Point3f> pts3d(4);
|
||||
vector<Point2f> pts2d(4);
|
||||
for(;;)
|
||||
{
|
||||
pts3d[0] = p + pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;
|
||||
pts3d[1] = p + pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;
|
||||
pts3d[2] = p - pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;
|
||||
pts3d[3] = p - pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;
|
||||
|
||||
/* can remake with better perf */
|
||||
projectPoints(pts3d, rvec, tvec, camMat, distCoeffs, pts2d);
|
||||
|
||||
bool inrect1 = pts2d[0].x < bg.cols && pts2d[0].y < bg.rows && pts2d[0].x > 0 && pts2d[0].y > 0;
|
||||
bool inrect2 = pts2d[1].x < bg.cols && pts2d[1].y < bg.rows && pts2d[1].x > 0 && pts2d[1].y > 0;
|
||||
bool inrect3 = pts2d[2].x < bg.cols && pts2d[2].y < bg.rows && pts2d[2].x > 0 && pts2d[2].y > 0;
|
||||
bool inrect4 = pts2d[3].x < bg.cols && pts2d[3].y < bg.rows && pts2d[3].x > 0 && pts2d[3].y > 0;
|
||||
|
||||
if (inrect1 && inrect2 && inrect3 && inrect4)
|
||||
break;
|
||||
|
||||
cbHalfWidth*=0.8f;
|
||||
cbHalfHeight = cbHalfWidth * patternSize.height / patternSize.width;
|
||||
|
||||
cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width;
|
||||
cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height;
|
||||
}
|
||||
|
||||
Point3f zero = p - pb1 * cbHalfWidth - cbHalfHeight * pb2;
|
||||
float sqWidth = 2 * cbHalfWidth/patternSize.width;
|
||||
float sqHeight = 2 * cbHalfHeight/patternSize.height;
|
||||
|
||||
return generateChessBoard(bg, camMat, distCoeffs, zero, pb1, pb2, sqWidth, sqHeight, pts3d, corners);
|
||||
}
|
||||
|
||||
|
||||
Mat ChessBoardGenerator::operator ()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs,
|
||||
const Size2f& squareSize, vector<Point2f>& corners) const
|
||||
{
|
||||
cov = std::min(cov, 0.8);
|
||||
double fovx, fovy, focalLen;
|
||||
Point2d principalPoint;
|
||||
double aspect;
|
||||
calibrationMatrixValues( camMat, bg.size(), sensorWidth, sensorHeight,
|
||||
fovx, fovy, focalLen, principalPoint, aspect);
|
||||
|
||||
RNG& rng = theRNG();
|
||||
|
||||
float d1 = static_cast<float>(rng.uniform(0.1, 10.0));
|
||||
float ah = static_cast<float>(rng.uniform(-fovx/2 * cov, fovx/2 * cov) * CV_PI / 180);
|
||||
float av = static_cast<float>(rng.uniform(-fovy/2 * cov, fovy/2 * cov) * CV_PI / 180);
|
||||
|
||||
Point3f p;
|
||||
p.z = std::cos(ah) * d1;
|
||||
p.x = std::sin(ah) * d1;
|
||||
p.y = p.z * std::tan(av);
|
||||
|
||||
Point3f pb1, pb2;
|
||||
generateBasis(pb1, pb2);
|
||||
|
||||
float cbHalfWidth = squareSize.width * patternSize.width * 0.5f;
|
||||
float cbHalfHeight = squareSize.height * patternSize.height * 0.5f;
|
||||
|
||||
float cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width;
|
||||
float cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height;
|
||||
|
||||
vector<Point3f> pts3d(4);
|
||||
vector<Point2f> pts2d(4);
|
||||
for(;;)
|
||||
{
|
||||
pts3d[0] = p + pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;
|
||||
pts3d[1] = p + pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;
|
||||
pts3d[2] = p - pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;
|
||||
pts3d[3] = p - pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;
|
||||
|
||||
/* can remake with better perf */
|
||||
projectPoints(pts3d, rvec, tvec, camMat, distCoeffs, pts2d);
|
||||
|
||||
bool inrect1 = pts2d[0].x < bg.cols && pts2d[0].y < bg.rows && pts2d[0].x > 0 && pts2d[0].y > 0;
|
||||
bool inrect2 = pts2d[1].x < bg.cols && pts2d[1].y < bg.rows && pts2d[1].x > 0 && pts2d[1].y > 0;
|
||||
bool inrect3 = pts2d[2].x < bg.cols && pts2d[2].y < bg.rows && pts2d[2].x > 0 && pts2d[2].y > 0;
|
||||
bool inrect4 = pts2d[3].x < bg.cols && pts2d[3].y < bg.rows && pts2d[3].x > 0 && pts2d[3].y > 0;
|
||||
|
||||
if ( inrect1 && inrect2 && inrect3 && inrect4)
|
||||
break;
|
||||
|
||||
p.z *= 1.1f;
|
||||
}
|
||||
|
||||
Point3f zero = p - pb1 * cbHalfWidth - cbHalfHeight * pb2;
|
||||
|
||||
return generateChessBoard(bg, camMat, distCoeffs, zero, pb1, pb2,
|
||||
squareSize.width, squareSize.height, pts3d, corners);
|
||||
}
|
||||
|
||||
Mat ChessBoardGenerator::operator ()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs,
|
||||
const Size2f& squareSize, const Point3f& pos, vector<Point2f>& corners) const
|
||||
{
|
||||
cov = std::min(cov, 0.8);
|
||||
Point3f p = pos;
|
||||
Point3f pb1, pb2;
|
||||
generateBasis(pb1, pb2);
|
||||
|
||||
float cbHalfWidth = squareSize.width * patternSize.width * 0.5f;
|
||||
float cbHalfHeight = squareSize.height * patternSize.height * 0.5f;
|
||||
|
||||
float cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width;
|
||||
float cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height;
|
||||
|
||||
vector<Point3f> pts3d(4);
|
||||
vector<Point2f> pts2d(4);
|
||||
|
||||
pts3d[0] = p + pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;
|
||||
pts3d[1] = p + pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;
|
||||
pts3d[2] = p - pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;
|
||||
pts3d[3] = p - pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;
|
||||
|
||||
/* can remake with better perf */
|
||||
projectPoints(pts3d, rvec, tvec, camMat, distCoeffs, pts2d);
|
||||
|
||||
Point3f zero = p - pb1 * cbHalfWidth - cbHalfHeight * pb2;
|
||||
|
||||
return generateChessBoard(bg, camMat, distCoeffs, zero, pb1, pb2,
|
||||
squareSize.width, squareSize.height, pts3d, corners);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,43 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#ifndef CV_CHESSBOARDGENERATOR_H143KJTVYM389YTNHKFDHJ89NYVMO3VLMEJNTBGUEIYVCM203P
|
||||
#define CV_CHESSBOARDGENERATOR_H143KJTVYM389YTNHKFDHJ89NYVMO3VLMEJNTBGUEIYVCM203P
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
using std::vector;
|
||||
|
||||
class ChessBoardGenerator
|
||||
{
|
||||
public:
|
||||
double sensorWidth;
|
||||
double sensorHeight;
|
||||
size_t squareEdgePointsNum;
|
||||
double min_cos;
|
||||
mutable double cov;
|
||||
Size patternSize;
|
||||
int rendererResolutionMultiplier;
|
||||
|
||||
ChessBoardGenerator(const Size& patternSize = Size(8, 6));
|
||||
Mat operator()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, std::vector<Point2f>& corners) const;
|
||||
Mat operator()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, const Size2f& squareSize, std::vector<Point2f>& corners) const;
|
||||
Mat operator()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, const Size2f& squareSize, const Point3f& pos, std::vector<Point2f>& corners) const;
|
||||
Size cornersSize() const;
|
||||
|
||||
mutable std::vector<Point3f> corners3d;
|
||||
private:
|
||||
void generateEdge(const Point3f& p1, const Point3f& p2, std::vector<Point3f>& out) const;
|
||||
Mat generateChessBoard(const Mat& bg, const Mat& camMat, const Mat& distCoeffs,
|
||||
const Point3f& zero, const Point3f& pb1, const Point3f& pb2,
|
||||
float sqWidth, float sqHeight, const std::vector<Point3f>& whole, std::vector<Point2f>& corners) const;
|
||||
void generateBasis(Point3f& pb1, Point3f& pb2) const;
|
||||
|
||||
Mat rvec, tvec;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
+11
-8
@@ -211,13 +211,13 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename )
|
||||
case CHESSBOARD:
|
||||
case CHESSBOARD_SB:
|
||||
case CHESSBOARD_PLAIN:
|
||||
folder = string(ts->get_data_path()) + "cv/cameracalibration/";
|
||||
folder = string(ts->get_data_path()) + "cameracalibration/";
|
||||
break;
|
||||
case CIRCLES_GRID:
|
||||
folder = string(ts->get_data_path()) + "cv/cameracalibration/circles/";
|
||||
folder = string(ts->get_data_path()) + "cameracalibration/circles/";
|
||||
break;
|
||||
case ASYMMETRIC_CIRCLES_GRID:
|
||||
folder = string(ts->get_data_path()) + "cv/cameracalibration/asymmetric_circles/";
|
||||
folder = string(ts->get_data_path()) + "cameracalibration/asymmetric_circles/";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -681,8 +681,9 @@ TEST(Calib3d_AsymmetricCirclesPatternDetectorWithClustering, accuracy) { CV_Ches
|
||||
|
||||
TEST(Calib3d_ChessboardWithMarkers, regression_25806_white)
|
||||
{
|
||||
const cv::String dataDir = string(TS::ptr()->get_data_path()) + "cv/cameracalibration/";
|
||||
const cv::String dataDir = string(TS::ptr()->get_data_path()) + "cameracalibration/";
|
||||
const cv::Mat image = cv::imread(dataDir + "checkerboard_marker_white.png");
|
||||
ASSERT_FALSE(image.empty());
|
||||
|
||||
std::vector<Point2f> corners;
|
||||
const bool success = cv::findChessboardCornersSB(image, Size(9, 14), corners, CALIB_CB_MARKER);
|
||||
@@ -691,8 +692,9 @@ TEST(Calib3d_ChessboardWithMarkers, regression_25806_white)
|
||||
|
||||
TEST(Calib3d_ChessboardWithMarkers, regression_25806_black)
|
||||
{
|
||||
const cv::String dataDir = string(TS::ptr()->get_data_path()) + "cv/cameracalibration/";
|
||||
const cv::String dataDir = string(TS::ptr()->get_data_path()) + "cameracalibration/";
|
||||
const cv::Mat image = cv::imread(dataDir + "checkerboard_marker_black.png");
|
||||
ASSERT_FALSE(image.empty());
|
||||
|
||||
std::vector<Point2f> corners;
|
||||
const bool success = cv::findChessboardCornersSB(image, Size(9, 14), corners, CALIB_CB_MARKER);
|
||||
@@ -701,7 +703,7 @@ TEST(Calib3d_ChessboardWithMarkers, regression_25806_black)
|
||||
|
||||
TEST(Calib3d_CirclesPatternDetectorWithClustering, accuracy)
|
||||
{
|
||||
cv::String dataDir = string(TS::ptr()->get_data_path()) + "cv/cameracalibration/circles/";
|
||||
cv::String dataDir = string(TS::ptr()->get_data_path()) + "cameracalibration/circles/";
|
||||
|
||||
cv::Mat expected;
|
||||
FileStorage fs(dataDir + "circles_corners15.dat", FileStorage::READ);
|
||||
@@ -709,6 +711,7 @@ TEST(Calib3d_CirclesPatternDetectorWithClustering, accuracy)
|
||||
fs.release();
|
||||
|
||||
cv::Mat image = cv::imread(dataDir + "circles15.png");
|
||||
ASSERT_FALSE(image.empty());
|
||||
|
||||
std::vector<Point2f> centers;
|
||||
cv::findCirclesGrid(image, Size(10, 8), centers, CALIB_CB_SYMMETRIC_GRID | CALIB_CB_CLUSTERING);
|
||||
@@ -814,7 +817,7 @@ TEST(Calib3d_AsymmetricCirclesPatternDetector, regression_19498)
|
||||
|
||||
TEST(Calib3d_RotatedCirclesPatternDetector, issue_24964)
|
||||
{
|
||||
string path = cvtest::findDataFile("cv/cameracalibration/circles/circles_24964.png");
|
||||
string path = cvtest::findDataFile("cameracalibration/circles/circles_24964.png");
|
||||
Mat image = cv::imread(path);
|
||||
ASSERT_FALSE(image.empty()) << "Can't read image: " << path;
|
||||
|
||||
@@ -850,7 +853,7 @@ TEST(Calib3d_RotatedCirclesPatternDetector, issue_24964)
|
||||
}
|
||||
|
||||
TEST(Calib3d_CornerOrdering, issue_26830) {
|
||||
const cv::String dataDir = string(TS::ptr()->get_data_path()) + "cv/cameracalibration/";
|
||||
const cv::String dataDir = string(TS::ptr()->get_data_path()) + "cameracalibration/";
|
||||
const cv::Mat image = cv::imread(dataDir + "checkerboard_marker_white.png");
|
||||
|
||||
std::vector<Point2f> cornersMinimumSizeMatchesPatternSize;
|
||||
+1
-1
@@ -72,7 +72,7 @@ void CV_ChessboardDetectorTimingTest::run( int start_from )
|
||||
int idx, max_idx;
|
||||
int progress = 0;
|
||||
|
||||
filepath = cv::format("%scv/cameracalibration/", ts->get_data_path().c_str() );
|
||||
filepath = cv::format("%scameracalibration/", ts->get_data_path().c_str() );
|
||||
filename = cv::format("%schessboard_timing_list.dat", filepath.c_str() );
|
||||
cv::FileStorage fs( filename, FileStorage::READ );
|
||||
cv::FileNode board_list = fs["boards"];
|
||||
@@ -5,6 +5,7 @@
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts.hpp"
|
||||
#include "opencv2/3d.hpp"
|
||||
#include "opencv2/objdetect.hpp"
|
||||
|
||||
#include <random>
|
||||
|
||||
+4
-3
@@ -15,6 +15,7 @@ import org.opencv.core.Point;
|
||||
import org.opencv.core.Scalar;
|
||||
import org.opencv.core.Size;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
import org.opencv.objdetect.Objdetect;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
@@ -124,8 +125,8 @@ public class CameraCalibrator {
|
||||
}
|
||||
|
||||
private void findPattern(Mat grayFrame) {
|
||||
mPatternWasFound = Calib.findCirclesGrid(grayFrame, mPatternSize,
|
||||
mCorners, Calib.CALIB_CB_ASYMMETRIC_GRID);
|
||||
mPatternWasFound = Objdetect.findCirclesGrid(grayFrame, mPatternSize,
|
||||
mCorners, Objdetect.CALIB_CB_ASYMMETRIC_GRID);
|
||||
}
|
||||
|
||||
public void addCorners() {
|
||||
@@ -135,7 +136,7 @@ public class CameraCalibrator {
|
||||
}
|
||||
|
||||
private void drawPoints(Mat rgbaFrame) {
|
||||
Calib.drawChessboardCorners(rgbaFrame, mPatternSize, mCorners, mPatternWasFound);
|
||||
Objdetect.drawChessboardCorners(rgbaFrame, mPatternSize, mCorners, mPatternWasFound);
|
||||
}
|
||||
|
||||
private void renderFrame(Mat rgbaFrame) {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/objdetect.hpp"
|
||||
#include "opencv2/core/utility.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#include "opencv2/core.hpp"
|
||||
#include <opencv2/core/utility.hpp>
|
||||
#include "opencv2/core/utility.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/3d.hpp"
|
||||
#include "opencv2/calib.hpp"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/videoio.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include <opencv2/objdetect/charuco_detector.hpp>
|
||||
#include "opencv2/objdetect.hpp"
|
||||
#include "opencv2/objdetect/charuco_detector.hpp"
|
||||
|
||||
#include <cctype>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "opencv2/3d.hpp"
|
||||
#include "opencv2/calib.hpp"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/objdetect.hpp"
|
||||
#include "opencv2/videoio.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/objdetect.hpp"
|
||||
#include "opencv2/objdetect/charuco_detector.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <opencv2/imgcodecs.hpp>
|
||||
#include <opencv2/videoio.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/objdetect.hpp>
|
||||
#include "opencv2/objdetect/charuco_detector.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/3d.hpp>
|
||||
#include <opencv2/calib.hpp>
|
||||
#include <opencv2/objdetect.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/3d.hpp>
|
||||
#include <opencv2/objdetect.hpp>
|
||||
#include <opencv2/calib.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/3d.hpp>
|
||||
#include <opencv2/calib.hpp>
|
||||
#include <opencv2/objdetect.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/3d.hpp>
|
||||
#include <opencv2/calib.hpp>
|
||||
#include <opencv2/objdetect.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
Reference in New Issue
Block a user