카테고리 없음
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