OpenCVSharp 基于特征的图像拼接

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

OpenCVSharp 基于特征的图像拼接_第1张图片

OpenCVSharp 基于特征的图像拼接_第2张图片

 

怼成这样:

OpenCVSharp 基于特征的图像拼接_第3张图片

 

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

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

 

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

OpenCVSharp 基于特征的图像拼接_第4张图片

 

OpenCVSharp 基于特征的图像拼接_第5张图片

 

对于这种场景,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 对于没有透视变形的图片们拼接效果较好,如果有透视变形,就不适用了,因为它会发生这样的事情:

OpenCVSharp 基于特征的图像拼接_第6张图片

OpenCVSharp 基于特征的图像拼接_第7张图片

 

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

 

 

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

            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();
            var pointsDst = new List();
            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;

 

你可能感兴趣的:(OpenCVSharp,C#图像处理,opencv,c#,图像拼接)