Converting 2D points into 3D then connect 3D lines together

asked 2017-12-23 14:46:14 -0600

Ahmed gravatar image

Hi All, I'm trying to convert 2D points using camera matrix then I find the 3D lines using cv::fitLine, then I try to project them back into 2D to visualize the lines. but I get only two points and all the projected points are just in one place.

//Generate a camera intrinsic matrix
            Mat K = (Mat_<double>(3, 3)
                << 1600, 0,src.cols/2,
                0, 1600,src.rows/2,
                0, 0, 1);



            Mat invCameraIntrinsics = K.inv();
            cout << "inv" << invCameraIntrinsics;
            std::vector<cv::Vec3d> pointsTransformed3D;

            std::vector<cv::Vec3d> points3D;
            for (int i = 0; i < corners.size(); i++)
            {
                cv::Vec3d pt;

                pt[2] = 1.0f;

                pt[0] = (corners[i].x );
                pt[1] = (corners[i].y );

                points3D.push_back(pt);
            }

            cv::transform(points3D, pointsTransformed3D, invCameraIntrinsics);


            std::vector<Vec6f> outputlines;
            for (int i = 0; i < pointsTransformed3D.size(); i++)
            {   
                cv::Vec3f p1;
                p1[0] = pointsTransformed3D[i][0];
                p1[1] = pointsTransformed3D[i][1];
                p1[2] = pointsTransformed3D[i][2];
                for (int j = i + 1; j < pointsTransformed3D.size(); j++)
                {

                    cv::Vec3f p2;
                    p2[0] = pointsTransformed3D[j][0];
                    p2[1] = pointsTransformed3D[j][1];
                    p2[2] = pointsTransformed3D[j][2];

                    for (int b = j + 1; b < pointsTransformed3D.size(); b++)
                    {
                        cv::Vec3f p3;
                        p3[0] = pointsTransformed3D[b][0];
                        p3[1] = pointsTransformed3D[b][1];
                        p3[2] = pointsTransformed3D[b][2];

                        std::vector<cv::Vec3f> lines;

                        lines.push_back(p1);
                        lines.push_back(p2);
                        lines.push_back(p3);

                        Vec6f lineOutput;
                        cv::fitLine(lines, lineOutput, CV_DIST_L2, 0, 0.01, 0.01);

                        outputlines.push_back(lineOutput);

                    }
                }
            }

Mat rvec = (Mat_<double>(3, 3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);
            Mat tvec = (Mat_<double>(3, 1) << 0, 0, 0);


            //Project the 3D Point onto 2D plane
            std::vector<cv::Point2d> points_2d;
            std::vector<cv::Point3d> points_3d;

            for (int i = 0; i < pointsTransformed3D.size(); i++)
            {
                cv::Point3d pt; 
                pt.x = (outputlines[i][0]);
                pt.y = (outputlines[i][1]);
                pt.z = (outputlines[i][2]);
                points_3d.push_back(pt);
            }

            projectPoints(points_3d, rvec, tvec, K, Mat(), points_2d);

            for (size_t i = 0; i < points_2d.size(); i++)
            {
                cv::Point2d pt;

                pt.x = points_2d[i].x;
                pt.y = points_2d[i].y;

                cv::circle(src, pt, 10, cv::Scalar(255, 0, 255), -1);
            }
edit retag flag offensive close merge delete

Comments

1

Are you familiar at all with OpenGL? Here is code to get the modelviewprojection matrix: http://answers.opencv.org/question/17...

To get a 3D point to 2D screen coordinates, one must first multiply the matrix and the 3D point -- gl_Position = mvp_matrix*vec4(position, 1);. Then one must convert from clip space to NDC space. Your idea of using the inverse matrix to convert from 2D to 3D seems to be logical, but I don't know if it's correct.

sjhalayka gravatar imagesjhalayka ( 2017-12-23 21:55:48 -0600 )edit

Thanks so much for your comment. But how would I convert from 2D o 3D ?

Ahmed gravatar imageAhmed ( 2017-12-24 03:28:31 -0600 )edit

Sorry, I’m not good enough at OpenCV to give you an answer. But, if you’re planning on drawing a line between two points, you’re going to need the 2D screen coordinates, not the 3D world coordinates.

Anyway, here is some code to convert from screen space to clip space, the reverse process being conversion from clip space to screen space: https://www.opengl.org/discussion_boa...

sjhalayka gravatar imagesjhalayka ( 2017-12-24 15:09:21 -0600 )edit