OpenCVSharp 基于特征的图像拼接

拼接有多个意思,有的只是简单的两个图片怼成一张图,比如这样:

 

怼成这样:

 

OpenCVSharp 有这样的函数,简单说一下,就不上完整代码了:

//上下拼接 两图像宽度必须一样
Cv2.VConcat(srcImg1, srcImg2, ret);
  
//左右拼接 两图像高度必须一样
Cv2.HConcat(srcImg1, srcImg2, ret);

 

但多数时候,我们要拼接的图像们之间是有重合的部分,比如这样:

 

 

对于这种场景,OpenCVSharp 提供了一个用于 图像拼接的 拼接器 Stitcher:

            //智能拼接,图像们有共同的重叠部分

            Mat srcImg2 = new Mat(strImg2);
            Mat srcImg3 = new Mat(strImg3);

            Mat[] images = new Mat[] { srcImg2, srcImg3 }; //数量两个以上
            Stitcher stitcher = Stitcher.Create(Stitcher.Mode.Scans);
            Mat pano = new Mat();
            var status = stitcher.Stitch(images, pano);
            if (status != Stitcher.Status.OK)
            {
                Console.WriteLine("失败:" + status.ToString());
                return;
            }

 

Stitcher 对于没有透视变形的图片们拼接效果较好,如果有透视变形,就不适用了,因为它会发生这样的事情:

 

虽然是拼到一起了,但因为两个照片是从不同的视角拍的,拼接后的图像是扭曲的,我们可能更想要这样的效果:

 

 

这时我们就要用到 基于特征的图像拼接:

            int w = img2.Width;
            int h = img2.Height;

            Mat img0 = new Mat(new Size(w * 2, h * 2), img2.Type());

            img0[0, h, w, w + w] = img2;

            ORB orb = ORB.Create(10000);
            Mat dscrip1 = new Mat();
            Mat dscrip2 = new Mat();


            orb.DetectAndCompute(img1, null, out KeyPoint[] keyPoint1, dscrip1);
            orb.DetectAndCompute(img0, null, out KeyPoint[] keyPoint2, dscrip2);


            //  暴力匹配
            BFMatcher matcher = new BFMatcher(NormTypes.Hamming, true);
            DMatch[] match = matcher.Match(dscrip1, dscrip2);

            match = match.OrderBy(x => x.Distance).ToArray();
            var goodmatch = match.Take(1600);

            if (goodmatch.Count() < 4) return;
             
            //画出匹配关系
            Mat outImg = new Mat();
            Cv2.DrawMatches(img1, keyPoint1, img0, keyPoint2, goodmatch, outImg, flags: DrawMatchesFlags.DrawRichKeypoints | DrawMatchesFlags.NotDrawSinglePoints);
            Cv2.ImShow("ORB", outImg);

            // 提取匹配的位置
            var pointsSrc = new List<Point2f>();
            var pointsDst = new List<Point2f>();
            foreach (var m in goodmatch)
            {
                pointsSrc.Add(keyPoint1[m.QueryIdx].Pt);
                pointsDst.Add(keyPoint2[m.TrainIdx].Pt);
            }
 

            var pSrc = pointsSrc.ConvertAll(Point2fToPoint2d);
            var pDst = pointsDst.ConvertAll(Point2fToPoint2d);
            
            //获得变换矩阵
            var M = Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac);
            Console.WriteLine(M);
            Console.WriteLine(Cv2.Format(M));
            
            // 对 img1 透视变换
            var result = new Mat();
            Cv2.WarpPerspective(img1, result, M, new Size(w * 2, h * 2));

            // 将img2拼接到结果
            result[0, h, w, w + w] = img2;

 

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

易极

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值