카테고리 없음

OpenCVSharp Undistort

파란김치 2023. 5. 15. 17:13
    public class Calibrator
    {
        Mat _cameraMatrix;
        Mat _distCoeffs;
        Mat _newCameraMatrix;
        private Calibrator()
        {

        }
        public static Calibrator FromFile(string savePath)
        {
            var res = new Calibrator();

            using (var sw = new StreamReader(savePath))
            {
                res._cameraMatrix = new Mat(3, 3, MatType.CV_64FC1);
                res._distCoeffs = new Mat(5, 1, MatType.CV_64FC1);
                res._newCameraMatrix = new Mat(3, 3, MatType.CV_64FC1);
                var temp = new List<Mat>()
                                {
                                    res._cameraMatrix,
                                    res._distCoeffs,
                                    res._newCameraMatrix
                                };

                for (int index = 0; index < temp.Count; index++)
                {
                    var m = temp[index];
                    for (int i = 0; i < m.Rows; i++)
                    {
                        for (int j = 0; j < m.Cols; j++)
                        {
                            var ss = sw.ReadLine();
                            m.Set(i, j, double.Parse(ss));
                        }
                    }
                }
            }
            return res;
        }
        public static Calibrator FromImages(string[] images, Size imgSize, Size ptrnSize, int interval = 30, int left_margin = 0, int top_margin = 0)
        {

            var res = new Calibrator();

            var imPts = res.GetimagePoints(images, ptrnSize);
            var objPts = res.GetObjectPoints(ptrnSize, imPts.Count);

            var camMat = new Mat<double>(3, 3);
            var distCoeffs = new Mat<double>(5, 1);
            Cv2.CalibrateCamera(objPts, imPts.Values, imgSize, camMat, distCoeffs, out Mat[] rvecs, out Mat[] tvecs);

            var newImageSize = new Size();
            var newCameraMatrix = Cv2.GetOptimalNewCameraMatrix(camMat, distCoeffs, imgSize, 1, newImageSize, out Rect validPixROI);

            res._cameraMatrix = camMat.Clone();
            res._distCoeffs = distCoeffs.Clone();
            res._newCameraMatrix = newCameraMatrix.Clone();
            return res;
        }
        public Mat Calibrate(Mat input)
        {
            return input.Undistort(_cameraMatrix, _distCoeffs, _newCameraMatrix);
        }
        public void Save(string savePath)
        {
            using (var sw = new StreamWriter(savePath))
            {
                var temp = new List<Mat>() { _cameraMatrix, _distCoeffs, _newCameraMatrix };
                foreach (var m in temp)
                {
                    for (int i = 0; i < m.Rows; i++)
                    {
                        for (int j = 0; j < m.Cols; j++)
                        {
                            var val = m.At<double>(i, j);
                            sw.WriteLine(val);
                        }
                    }
                }
            }
        }
        private Dictionary<string, Mat<Point2f>> GetimagePoints(string[] images, Size patternSize)
        {
            var res = new Dictionary<string, Mat<Point2f>>();
            foreach (var image in images.Distinct())
            {
                using (var img = new Mat(image, ImreadModes.Grayscale))
                {
                    var corners = new Mat();
                    var ret = Cv2.FindChessboardCorners(img, patternSize, corners);

                    if (ret)
                    {
                        Point2f[] ptArr;
                        corners.GetArray<Point2f>(out ptArr);
                        res.Add(image, Mat.FromArray(ptArr));
                    }
                }
            }
            return res;
        }
        private List<Mat<Point3f>> GetObjectPoints(Size patternSize, int cnt, int interval = 30, int left_margin = 0, int top_margin = 0)
        {
            var result = new List<Mat<Point3f>>();
            for (int index = 0; index < cnt; index++)
            {
                var object_points = new List<Point3f>();
                for (int j = 0; j < patternSize.Height; j++)
                {
                    for (int i = 0; i < patternSize.Width; i++)
                    {
                        object_points.Add(new Point3f(left_margin + i * interval, top_margin + j * interval, 0));
                    }
                }
                result.Add(Mat.FromArray(object_points.ToArray()));
            }
            return result;
        }
    }

 

var images = Directory.GetFiles(@"sampledir");

Calibrator ss = Calibrator.FromImages(images, new Size(1000, 500), new Size(11, 7));


for (int i = 0; i < images.Count(); i++)
{
    using (var data = new Mat(images[i], ImreadModes.Grayscale))
    {
        using (var sdfds = ss.Calibrate(data))
        {
            Cv2.ImShow("dafs", sdfds);
            Cv2.WaitKey(100);
        }
    }
}

 

Sample 이미지 : https://www.kaggle.com/datasets/danielwe14/stereocamera-chessboard-pictures/download?datasetVersionNumber=3