简体   繁体   中英

OpenCV and reading data from OutputArrays or (Mat)

I have a couple of problems with OpenCV's own functions for PnP and Rodrigues formula. I think it is related to cv::solvePnPRansac()

 cv::Mat w = cv::Mat::zeros(3,1,CV_32FC1);
 cv::Mat t = cv::Mat::zeros(3,1,CV_32FC1);
 std::vector<float> distortion = {0,0,0,0};

 std::vector<cv::Point3f> tmp1 = eig_vec_to_cv3(pts);
 std::vector<cv::Point2f> tmp2 =  eig_vec_to_cv2(pixels);

 cv::solvePnPRansac(tmp1, tmp2, eig_mat_2_cv(K),distortion, w, t,false, 100, 2.0f);

 cv::Mat R_ = cv::Mat::zeros(3,3,CV_32FC1);
 cv::Rodrigues(w,R_);

 std::cout<<"R_"<<std::endl;
 std::cout<<R_<<std::endl;
 std::cout<<R_.at<float>(0,0)<<std::endl;

For std::cout<<R_<<std::endl it looks ok, but R_.at<float>(0,0) gives a trash number, like the memory is not allocated. The same holds for w and t .

However, if I make like this:

cv::Mat w_ = cv::Mat(3,1,cv_32FC1);
w.at<float>(0,0) = 0.2;
w.at<float>(0,1) = 0.4;
w.at<float>(0,2) = 0.3;

cv::Rodrigues(w_,R_);

std::cout<<"R_"<<std::endl;
std::cout<<R_<<std::endl;
std::cout<<R_.at<float>(0,0)<<std::endl;

It works just fine.

This is a minimal (non)-working example:

#include <opencv2/calib3d.hpp>
#include <opencv2/opencv.hpp>
#include <vector>

int main()
{
    cv::Mat w = cv::Mat(3,1,CV_32FC1);
    cv::Mat t = cv::Mat(3,1, CV_32FC1);

    std::vector<cv::Point3f> tmp1;
    std::vector<cv::Point2f> tmp2;

    for (int k = 0; k < 10; ++k)
    {
        cv::Point3f p1(0.2f+k, 0.3f-k, 7.5f-k);
        cv::Point2f p2(3.2f*k, 4.5f/k);
        tmp1.push_back(p1);
        tmp2.push_back(p2);
    }

    cv::Mat K = cv::Mat::zeros(3,3,CV_32FC1);
    K.at<float>(0,0) = 525.0;
    K.at<float>(0,2) = 234.5;
    K.at<float>(1,1) = 525;
    K.at<float>(1,2) = 312.5;
    K.at<float>(2,2) = 1.0f;

    std::vector<float> distortion = {0,0,0,0};

    cv::solvePnPRansac(tmp1, tmp2, K,distortion, w, t,false, 100, 2.0f);

    std::cout<<w<<std::endl;
    cv::Mat R = cv::Mat::zeros(3,3,CV_32FC1);
    cv::Rodrigues(w,R);
    std::cout<<R<<std::endl;

    std::cout<<R.at<float>(0,0)<<std::endl;
    return 0;
}

Compiled with

g++ main.cpp -I /usr/local/include/opencv4/ -o test -L /usr/local/lib/ -lopencv_calib3d -lopencv_core

The reason is that the function cv::Rodrigues creates the output matrix of type CV_64FC1 . So the values have to be read as follows:

std::cout<<R.at<double>(0,0)<<std::endl;

Even if we pre-allocate the output matrix to be of any other type ( say CV_32FC1 ), it will be reallocated by cv::Rodrigues to type CV_64FC1 .

In my opinion, the OpenCV documentation lacks clarity about the input and output types of many functions. In cases like these, one must be sure about the output types by printing the return value of Mat::type() function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM