c# OpenCV checkerboard

Reference 1
Insert image description here

code

draw

        private void button1_Click(object sender, EventArgs e)
        {
    
    
            OpenFileDialog openFile = new OpenFileDialog();
            //GetType().Assembly.Location:获取当前进程的完整路径,包含文件名。
            openFile.InitialDirectory = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), "Images");
            openFile.Filter = "All|*.*";
            if (openFile.ShowDialog() == DialogResult.OK)
            {
    
    
                Img = Cv2.ImRead(openFile.FileName);
            }

            //首先裁剪图片右下角那块 输出为img2
            //x=0在图片最左边 y=0在最上面 取的是矩形的左上顶点
            int kuan = Img.Width / 2;
            int gao=Img.Height /2 ;
            //gao= 720;
            MessageBox.Show(Img.Height.ToString());
            Rect rect = new Rect();
            rect.X = kuan-180;
            rect.Width = kuan+50;
            rect.Y =gao-180;
            rect.Height = gao+180;
            Mat img2= new Mat(Img,rect);
            Cv2.ImShow("裁剪", img2);

            //处理
            myFind_chessboard(img2);
            //chart上画图
            drawLine();
        }

Checkerboard processing

The core is to call Cv2.FindChessboardCorners(Img, a, out corners); just find the inner corner points directly. The direct output is a row of (x, y). It is more useful to convert it into a two-dimensional matrix. Then subtract it and you get the distortion value.

        Mat Img;
        List<double> ww = new List<double>();
        List<double> hh = new List<double>();
        public static int xP = 0;
        public static int yP = 0;
        public static int hxP = xP / 2;//直接这样除是不行的 输出为0 
        public static int hyP = yP / 2;
      void myFind_chessboard(Mat Img)
        {
    
    
            xP = int.Parse(textBox1.Text);//x和y方向的总点数
            yP = int.Parse(textBox2.Text);
            hxP = xP / 2;//需要在这里除 9/2=4
            hyP = yP / 2;


            //在Img中找内角点
            Point2f[] corners;
            Size a = new OpenCvSharp.Size(hxP, hyP);//第一个宽 第二个高
            bool isFound = Cv2.FindChessboardCorners(Img, a, out corners);
            MessageBox.Show("是否找出:" + isFound);

            //复制一张img 为img3 在img3上将内角点画出来
            Mat img2 = new Mat();
            Img.CopyTo(img2);
            //我觉得corners应该是一排的(x,y)
            Cv2.DrawChessboardCorners(img2, a, corners, isFound);
            Cv2.ImShow("img2", img2);
            

            if (isFound)
            {
    
    
                //Corners2:将找到的corners按照一排多少个,矩阵这样的格式进行排列
                Point2f[,] Corners2 = new Point2f[hxP, hyP];
                Corners2 = OneD_2<Point2f>(corners, hyP);
                for(int i = 0;i < hxP -1; i++)//列
                {
    
    
                    for(int j = 0;j< hyP -1; j++)//行
                    {
    
    
                        double detaX = 0;
                        double detaY = 0;
                        Point centerY = new Point();
                        Point centerX = new Point();

                            detaX = Corners2[j, i + 1].X - Corners2[j, i].X;
                            detaY = Corners2[j + 1, i].Y - Corners2[j, i].Y;
                            centerX = center((Point)Corners2[j, i], (Point)Corners2[j, i + 1]);
                            centerY = center((Point)Corners2[j, i], (Point)Corners2[j + 1, i]);
                        //Cv2.PutText(Img, detaX.ToString("0.000"), (OpenCvSharp.Point)Corners2[j, i], HersheyFonts.HersheySimplex, 0.5, Scalar.Red, 2, LineTypes.Link4);
                       //应该是中间向边上畸变值不断减少
                        Cv2.PutText(Img, detaX.ToString("0.000"), centerX, HersheyFonts.HersheySimplex, 0.5, Scalar.Red, 2, LineTypes.Link4);
                        Cv2.PutText(Img, detaY.ToString("n4"), centerY, HersheyFonts.HersheySimplex, 0.5, Scalar.Red, 2, LineTypes.Link4);

                            if (i == 1)//第一列 也就是y轴上的那么几个
                                hh.Add(detaY * 0.00175 / 3.0);
                            if (j == 1)//第一行 也就是x轴上的那么几个
                                ww.Add(detaX * 0.00175 / 3.0);
                            
                        Cv2.Circle(Img, (OpenCvSharp.Point)Corners2[j,i], 5, Scalar.Red, -1, LineTypes.Link8);                       
                    }

                }

                Cv2.ImShow("img", Img);
                Cv2.WaitKey(0);
            }
        }
        /// <summary>
        /// 取中心点
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <returns></returns>
        public Point center(Point p1, Point p2)
        {
    
    
            return new Point((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2);
        }
        /// <summary>
        /// 一维数组转2维数组(矩阵)
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="len">矩阵行数</param>
        /// <returns></returns>
        public static T[,] OneD_2<T>(T[] obj, int len)
        {
    
    
            if (obj.Length % len != 0)
                return null;//这样就是无法做一个矩阵
            int width = obj.Length / len;
            T[,] obj2 = new T[len, width];
            for (int i = 0; i < obj.Length; i++)
            {
    
    
                obj2[i / width, i % width] = obj[i];
            }
            return obj2;
        }

Draw a picture

The core is chart1.Series[0].Points.AddXY(i + 1, ww[i]); add points, and other information is set directly

        private void drawLine()
        {
    
    
            chart1.Visible = true;//在没有显示值之前先隐藏
            int min = Math.Min(hh.Count, ww.Count);
            //输入数据
            for (int i = 0; i < min; i++)
            {
    
    
                chart1.Series[0].Points.AddXY(i + 1, ww[i]);
                chart1.Series[1].Points.AddXY(i + 1, hh[i]);
            }

            ww.Clear();
            hh.Clear();
        }

Experimental phenomena

Insert image description here
Insert image description here
Insert image description here

Guess you like

Origin blog.csdn.net/chengcao123/article/details/128326350