본문 바로가기

C#

c# Emgu 카메라 칼리브레이션 요점 정리

요점만..





위의 사진을 사용하여 키보드 [1], [3] 을 번갈아 누르면, 점차 정확한 이미지를 얻을 수 있다.




위의 이미지는 대략 10번 정도 반복한 결과 이다.

원리는 컬리브레이션 결과를 다시 컬리브레이션 하는 반복 과정 이다.



using Emgu.CV;
using Emgu.CV.Structure;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace CCT_form
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.Load += Form1_Load;
        }
        private Size patternSize = new Size(9, 6);
        private Image<Gray, byte> raw_image;
        void Form1_Load(object sender, EventArgs e)
        {
            raw_image = new Image<Gray, byte>(@"C:\temp\ChessBoard-1.jpg");
            this.pictureBox1.Image = raw_image.Bitmap;

            this.KeyUp += Form1_KeyUp;
        }

        private PointF[][] corners = new PointF[1][];
        private void FindChessboard(Image<Gray, byte> org_img)
        {

            Image<Bgr, byte> c_image = org_img.Clone().Convert<Bgr, byte>();
            PointF[] _corners_1 = CameraCalibration.FindChessboardCorners(raw_image, patternSize, Emgu.CV.CvEnum.CALIB_CB_TYPE.ADAPTIVE_THRESH);
            raw_image.FindCornerSubPix(new PointF[1][] { _corners_1 }, new Size(11, 11), new Size(-1, -1), new MCvTermCriteria(30, 0.1));

            for (int i = 0; i < _corners_1.Length; ++i)
            {
                if (i < _corners_1.Length - 1)
                    c_image.Draw(new LineSegment2DF(_corners_1[i], _corners_1[i + 1]), new Bgr(Color.Red), 1);

                c_image.Draw(new CircleF(_corners_1[i], 3), new Bgr(Color.Cyan), 3);
            }

            corners[0] = _corners_1;
            this.pictureBox1.Image = c_image.Bitmap;
        }

        private IntrinsicCameraParameters IC = new IntrinsicCameraParameters();
        private ExtrinsicCameraParameters[] EX_Param;
        private void Calibration()
        {
            MCvPoint3D32f[][] refPoints = new MCvPoint3D32f[1][];//[patternSize.Width * patternSize.Height];
            MCvPoint3D32f[] _refPoints_1 = new MCvPoint3D32f[patternSize.Width * patternSize.Height];

            int c = 0;
            for (int i = 0; i < patternSize.Height; ++i)
            {
                for (int j = 0; j < patternSize.Width; ++j)
                {
                    _refPoints_1[c] = (new MCvPoint3D32f(j * 20.0f, i * 20.0f, 0.0f));
                    ++c;
                }
            }
            refPoints[0] = _refPoints_1;


            double resultValue = CameraCalibration.CalibrateCamera(refPoints, corners, raw_image.Size, IC, Emgu.CV.CvEnum.CALIB_TYPE.CV_CALIB_RATIONAL_MODEL, new MCvTermCriteria(30, 0.1), out EX_Param);
            Console.WriteLine("calib result : " + resultValue);


            Matrix<float> map_x, map_y;
            IC.InitUndistortMap(raw_image.Width, raw_image.Height, out map_x, out map_y);

            Image<Gray, byte> blankImage = raw_image.CopyBlank();
            CvInvoke.cvRemap(raw_image, blankImage, map_x, map_y, 0, new MCvScalar(0));
            raw_image = blankImage.Copy();

            this.pictureBox1.Image = raw_image.Bitmap;
        }

        void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.D1)
            {
                FindChessboard(raw_image);
            }

            if (e.KeyCode == Keys.D2)
            {

            }

            if (e.KeyCode == Keys.D3)
            {
                Calibration();
            }
        }
    }
}