前提・実現したいこと
C# + OpenCvSharp3を用いて「カメラで撮像した歪みのあるグリッドパターンを理想点でキャリブレーションし、歪みのないグリッドパターン画像に変換」したいと考えています。
処理の流れは以下の通りとなります。
1.撮像したグリッドパターン画像を読み込み、円の中心点の座標を検出
2.中心点の座標に対応する理想点の座標を入力
3.上記の座標値からカメラ行列を求め、理想点の位置に変換するよう、射影変換(WarpPerspective())を行う。
発生している問題・エラーメッセージ
テスト用に作成した画像では上手くいっているように見えたのですが、実際のカメラから取得する画像だと、左右上下に歪みが残っている状況となっています。(添付とは別のカメラ画像です。サイズとしては5000×5000 pixel程度になります)
本件、ソースコードに何か問題があるのでしょうか?
または、理想点にキャリブレーションするのであれば、この方法が良いというものがあれば、ご教授のほど、よろしくお願いいたします。
該当のソースコード
Mat src_img = new Mat();
string path = @"..\src_img.jpg"; src_img = new Mat(path, ImreadModes.Color); SimpleBlobDetector.Params param = new SimpleBlobDetector.Params(); param.MaxArea = 100000; SimpleBlobDetector.Create(param); Mat current = src_img; Cv2.CvtColor(src_img, current, ColorConversionCodes.BGR2GRAY); OpenCvSharp.Size pattern = new OpenCvSharp.Size(7, 5); var disPts = new List<MatOfPoint2f>(); MatOfPoint2f grid = new MatOfPoint2f(); bool isFoundCorner; isFoundCorner = Cv2.FindCirclesGrid(current, pattern, OutputArray.Create(grid), FindCirclesGridFlags.SymmetricGrid, SimpleBlobDetector.Create(param)); disPts.Add(grid); var object_points = new List<Point3f>(); for (int i = 0; i < 5; i++) { for (int j = 0; j < 7; j++) { object_points.Add(new Point3f(99 + j * 100, 99 + i * 100, 0.0F)); } } var objects = new List<MatOfPoint3f>(); MatOfPoint3f oPointMat = new MatOfPoint3f(7 * 5, 1, object_points.ToArray()); objects.Add(oPointMat); Mat distCoeffs = new Mat(5, 1, MatType.CV_64F); Mat[] rvecs; Mat[] tvecs; Mat intrinsic = new Mat(3, 3, MatType.CV_64F); OpenCvSharp.Size imgsize = new OpenCvSharp.Size(src_img.Width, src_img.Height); Cv2.CalibrateCamera(objects, disPts, imgsize, intrinsic, distCoeffs, out rvecs, out tvecs); Mat tempImg = new Mat(); Cv2.Undistort(images[0], tempImg, intrinsic, distCoeffs); var transData = new double[] { 0, 0, tvecs[0].At<double>(0), 0, 0, tvecs[0].At<double>(1), 0, 0, tvecs[0].At<double>(2) }; Mat translate = new Mat(3, 3, MatType.CV_64F, transData); Mat rotation = new Mat(); Cv2.Rodrigues(rvecs[0], rotation); Mat transRot = new Mat(3, 3, MatType.CV_64F); rotation.Col.Get(0).CopyTo(transRot.Col.Get(0)); rotation.Col.Get(1).CopyTo(transRot.Col.Get(1)); translate.Col.Get(2).CopyTo(transRot.Col.Get(2)); Mat dist_img = new Mat(); Mat matPerspective = intrinsic * transRot; Cv2.WarpPerspective(tempImg, dist_img, matPerspective, imgsize ,InterpolationFlags.WarpInverseMap); Cv2.ImShow("CalWARP", dist_img); Cv2.ImWrite(@"..\dist_img.jpg", dist_img);
試したこと
途中で作成したカメラ行列のパラメータを編集しましたが、樽型に拡大していくだけで、理想の効果は得られませんでした。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/12/22 01:18
2019/12/23 01:13