CvInvoke.Undistort Делает изображение более искаженным, а не меньшим - PullRequest
0 голосов
/ 19 апреля 2020

Я впервые работаю с OpenCV. Приведенный ниже код использует пакет Emgu, но я также попробовал его с помощью OpenCVSharp и получил точно такие же результаты.

Я калибрую камеру, используя 6 фотографий с шахматной доски, затем использую калибровку, чтобы удалить изображение. Тестовое изображение - это фотография какой-то бумаги в квадрате. Камера на самом деле не очень искажена - я не могу сказать, что она искажена на глаз, только когда я рисую прямую линию над линиями в программе рисования.

Однако - получающееся изображение выходит из-под контроля более искаженный, чем оригинал - добавление большого количества бочкообразных искажений.

Когда я запускаю закомментированные строки, DrawChessboardCorners показывают, что он точно определяет точки.

Что я делаю здесь не так?

       static void Main(string[] args)
        {

            Size patternSize = new Size(9, 6);
            List<VectorOfPointF> ListOfCornerPoints = new List<VectorOfPointF>();
            DirectoryInfo dir = new DirectoryInfo(@"Z:\Simon\Dropbox\Apps\OpenCVPlay\Image Processing\Chessboard Pattern Photos With Pixel");

            Size calibrationImageSize = new Size(0,0) ;

            foreach (var file in dir.GetFiles())
            {
                VectorOfPointF corners = new VectorOfPointF();
                var calibrationImage = new Image<Rgb, byte>(file.FullName);

                bool find = CvInvoke.FindChessboardCorners(calibrationImage, patternSize, corners, CalibCbType.AdaptiveThresh | CalibCbType.FilterQuads);

                //CvInvoke.DrawChessboardCorners(calibrationImage, patternSize, corners, find);
                //calibrationImage.Save(@"Z:\Simon\Dropbox\Apps\OpenCVPlay\Image Processing\Chessboard Pattern Photos With Pixel\test\" + file.Name);

                ListOfCornerPoints.Add(corners);

                calibrationImageSize = calibrationImage.Size;
            }

            PointF[][] arrayOfCornerPoints = ListOfCornerPoints.Select(a => a.ToArray()).ToArray();

            var modelPoints = CreateModelPoints(ListOfCornerPoints.Count, patternSize.Width, patternSize.Height);

            var arrayOfModelPoints = modelPoints.Select(a => a.ToArray()).ToArray();

            Matrix<double> cameraDistortionCoeffs = new Matrix<double>(5, 1);
            Matrix<double> cameraMatrix = new Matrix<double>(3, 3);

            Mat[] rotationVectors;
            Mat[] translationVectors;

            CvInvoke.CalibrateCamera(
                arrayOfModelPoints,
                arrayOfCornerPoints,
                calibrationImageSize,
                cameraMatrix,
                cameraDistortionCoeffs,
                CalibType.Default,
                new MCvTermCriteria(),
                out rotationVectors,
                out translationVectors);

            var imageToProcess = new Image<Rgb, byte>(@"Z:\Simon\Dropbox\Apps\OpenCVPlay\Image Processing\Test data\squarePaper.jpg");
            Rectangle Rect2 = new Rectangle();
            var newCameraMatrix = CvInvoke.GetOptimalNewCameraMatrix(cameraMatrix, cameraDistortionCoeffs, calibrationImageSize, 1, imageToProcess.Size, ref Rect2, true);

            Image<Rgb, byte> processedImage = imageToProcess.Clone();
            CvInvoke.Undistort(imageToProcess, processedImage, cameraMatrix, cameraDistortionCoeffs);

            processedImage.Save(@"Z:\Simon\Dropbox\Apps\OpenCVPlay\Image Processing\Test data\squarePaperFixed.jpg");

        }



        static List<List<MCvPoint3D32f>> CreateModelPoints(int length, int chessboardCols, int chessboardRows)
        {
            var modelPoints = new List<List<MCvPoint3D32f>>();
            for (var k = 0; k < length; k++)
            {
                var chessboard = new List<MCvPoint3D32f>();
                for (var y = 0; y < chessboardRows; y++)
                {
                    for (var x = 0; x < chessboardCols; x++)
                    {
                        chessboard.Add(new MCvPoint3D32f(x, y, 0));
                    }
                }
                modelPoints.Add(chessboard);
            }
            return modelPoints;
        }


...