C#联合OpenCV进行图像拼接

CsharpOpencv图像拼接

简单的图像拼接

简单粗暴的将两张图片水平或者垂直拼接

                                                                

            var image1= Cv2.ImRead("mandrill.png", ImreadModes.Color);      
            var image2 = Cv2.ImRead("lenna.png", ImreadModes.Color);
            //修改图片的尺寸
            Cv2.Resize(image1, image1, image2.Size());
            var Himagejoint = new Mat();
            var Vimagejoint = new Mat();
            var imagetuple = new Mat[] { image1, image2 };
            //水平拼接
            Cv2.HConcat(imagetuple, Himagejoint);
            //垂直拼接
            Cv2.VConcat(imagetuple, Vimagejoint);

            Cv2.ImShow("Himagejoint", Himagejoint);
            Cv2.ImShow("Vimagejoint", Vimagejoint);

水平拼接结果图 

垂直拼接结果图 

使用特征点+透视变换的方式进行拼接

参考C++版本https://www.jb51.net/article/255900.htm](https://www.jb51.net/article/255900.htm

参考Python版本https://www.jb51.net/article/214191.htm](https://www.jb51.net/article/214191.htm

使用C#代码进行(20230223代码更新)

//Mat Left = Cv2.ImRead(System.Windows.Forms.Application.StartupPath + "\\ImageTest\\pingjie1.jpg", ImreadModes.AnyColor);
            //Mat Right = Cv2.ImRead(System.Windows.Forms.Application.StartupPath + "\\ImageTest\\pingjie2.jpg", ImreadModes.AnyColor);
            var sift = SIFT.Create();
            var descriptors1 = new Mat<float>();
            var descriptors2 = new Mat<float>();
            sift.DetectAndCompute(Left, null, out var keypoints1, descriptors1);
            sift.DetectAndCompute(Right, null, out var keypoints2, descriptors2);
            var bf = new BFMatcher();
            var Matchs = bf.Match(descriptors1, descriptors2);
            if (Matchs.Length > 10)
            {
                //冒泡排序
                for (int i = 0; i < Matchs.Length - 1; i++)
                {
                    for (int j = 0; j < Matchs.Length - 1 - i; j++)
                    {
                        if (Matchs[j] > Matchs[j + 1])
                        {
                            var temp = Matchs[j];
                            Matchs[j] = Matchs[j + 1];
                            Matchs[j + 1] = temp;
                        }
                    }
                }
                List<DMatch> goodmatchs = new List<DMatch>();
                for (int i = 0; i < 50; i++)
                {
                    goodmatchs.Add(Matchs[i]);
                }
                Mat Dst_Images = new Mat();
                Cv2.DrawMatches(Left, keypoints1, Right, keypoints2, goodmatchs, Dst_Images, Scalar.Red, Scalar.Green, null, DrawMatchesFlags.NotDrawSinglePoints);
             //   Cv2.ImShow("goodmatchs", Dst_Images);

                //3特征点匹配
                List<Point2d> imagepoint1 = new List<Point2d> { };
                List<Point2d> imagepoint2 = new List<Point2d> { };
                for (int j = 0; j < goodmatchs.Count; j++)
                {
                    //查找特征点可连接处   变形
                    Point2d point2D = new Point2d(0, 0);
                    if (goodmatchs[j].TrainIdx > Matchs.Length)
                    {
                        continue;
                    }
                    point2D.X = Convert.ToDouble(keypoints1[goodmatchs[j].QueryIdx].Pt.X);
                    point2D.Y = Convert.ToDouble(keypoints1[goodmatchs[j].QueryIdx].Pt.Y);
                    imagepoint1.Add(point2D);
                    //查找特征点可连接处                          查找基准线
                    point2D.X = Convert.ToDouble(keypoints2[goodmatchs[j].TrainIdx].Pt.X);
                    point2D.Y = Convert.ToDouble(keypoints2[goodmatchs[j].TrainIdx].Pt.Y);
                    imagepoint2.Add(point2D);
                }
                //4 透视变换图形融合
                Mat homo = Cv2.FindHomography(imagepoint2, imagepoint1, HomographyMethods.Ransac);
                Mat imageTranForm = new Mat();
                CalcCorners(homo, Right);
                Cv2.WarpPerspective(Right, imageTranForm, homo, new Size(Left.Cols + Left.Cols - 40, Left.Rows));
                Cv2.WarpPerspective(Right, imageTranForm, homo, new Size(Math.Max(corners.right_top.X, corners.right_bottom.X), Left.Rows));

              //  Cv2.ImShow("imageTranForm", imageTranForm);
                //创建拼接后的图,计算图的大小
                int dst_width = imageTranForm.Cols;//获取最右点为拼接图长度
                int dst_height = Left.Rows;
                Mat dst = new Mat(dst_height, dst_width, MatType.CV_8UC3);
                dst.SetTo(0);
                imageTranForm.CopyTo(new Mat(dst, (new Rect(0, 0, imageTranForm.Cols, imageTranForm.Rows))));
                Left.CopyTo(new Mat(dst, (new Rect(0, 0, Left.Cols, Left.Rows))));
                //  Cv2.ImShow("imageTranForm3", dst);
                dst.CopyTo(dstimage);
              
            }
            else
            {
                //System.Windows.Forms.MessageBox.Show("特征点过少");
            }
            return;

      
增加矩阵计算功能,消除图像黑边  图像配准


      public struct four_corners_t
        {
            public Point2d left_top;
            public Point2d left_bottom;
            public Point2d right_top;
            public Point2d right_bottom;
        }; 
         public static four_corners_t corners = new four_corners_t();
        public static void CalcCorners(Mat H, Mat src)
        {

            double[,] matrix3x3 = new double[3, 3] {
            { H.Get<double>(0, 0), H.Get<double>(0, 1), H.Get<double>(0, 2) },
            { H.Get<double>(1, 0), H.Get<double>(1, 1), H.Get<double>(1, 2) },
            { H.Get<double>(2, 0), H.Get<double>(2, 1), H.Get<double>(2,2) }
            };
            // 左上角(0, 0, 1)
            double[,] result = new double[3, 1];
            double[,] matrix1x3 = new double[3, 1] { { 0.0 }, { 0.0 }, { 1.0 } };
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 1; j++)
                {
                    double sum = 0;
                    for (int k = 0; k < 3; k++)
                    {
                        sum += matrix3x3[i, k] * matrix1x3[k, j];
                    }
                    result[i, j] = sum;
                }
            }
            corners.left_top.X = result[0, 0] / result[2, 0];
            corners.left_top.Y = result[1, 0] / result[2, 0];


            //左下角(0,src.rows,1)
            result = new double[3, 1];
            matrix1x3 = new double[3, 1] { { 0.0 }, { src.Rows }, { 1.0 } };
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 1; j++)
                {
                    double sum = 0;
                    for (int k = 0; k < 3; k++)
                    {
                        sum += matrix3x3[i, k] * matrix1x3[k, j];
                    }
                    result[i, j] = sum;
                }
            }
            corners.left_bottom.X = result[0, 0] / result[2, 0];
            corners.left_bottom.Y = result[1, 0] / result[2, 0];

            //右上角(src.cols,0,1)
            result = new double[3, 1];
            matrix1x3 = new double[3, 1] { { src.Cols }, { 0.0 }, { 1.0 } };
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 1; j++)
                {
                    double sum = 0;
                    for (int k = 0; k < 3; k++)
                    {
                        sum += matrix3x3[i, k] * matrix1x3[k, j];
                    }
                    result[i, j] = sum;
                }
            }
            corners.right_top.X = result[0, 0] / result[2, 0];
            corners.right_top.Y = result[1, 0] / result[2, 0];
            //右下角(src.cols,src.rows,1)
            result = new double[3, 1];
            matrix1x3 = new double[3, 1] { { src.Cols }, { src.Rows }, { 1.0 } };
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 1; j++)
                {
                    double sum = 0;
                    for (int k = 0; k < 3; k++)
                    {
                        sum += matrix3x3[i, k] * matrix1x3[k, j];
                    }
                    result[i, j] = sum;
                }
            }
            corners.right_bottom.X = result[0, 0] / result[2, 0];
            corners.right_bottom.Y = result[1, 0] / result[2, 0];
        }

拼接效果图

图片不要从这里下载哦!

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
回答: 联合OpenCV是指在C#中使用OpenCV进行图像处理和计算机视觉任务。在C#中使用OpenCV,可以通过调用OpenCV的函数和方法来实现各种图像处理操作,例如图像的读取、修改尺寸、水平和垂直拼接等。在引用中的代码示例中,使用了OpenCV的Cv2命名空间下的函数来读取和处理图像,包括修改图像尺寸、水平和垂直拼接等操作。通过调用这些函数,可以在C#中实现对图像联合处理。在引用和引用中也提供了其他使用OpenCV进行图像处理的代码示例。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C#联合OpenCV进行图像拼接](https://blog.csdn.net/weixin_43852823/article/details/127258175)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Baumer工业相机堡盟相机BGAPI SDK联合OpenCV进行Mat图像转换(C#)](https://blog.csdn.net/xianzuzhicai/article/details/129075698)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [OpencvC#.Net版本开发,并访问像素的方法](https://blog.csdn.net/qq_24629901/article/details/77828769)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值