'Missing y-values from `ProjectPoints`

Translating c++ code that uses OpenCV to C# (OpenCvSharp).

I stumbled upon Cv2.ProjectPoints() that is not working as expected: The result seems to be missing the y-dimension.

The result should be a 4*2 list:

projectedCorners2d = [
589.0155, 321.80783;
524.12396, 785.2381;
1038.7371, 812.94391;
1076.3754, 338.71786]

but i actually get a 4*1 list:

projectedCorners2d = [
589.565955955177,
524.185987630325,
1038.84068610911,
1076.32524853965]

I tried to translate the parameters as careful as i possibly can, but somewhere along the way i messed up.

This is the C# code i am using to replicate this problem.

class OpenCVWrapper
    {
        static void Main(string[] args)
        {
            var program = new OpenCVWrapper();
            program.ProjectPoints();
            System.Console.ReadKey();
        }

        private void ProjectPoints()
        {
            /*
             boardCorners3d =
             [-100, -100, 0;
             -100, 100, 0;
             100, 100, 0;
             100, -100, 0]
             */
            var boardCorners3d = new Mat(4, 3, MatType.CV_64FC1);
            boardCorners3d.Set<double>(0, 0, -100);
            boardCorners3d.Set<double>(0, 1, -100);
            boardCorners3d.Set<double>(0, 2, 0);
            boardCorners3d.Set<double>(1, 0, -100);
            boardCorners3d.Set<double>(1, 1, 100);
            boardCorners3d.Set<double>(1, 2, 0);
            boardCorners3d.Set<double>(2, 0, 100);
            boardCorners3d.Set<double>(2, 1, 100);
            boardCorners3d.Set<double>(2, 2, 0);
            boardCorners3d.Set<double>(3, 0, 100);
            boardCorners3d.Set<double>(3, 1, -100);
            boardCorners3d.Set<double>(3, 2, 0);

            /*
            projMatrix =
            [3127.547993344112, 0, 932.2602964508543;
            0, 3124.497278429708, 619.9096446889635;
            0, 0, 1]
            */
            var projMatrix = new Mat(3, 3, MatType.CV_64FC1);
            projMatrix.Set<double>(0, 0, 3127.547993344112);
            projMatrix.Set<double>(0, 1, 0);
            projMatrix.Set<double>(0, 2, 932.2602964508543);
            projMatrix.Set<double>(1, 0, 0);
            projMatrix.Set<double>(1, 1, 3124.497278429708);
            projMatrix.Set<double>(1, 2, 619.9096446889635);
            projMatrix.Set<double>(2, 0, 0);
            projMatrix.Set<double>(2, 1, 0);
            projMatrix.Set<double>(2, 2, 1);

            /*
            R_mat_boardToProj =
            [0.9911558918579844, -0.0874228071603788, 0.09983611983346924;
            0.04546793729222496, 0.9305152298212276, 0.3634199688365212;
            -0.1246702238451264, -0.3556665008950758, 0.9262605872147747]
            */
            var R_mat_boardToProj = new Mat(3, 3, MatType.CV_64FC1);
            R_mat_boardToProj.Set<double>(0, 0, 0.9911558918579844);
            R_mat_boardToProj.Set<double>(0, 1, -0.0874228071603788);
            R_mat_boardToProj.Set<double>(0, 2, 0.09983611983346924);
            R_mat_boardToProj.Set<double>(1, 0, 0.04546793729222496);
            R_mat_boardToProj.Set<double>(1, 1, 0.9305152298212276);
            R_mat_boardToProj.Set<double>(1, 2, 0.3634199688365212);
            R_mat_boardToProj.Set<double>(2, 0, -0.1246702238451264);
            R_mat_boardToProj.Set<double>(2, 1, -0.3556665008950758);
            R_mat_boardToProj.Set<double>(2, 2, 0.9262605872147747);

            /*
            T_mat_boardToProj =
            [-50.01808646798166;
            -24.35497443342842;
            1231.960732054335]
              */
            var T_mat_boardToProj = new Mat(3, 1, MatType.CV_64FC1);
            T_mat_boardToProj.Set<double>(0, -50.01808646798166);
            T_mat_boardToProj.Set<double>(1, -24.35497443342842);
            T_mat_boardToProj.Set<double>(2, 1231.960732054335);

            /*
            projDistCoeff =
            [-0.04682676156309139, -0.06223329334710802, -0.004916064378016475, -0.001689106057458739, 0]
            */
            var projDistCoeff = new Mat(1, 5, MatType.CV_64FC1);
            projDistCoeff.Set<double>(0, -0.04682676156309139);
            projDistCoeff.Set<double>(1, -0.06223329334710802);
            projDistCoeff.Set<double>(2, -0.004916064378016475);
            projDistCoeff.Set<double>(3, -0.001689106057458739);
            projDistCoeff.Set<double>(4, 0);

            // without jacobian
            var projectedCorners2d = new Mat();
            Cv2.ProjectPoints(boardCorners3d, R_mat_boardToProj, T_mat_boardToProj, projMatrix, projDistCoeff, projectedCorners2d);

            /*
            projectedCorners2d =
             [589.0155, 321.80783;
             524.12396, 785.2381;
             1038.7371, 812.94391;
             1076.3754, 338.71786]
            */
            PrintMat(projectedCorners2d, "projectedCorners2d");        

            System.Console.WriteLine("Finished");
        }

        private static void PrintMat(Mat mat, string objectName = "")
        {
            string matString = objectName + " = [\n";
            for (var rowIndex = 0; rowIndex < mat.Rows; rowIndex++)
            {
                for (var colIndex = 0; colIndex < mat.Cols; colIndex++)
                {
                    matString += mat.At<double>(rowIndex, colIndex) + ", ";
                }

                matString += "\n";
            }

            matString += "]";

            System.Console.WriteLine(matString);
        }
    }

The commented values are the values printed from c++ using

cout << "projectedCorners2d = " << endl << " " << projectedCorners2d << endl << endl;


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source