Skip to content

[GSoC23] Support of mixed model in stereo calibration and multi-view calibration#24052

Open
lpanaf wants to merge 51 commits intoopencv:5.xfrom
lpanaf:mixed_model
Open

[GSoC23] Support of mixed model in stereo calibration and multi-view calibration#24052
lpanaf wants to merge 51 commits intoopencv:5.xfrom
lpanaf:mixed_model

Conversation

@lpanaf
Copy link
Copy Markdown
Contributor

@lpanaf lpanaf commented Jul 24, 2023

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • 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

Summary

This is the major pull request for the project "Multi-camera calibration part 2" in GSoC 2023. This links to the final report of the project. For details of how the project was extended can be found there.

The major contribution is to add the support for a mixed model of pinhole and fisheye camera models, and the support of calibrating cameras without constraints of overlapping field of view and complete.

The documentation is also improved with debugging advice on multi-camera calibration added. This link and this correspond to the documentation for the implemented registerCameras. This links to the documentation of the multiview calibration funtion. As for the tutorial, it can be found here.

Besides, some self captured data can be found in the opencv_extra (currently in pull request 1089).

@asmorkalov asmorkalov added category: calib3d GSoC pr: needs test New functionality requires minimal tests set labels Jul 27, 2023
{
int cn = rvecs.channels();
int depth = rvecs.depth();
if( (depth != CV_32F && depth != CV_64F) ||
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use CV_Assert here.

{
int cn = tvecs.channels();
int depth = tvecs.depth();
if( (depth != CV_32F && depth != CV_64F) ||
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CV_Assert

TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6) );

// TODO: add documentation for this
CV_EXPORTS_AS(stereoCalibrateExtrinsicExtended) double stereoExtrinsicCalibrate( InputArrayOfArrays objectPoints,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stereo is bad choice for the function name:

  • You cannot get real stereo if cameras have different type.
  • The function just registers two cameras, but does not run intrinsics tuning.

I propose to name it registerCameras.

Comment on lines +1330 to +1331
cv::fisheye::undistortPoints(imgpt_ik, imagePointsNormalized, cameraMatrix, distCoeffs, noArray(), cameraMatrix);
solvePnP(objpt_i, imagePointsNormalized, cameraMatrix, noArray(), rv, T[k], false, SOLVEPNP_ITERATIVE);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ivashmak @lpanaf I propose to add fisheye overload for solvePnP to namespace fisheye.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to make a separate function within fisheye namespace that takes as input distorted points from fisheye camera, internally undistorts them and runs the PnP solver?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general - yes. We have solvePnP that expects pinhole model. Let's introduce fisheye::solvePnP that expects fisheye camera model internally. The first implementation may be done with just undistort->solvePnP, if it produces reasonable result.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that makes sense. It looks like just a combination of two functions. @lpanaf will you do it since it is your pull request, or I can try to push here too?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add it, no problem :)

CV_EXPORTS_AS(stereoCalibrateExtrinsicExtended) double stereoExtrinsicCalibrate( InputArrayOfArrays objectPoints,
InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2,
InputOutputArray cameraMatrix1, InputOutputArray distCoeffs1,
bool isFisheye1,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense to rename the parameter to cameraModel and use int/enum. It's more future proof.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is reflected in the new code

@asmorkalov
Copy link
Copy Markdown
Contributor

@lpanaf Please rebase the PR on top of current 5.x. Last merge introduced some conflicts.

return cv::Mat(R_z * R_y * R_x);
};
const cv::Size board_size (5,4);
const cv::Size board_size (9, 7);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to split the test on 3 cases:

  • Pinhole only
  • Fisheye only
  • Mixed.

if (img_file.empty())
break;
std::cout << img_file << "\n";
if (img_file.empty()){
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}
else if (pattern_type == "charuco")
{
cv::cvtColor(img, img, cv::COLOR_BGR2GRAY);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed for Charuco.


///////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////// Register Cmeras /////////////////////////////////////
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

cv::Rodrigues(Rs[1], theR);

EXPECT_MAT_NEAR(theR, R_correct, 1e-2);
EXPECT_MAT_NEAR(Rs[1], R_correct, 1e-2);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Comment on lines -2051 to +2521
cv::Rodrigues(Rs[1], R);
Rs[1].copyTo(R);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

asmorkalov added a commit that referenced this pull request Feb 16, 2024
solvePnP implementation for Fisheye camera model #25028

Credits to Linfei Pan
Extracted from #24052

**Warning:** The patch changes Obj-C generator behaviour and adds "fisheye_" prefix for all ObjC functions from namespace.

### 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
- [x] The PR is proposed to the proper branch
- [x] 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

Co-authored-by: lpanaf <linpan@student.ethz.ch>
Co-authored-by: Vadim Levin <vadim.levin@xperience.ai>
((points.rows == pointsTotal[k] && points.cols*cn == 2) ||
(points.rows == 1 && points.cols == pointsTotal[k] && cn == 2)));

A[k] = Matx33d::eye();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like redundant. A[k] is always initialized with the following copyTo.

solvePnP(objpt_i, imgpt_ik, A[k], tdists[k], rv, T[k], false, SOLVEPNP_ITERATIVE );
else if (cameraModels[k] == CALIB_MODEL_FISHEYE){
fisheye::solvePnP(objpt_i, imgpt_ik, A[k], tdists[k], rv, T[k], false, SOLVEPNP_ITERATIVE );
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need assert in else branch.

if( matR.rows == 3 && matR.cols == 3 )
Rodrigues(matR, R);
else
matR.convertTo(R, CV_64F);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add assert on size here.

}
else if (rvecs.rows * rvecs.cols * rvecs.channels() == nimages * 3 )
{
Mat(Mat(srcR).t()).convertTo(r1d.row(i), rvecs.depth());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds strange.

if( !tvecs.empty() )
{
Vec3d srcT(param[idx + 3], param[idx + 4], param[idx + 5]);
Mat(Mat(srcT).t()).convertTo(t1d.row(i), tvecs.depth());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds strange.

asmorkalov added a commit that referenced this pull request Feb 26, 2024
RegisterCameras function for heterogenious cameras pair #25061

Credits to Linfei Pan
Extracted from #24052

### 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
- [x] The PR is proposed to the proper branch
- [x] 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

---------

Co-authored-by: lpanaf <linpan@student.ethz.ch>
@asmorkalov
Copy link
Copy Markdown
Contributor

Remaining pieces:

  • Case when the cameras see different parts of the same board.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category: calib3d GSoC pr: needs test New functionality requires minimal tests set

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants