c# OpenCV 棋盘格

参考1
在这里插入图片描述

代码

绘制

        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();
        }

棋盘格处理

核心就是调用Cv2.FindChessboardCorners(Img, a, out corners);直接将内角点找出来就行了,直接输出的是一排(x,y),将其转化为二维矩阵更好用一些。然后将其减来减去,就得到了畸变值。

        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;
        }

画图

核心就是 chart1.Series[0].Points.AddXY(i + 1, ww[i]);添加点,其他信息都直接设置好了

        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();
        }

实验现象

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/chengcao123/article/details/128326350