精华内容
下载资源
问答
  • 多幅图像拼接opencv
    千次阅读
    2018-11-04 10:05:05

    由于最近在学习超分辨率算法,但是大多数开源程序输入图片太大就显示显存不够,因此就把手机拍摄的图片先分割成一系列小的图片,超分辨率之后再拼接在一块

    OpenCV的程序如下:比较简单,对5x5即25张图片进行拼接:


    #include <iostream>
    #include <core/core.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include<opencv2/stitching.hpp>

    using namespace std;
    using namespace cv;
    int main()
    {
        int i = 0,j=0;
        Mat combine;
        Mat row[5][5], column[5];
        Mat com_row[5][5], con_column[5];

        row[0][0] = imread("C:\\test\\pic_div\\1-1.jpg");
        row[0][1] = imread("C:\\test\\pic_div\\1-2.jpg");
        row[0][2] = imread("C:\\test\\pic_div\\1-3.jpg");
        row[0][3] = imread("C:\\test\\pic_div\\1-4.jpg");
        row[0][4] = imread("C:\\test\\pic_div\\1-5.jpg");

        row[1][0] = imread("C:\\test\\pic_div\\2-1.jpg");
        row[1][1] = imread("C:\\test\\pic_div\\2-2.jpg");
        row[1][2] = imread("C:\\test\\pic_div\\2-3.jpg");
        row[1][3] = imread("C:\\test\\pic_div\\2-4.jpg");
        row[1][4] = imread("C:\\test\\pic_div\\2-5.jpg");

        row[2][0] = imread("C:\\test\\pic_div\\3-1.jpg");
        row[2][1] = imread("C:\\test\\pic_div\\3-2.jpg");
        row[2][2] = imread("C:\\test\\pic_div\\3-3.jpg");
        row[2][3] = imread("C:\\test\\pic_div\\3-4.jpg");
        row[2][4] = imread("C:\\test\\pic_div\\3-5.jpg");

        row[3][0] = imread("C:\\test\\pic_div\\4-1.jpg");
        row[3][1] = imread("C:\\test\\pic_div\\4-2.jpg");
        row[3][2] = imread("C:\\test\\pic_div\\4-3.jpg");
        row[3][3] = imread("C:\\test\\pic_div\\4-4.jpg");
        row[3][4] = imread("C:\\test\\pic_div\\4-5.jpg");

        row[4][0] = imread("C:\\test\\pic_div\\5-1.jpg");
        row[4][1] = imread("C:\\test\\pic_div\\5-2.jpg");
        row[4][2] = imread("C:\\test\\pic_div\\5-3.jpg");
        row[4][3] = imread("C:\\test\\pic_div\\5-4.jpg");
        row[4][4] = imread("C:\\test\\pic_div\\5-5.jpg");

        //cv::resize(a, a, cv::Size(1984, 1488), 0, 0, CV_INTER_LINEAR);
        //cv::resize(b, b, cv::Size(1984, 1488), 0, 0, CV_INTER_LINEAR);
        //cv::resize(c, c, cv::Size(1984, 1488), 0, 0, CV_INTER_LINEAR);
        //cv::resize(d, d, cv::Size(1984, 1488), 0, 0, CV_INTER_LINEAR);
        //水平拼接
        com_row[0][0] = row[0][0];
        com_row[1][0] = row[1][0];
        com_row[2][0] = row[2][0];
        com_row[3][0] = row[3][0];
        com_row[4][0] = row[4][0];
        for (i = 0; i < 5; i = i + 1)
        {
            for (j = 0; j < 4; j = j + 1)
            {
                hconcat(com_row[i][j], row[i][j+1], com_row[i][j+1]);
            }
            column[i] = com_row[i][4];   //产生的每一行的拼接图片
        }
        //垂直拼接
        con_column[0] = column[0];
        for (i = 0; i < 4; i = i + 1)
        {
            vconcat(con_column[i], column[i + 1], con_column[i + 1]);
        }
        combine = con_column[4];
        namedWindow("Combine", CV_WINDOW_AUTOSIZE);
        imshow("Combine", combine);
        imwrite("Combine.png", combine);
        cv::waitKey(1);

        system("pause");
        return 0;
    }

    拼接 之前的图片:

    拼接之后:

    更多相关内容
  • 主要为大家详细介绍了opencv实现图像拼接功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 该存储库包含图像拼接的实现。 高分辨率图像处理缓慢。 图像必须按从左到右的顺序提供,反之亦然。 演示->>> 要求 python3.7.1 的opencv3.4.2 或使用opencv-contrib-python,因为某些非免费功能不可用 pip ...
  • 高级图像拼接也叫作基于特征匹配的图像拼接拼接时消去两幅图像相同的部分,实现拼接合成全景图。这篇文章主要介绍了python opencv 图像拼接,需要的朋友可以参考下
  • Opencv 实战五 图像拼接

    千次阅读 热门讨论 2022-05-13 13:55:24
    下面用opencv实现一下图像进行拼接 如下图所示,三张不同角度的图像最终拼接成一张全视角的图像 from imutils import paths import numpy as np import argparse import imutils import cv2 # 构造参数解析...

    图像拼接技术就是将数张有重叠部分的图像(可能是不同时间、不同视角或者不同传感器获得的)拼成一幅无缝的全景图或高分辨率图像的技术。
    下面用opencv实现一下多张图像进行拼接
    如下图所示,三张不同角度的图像最终拼接成一张全视角的图像
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    from imutils import paths
    import numpy as np
    import argparse
    import imutils
    import cv2
    
    # 构造参数解析器并解析参数
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--images",default='images', type=str, required=True,
                    help="path to input directory of images to stitch")
    ap.add_argument("-o", "--output", default='output.png',type=str, required=True,
                    help="path to the output image")
    ap.add_argument("-c", "--crop", type=int, default=0,
                    help="whether to crop out largest rectangular region")
    args = vars(ap.parse_args())  # vars函数是实现返回对象object的属性和属性值的字典对象
    
    print(args)  # {'images': 'images/scottsdale', 'output': 'output.png', 'crop': 1}
    # 匹配输入图像的路径并初始化我们的图像列表
    # rectangular_region = 2
    print("[INFO] loading images...")
    # 获取到每张待拼接图像并排序,如['第一张图片路径', 第二张图片路径',第三张图片路径']
    imagePaths = sorted(list(paths.list_images(args["images"])))
    # print(imagePaths)
    # imagePaths = ['IMG_1786-2.jpg',
    # 			  'IMG_1787-2.jpg',
    # 			  'IMG_1788-2.jpg']
    images = []
    
    # 遍历图像路径,加载每个路径,然后将它们添加到我们的路径中图像到stich列表
    for imagePath in imagePaths:
        image = cv2.imread(imagePath)
        images.append(image)
    
    # 初始化OpenCV的图像sticher对象,然后执行图像拼接
    print("[INFO] stitching images...")
    stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create()
    (status, stitched) = stitcher.stitch(images)
    
    
    # print(status, stitched)
    # 如果状态为“0”,则OpenCV成功执行图像拼接
    if status == 0:
        # 检查我们是否应该从拼接图像中裁剪出最大的矩形区域
        if args["crop"] > 0:
            # 在拼接图像周围创建一个10像素的黑色边框
            print("[INFO] cropping...")
            stitched = cv2.copyMakeBorder(stitched, 10, 10, 10, 10,
                                          cv2.BORDER_CONSTANT, (0, 0, 0))
            # cv2.imshow('123',stitched)
    
            # 将拼接图像转换为灰度
            gray = cv2.cvtColor(stitched, cv2.COLOR_BGR2GRAY)
            # cv2.imshow('456', gray)
            # 对灰度图像进行阈值二值化,
            # 这样所有大于零的像素都设置为255(前景),而其他所有像素都保持为0(背景)
            thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)[1]
            # cv2.imshow('789', thresh)
            # 在阈值图像中找到所有外部轮廓,然后找到 “最大 ”轮廓,它将是拼接图像的轮廓
            # cv2.RETR_EXTERNAL:只找外轮廓。cv2.CHAIN_APPROX_SIMPLE:输出少量轮廓点
            # 输出参数1:图像
            # 输出参数2:轮廓列表
            # 输出参数3:层级
            cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
            # print(cnts) #cnts包括三个数组:
            # print(len(cnts))
    
            cnts = imutils.grab_contours(cnts)
    
            ################################
            # imutils.grab_contours 的源码 :
    
                # # if the length the contours tuple returned by cv2.findContours
                # # is '2' then we are using either OpenCV v2.4, v4-beta, or
                # # v4-official
                # if len(cnts) == 2:
                #     cnts = cnts[0]
                # # if the length of the contours tuple is '3' then we are using
                # # either OpenCV v3, v4-pre, or v4-alpha
                # elif len(cnts) == 3:
                #     cnts = cnts[1]
                # # otherwise OpenCV has changed their cv2.findContours return
                # # signature yet again and I have no idea WTH is going on
                # else:
                #     raise Exception(("Contours tuple must have length 2 or 3, "
                #                      "otherwise OpenCV changed their cv2.findContours return "
                #                      "signature yet again. Refer to OpenCV's documentation "
                #                      "in that case"))
                # # return the actual contours array
                # return cnts
            ##################################
    
            # 抓取具有最大区域的轮廓(即拼接图像本身的轮廓),cv2.contourArea是求轮廓面积
            c = max(cnts, key=cv2.contourArea)
            # print(c)
            # print(c.shape)
            # 为掩码分配内存,该掩码将包含拼接图像区域的矩形边界框
            mask = np.zeros(thresh.shape, dtype="uint8")
            # 计算出最大轮廓的边界框,使用边界矩形信息.使用 cv2.boundingRect(img) 函数,用一个最小的矩形,
            # 把找到的形状包起来,img是一个二值图,也就是它的参数;返回四个值,分别是 x,y,w,h;
            # 其中 x,y 是矩阵左上点的坐标,w,h 是矩阵的宽和高
            (x, y, w, h) = cv2.boundingRect(c)
            # 使用cv2.rectangle给图像加框,我们在mask上绘制一个纯白色矩形。
            # 参数1:图像
            # 参数2:左上角坐标
            # 参数3:右下角坐标
            # 参数4:框的颜色
            # 参数5:框的粗细
            cv2.rectangle(mask, (x, y), (x + w, y + h), 255, -1)
    
            # 创建掩码的两个副本
            # 第一个mask,将逐渐缩小,直到它可以放入全景内部。
            minRect = mask.copy()
            # 第二个mask,将用于确定是否需要继续减小minRect的大小。
            sub = mask.copy()
            cv2.imshow('111',sub)
    
            # 保持循环,直到sub中没有更多的前景像素
            # 对二值化图像执行countNonZero。可得到非零像素点数(即外边框的像素点)
            print(cv2.countNonZero(sub))
            while cv2.countNonZero(sub) > 0:
                # 执行侵蚀形态学操作以减小minRect的大小。
                minRect = cv2.erode(minRect, None)
                cv2.imshow('333',minRect)
                # 从minRect中减去thresh ,一旦minRect中没有更多的前景像素,我们就可以从循环中断开
                sub = cv2.subtract(minRect, thresh)
    
            # 在最小矩形掩码中找到轮廓,然后提取边界框(x,y) - 坐标
            cnts = cv2.findContours(minRect.copy(), cv2.RETR_EXTERNAL,
                                    cv2.CHAIN_APPROX_SIMPLE)
            cv2.imshow('444',cnts[0])
            cnts = imutils.grab_contours(cnts)
            c = max(cnts, key=cv2.contourArea)
            (x, y, w, h) = cv2.boundingRect(c)
    
            # 使用边界框坐标来提取我们的最终拼接图像
            stitched = stitched[y:y + h, x:x + w]
    
            # 将输出拼接图像写入磁盘
            cv2.imwrite("result.jpg", stitched)
    
            # 将输出拼接图像显示到我们的屏幕
            cv2.imshow("Stitched", stitched)
            cv2.waitKey(0)
    
    # 否则,拼接失败,可能是由于检测不到足够的关键点
    
    else:
       print("[INFO] image stitching failed ({})".format(status))
    
    
    #执行
    python main.py --images images/ --output output.png --crop 1
    

    结果如下所示
    在这里插入图片描述
    有一说一opencv真的牛掰

    展开全文
  • OpenCV 实现图像拼接

    千次阅读 2021-06-27 00:53:07
    点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达 本文转自:opencv学堂拼接算法OpenCV中从2.4.x版本之后出来一个新的模型 图像拼接,该...

    点击上方“小白学视觉”,选择加"星标"或“置顶

    重磅干货,第一时间送达
    

    本文转自:opencv学堂

    拼接算法

    OpenCV中从2.4.x版本之后多出来一个新的模型 图像拼接,该模块通过简单的高级API设置,可以获得比较好的图像拼接效果,OpenCV官方提供了一个高度集成的API函数 Stitcher,只要两行代码就可以得到一个很好的拼接图像。

    Ptr<Stitcher> stitcher = Stitcher::create(mode);
    Stitcher::Status status = stitcher->stitch(imgs, pano);
    

    其中第一行代码是创建拼接Stitcher的指针,第二行代码是调用拼接算法,

    • imgs表示的输入参数,是一系列Mat对象的vector。

    • pano表示的输出结果,是拼接之后的Mat对象

    官方的例子得到效果是非常的好,输入的images如下:

    拼接结果如下:

    但是很多人按照官方的例子开始拼接自己的图像,就是各种掉坑,各种拼接都不出结果,想跟跟上面一样简单的调用两句代码完成几乎是个梦,其实这个API里面有很多参数设置,这个在官方的演示当中都没有详细交代,stitching拼接算法 流程图示如下:

    可见图像拼接是一个很复杂的算法,是由一系列的基础算法构成,这些基础算法如果你不是很了解,其实很难实现自己的图像拼接,这其中影响拼接算法stitch工作最常见几个算法子模块为:

    • 特征发现与描述子
      常见的特征可以选择SIFT、SURF、AKAZE、ORB等特征算子进行匹配

    • 相机参数
      不同的相机参数与设置会导致不同的结果

    • 融合方式(blender)
      不同的融合方式,也会导致不同结果

    • 各种阈值设置,特别是config threshold,如果无法特征匹配,记得把这个阈值调小点

    其它参数可以如何设置可以参考OpenCV的官方文档,总之无法拼接就去调参数,一般最后都会拼接成功,此外该算法速度比较慢,但是支持GPU执行,所以想要实时的可以尝试如何GPU下执行,我这里没有尝试 ,谁尝试过的可以留言分享,我负责置顶。

    代码演示

    另外在拼接的时候可以设置不同warper,这样会对拼接之后的图像生成不同效果,常见的效果包括

    • 鱼眼相机

    • 环视(平面曲翘)

    • 默认

    图示分别如下:

    演示代码如下:

    #include <opencv2/opencv.hpp>
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    
    int main(int argc, char** argv) {
        vector<string> files;
        glob("D:/images/zsxq/1", files);
        vector<Mat> images;
        for (int i = 0; i < files.size(); i++) {
            printf("image file : %s \n", files[i].c_str());
            images.push_back(imread(files[i]));
        }
    
        // 设置拼接模式与参数
        Mat result1, result2, result3;
        Stitcher::Mode mode = Stitcher::PANORAMA;
        Ptr<Stitcher> stitcher = Stitcher::create(mode);
    
        // 拼接方式-多通道融合
        auto blender = detail::Blender::createDefault(detail::Blender::MULTI_BAND);
        stitcher->setBlender(blender);
    
        // 拼接
        Stitcher::Status status = stitcher->stitch(images, result1);
    
        // 平面曲翘拼接
        auto plane_warper = makePtr<cv::PlaneWarper>();
        stitcher->setWarper(plane_warper);
        status = stitcher->stitch(images, result2);
    
        // 鱼眼拼接
        auto fisheye_warper = makePtr<cv::FisheyeWarper>();
        stitcher->setWarper(fisheye_warper);
        status = stitcher->stitch(images, result3);
    
        // 检查返回
        if (status != Stitcher::OK)
        {
            cout << "Can't stitch images, error code = " << int(status) << endl;
            return EXIT_FAILURE;
        }
        imwrite("D:/result1.png", result1);
        imwrite("D:/result2.png", result2);
        imwrite("D:/result3.png", result3);
    
        waitKey(0);
        return 0;
    }
    

    注意:一起运行速度比较慢!是真的比较慢!

    下载1:OpenCV-Contrib扩展模块中文版教程

    在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

    下载2:Python视觉实战项目52讲

    在「小白学视觉」公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

    下载3:OpenCV实战项目20讲

    在「小白学视觉」公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

    交流群

    欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~

    展开全文
  • 读取指定目录下按照一定命名规格命名的图片,可循环读取多幅图片,并进行图像拼接。按照类似原理,可实现按照一定命名规格将图片存储到指定目录下。
  • 3、如果找到了足够的匹配点,就能将两幅图拼接起来,拼接前,可能需要将第二图透视旋转一下,利用找到的关键点,将第二图透视旋转到一个与第一图相同的可以拼接的角度; 4、进行拼接; 5、进行拼接后的一些...
  • OpenCV图像处理--常用图像拼接方法

    万次阅读 多人点赞 2021-10-15 14:57:10
    OpenCV常用图像拼接方法(一) :直接拼接

    OpenCV常用图像拼接方法(一) :直接拼接

    vconcat()—垂直方向拼接,要求待拼接图像有相同的宽度; hconcat()—水平方向拼接,要求待拼接图像有相同的高度。

    使用vconcat()和hconcat()拼接则要求待拼接图像有相同的宽度或高度

     	Mat img = imread("girl.jpg");
        vector<Mat>vImgs;
        Mat result;
        vImgs.push_back(img);
        vImgs.push_back(img);
        vconcat(vImgs, result); //垂直方向拼接
        //hconcat(vImgs, result); //水平方向拼接
        imshow("result",result);
        cout << "Hello World!" << endl;
        waitKey(0);
    

    在这里插入图片描述
    其他拼接函数

            vector<Mat> images;
    
            images.push_back(imread("stitch1.jpg"));
            images.push_back(imread("stitch2.jpg"));
    
            // 设置拼接模式与参数
            Mat result1, result2, result3;
            Stitcher::Mode mode = Stitcher::PANORAMA;
            Ptr<Stitcher> stitcher = Stitcher::create(mode);
    
            // 拼接方式-多通道融合
            auto blender = detail::Blender::createDefault(detail::Blender::MULTI_BAND);
            stitcher->setBlender(blender);
    
            // 拼接
            Stitcher::Status status = stitcher->stitch(images, result1);
    
            // 平面曲翘拼接
            auto plane_warper = makePtr<cv::PlaneWarper>();
            stitcher->setWarper(plane_warper);
            status = stitcher->stitch(images, result2);
    
            // 鱼眼拼接
            auto fisheye_warper = makePtr<cv::FisheyeWarper>();
            stitcher->setWarper(fisheye_warper);
            status = stitcher->stitch(images, result3);
    
            // 检查返回
            if (status != Stitcher::OK)
            {
                cout << "Can't stitch images, error code = " << int(status) << endl;
                return EXIT_FAILURE;
            }
    
            imshow("result1.png", result1);
            imshow("result2.png", result2);
            imshow("result3.png", result3);
    
             waitKey(0);
    

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

    OpenCV常用图像拼接方法(二) :基于模板匹配拼接

    • 适用范围:图像有重合区域,且待拼接图像之间无明显尺度变化和畸变。
    • 优点:简单、快速(相比于SIFT特征匹配拼接)。
    • 常用实例:两个相邻相机水平拍摄图像拼接。

    截取如下两部分ROI作为待拼接图像。
    在这里插入图片描述
    待拼接图①:
    在这里插入图片描述
    待拼接图②:

    在这里插入图片描述

    思路:在图①中截取部分公共区域ROI作为模板,利用模板在图②中匹配,得到最佳匹配位置后计算X和Y方向需要平移的像素距离,将图②对应的拼接到大图中。如下,模板为青色区域:

    图片
    部分代码和效果如下:

     Mat imgL = imread("A.jpg");
      Mat imgR = imread("B.jpg");
      double start = getTickCount();
      Mat grayL, grayR;
      cvtColor(imgL, grayL, COLOR_BGR2GRAY);
      cvtColor(imgR, grayR, COLOR_BGR2GRAY);
    
      Rect rectCut = Rect(372, 122, 128, 360);
      Rect rectMatched = Rect(0, 0, imgR.cols / 2, imgR.rows);
      Mat imgTemp = grayL(Rect(rectCut));
      Mat imgMatched = grayR(Rect(rectMatched));
    
      int width = imgMatched.cols - imgTemp.cols + 1;
      int height = imgMatched.rows - imgTemp.rows + 1;
      Mat matchResult(height, width, CV_32FC1);
      matchTemplate(imgMatched, imgTemp, matchResult, TM_CCORR_NORMED);
      normalize(matchResult, matchResult, 0, 1, NORM_MINMAX, -1);  //归一化到0--1范围
    
      double minValue, maxValue;
      Point minLoc, maxLoc;
      minMaxLoc(matchResult, &minValue, &maxValue, &minLoc, &maxLoc);
    
      Mat dstImg(imgL.rows, imgR.cols + rectCut.x - maxLoc.x, CV_8UC3, Scalar::all(0));
      Mat roiLeft = dstImg(Rect(0, 0, imgL.cols, imgL.rows));
      imgL.copyTo(roiLeft);
    
      Mat debugImg = imgR.clone();
      rectangle(debugImg, Rect(maxLoc.x, maxLoc.y, imgTemp.cols, imgTemp.rows), Scalar(0, 255, 0), 2, 8);
      imwrite("match.jpg", debugImg);
    
      Mat roiMatched = imgR(Rect(maxLoc.x, maxLoc.y - rectCut.y, imgR.cols - maxLoc.x, imgR.rows - 1 - (maxLoc.y - rectCut.y)));
      Mat roiRight = dstImg(Rect(rectCut.x, 0, roiMatched.cols, roiMatched.rows));
    
      roiMatched.copyTo(roiRight);
    
      double end = getTickCount();
      double useTime = (end - start) / getTickFrequency();
      cout << "use-time : " << useTime << "s" << endl;
    
      imwrite("dst.jpg", dstImg);
      cout << "Done!" << endl;
    

    匹配结果:
    在这里插入图片描述
    拼接结果:
    在这里插入图片描述
    OpenCV常用图像拼接方法(三) :SIFT特征匹配拼接方法
    特点和适用范围:图像有足够重合相同特征区域,且待拼接图像之间无明显尺度变换和畸变。
    优点:适应部分倾斜变化情况。缺点:需要有足够的相同特征区域进行匹配,速度较慢,拼接较大图片容易崩溃。
    如下是待拼接的两张图片:
    在这里插入图片描述
    在这里插入图片描述

    特征匹配图:
    在这里插入图片描述
    拼接结果图:
    在这里插入图片描述
    拼接缝处理后(拼接处过渡更自然):
    在这里插入图片描述

    /********************直接图像拼接函数*************************/
    bool ImageOverlap0(Mat &img1, Mat &img2)
    {
      Mat g1(img1, Rect(0, 0, img1.cols, img1.rows));  // init roi
      Mat g2(img2, Rect(0, 0, img2.cols, img2.rows));
     
      cvtColor(g1, g1, COLOR_BGR2GRAY);
      cvtColor(g2, g2, COLOR_BGR2GRAY);
     
      vector<cv::KeyPoint> keypoints_roi, keypoints_img;  /* keypoints found using SIFT */
      Mat descriptor_roi, descriptor_img;                           /* Descriptors for SIFT */
      FlannBasedMatcher matcher;                                   /* FLANN based matcher to match keypoints */
     
      vector<cv::DMatch> matches, good_matches;
      cv::Ptr<cv::SIFT> sift = cv::SIFT::create();
      int i, dist = 80;
     
      sift->detectAndCompute(g1, cv::Mat(), keypoints_roi, descriptor_roi);      /* get keypoints of ROI image */
      sift->detectAndCompute(g2, cv::Mat(), keypoints_img, descriptor_img);         /* get keypoints of the image */
      matcher.match(descriptor_roi, descriptor_img, matches);  //实现描述符之间的匹配
     
      double max_dist = 0; double min_dist = 5000;
      //-- Quick calculation of max and min distances between keypoints
      for (int i = 0; i < descriptor_roi.rows; i++)
      {
        double dist = matches[i].distance;
        if (dist < min_dist) min_dist = dist;
        if (dist > max_dist) max_dist = dist;
      }
      // 特征点筛选
      for (i = 0; i < descriptor_roi.rows; i++)
      {
        if (matches[i].distance < 3 * min_dist)
        {
          good_matches.push_back(matches[i]);
        }
      }
     
      printf("%ld no. of matched keypoints in right image\n", good_matches.size());
      /* Draw matched keypoints */
     
      Mat img_matches;
      //绘制匹配
      drawMatches(img1, keypoints_roi, img2, keypoints_img,
        good_matches, img_matches, Scalar::all(-1),
        Scalar::all(-1), vector<char>(),
        DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
      imshow("matches", img_matches);
     
      vector<Point2f> keypoints1, keypoints2;
      for (i = 0; i < good_matches.size(); i++)
      {
        keypoints1.push_back(keypoints_img[good_matches[i].trainIdx].pt);
        keypoints2.push_back(keypoints_roi[good_matches[i].queryIdx].pt);
      }
      //计算单应矩阵(仿射变换矩阵)
      Mat H = findHomography(keypoints1, keypoints2, RANSAC);
      Mat H2 = findHomography(keypoints2, keypoints1, RANSAC);
     
     
      Mat stitchedImage;  //定义仿射变换后的图像(也是拼接结果图像)
      Mat stitchedImage2;  //定义仿射变换后的图像(也是拼接结果图像)
      int mRows = img2.rows;
      if (img1.rows > img2.rows)
      {
        mRows = img1.rows;
      }
     
      int count = 0;
      for (int i = 0; i < keypoints2.size(); i++)
      {
        if (keypoints2[i].x >= img2.cols / 2)
          count++;
      }
      //判断匹配点位置来决定图片是左还是右
      if (count / float(keypoints2.size()) >= 0.5)  //待拼接img2图像在右边
      {
        cout << "img1 should be left" << endl;
        vector<Point2f>corners(4);
        vector<Point2f>corners2(4);
        corners[0] = Point(0, 0);
        corners[1] = Point(0, img2.rows);
        corners[2] = Point(img2.cols, img2.rows);
        corners[3] = Point(img2.cols, 0);
        stitchedImage = Mat::zeros(img2.cols + img1.cols, mRows, CV_8UC3);
        warpPerspective(img2, stitchedImage, H, Size(img2.cols + img1.cols, mRows));
     
        perspectiveTransform(corners, corners2, H);
        /*
        circle(stitchedImage, corners2[0], 5, Scalar(0, 255, 0), 2, 8);
        circle(stitchedImage, corners2[1], 5, Scalar(0, 255, 255), 2, 8);
        circle(stitchedImage, corners2[2], 5, Scalar(0, 255, 0), 2, 8);
        circle(stitchedImage, corners2[3], 5, Scalar(0, 255, 0), 2, 8); */
        cout << corners2[0].x << ", " << corners2[0].y << endl;
        cout << corners2[1].x << ", " << corners2[1].y << endl;
        imshow("temp", stitchedImage);
        //imwrite("temp.jpg", stitchedImage);
     
        Mat half(stitchedImage, Rect(0, 0, img1.cols, img1.rows));
        img1.copyTo(half);
        imshow("result", stitchedImage);
      }
      else  //待拼接图像img2在左边
      {
        cout << "img2 should be left" << endl;
        stitchedImage = Mat::zeros(img2.cols + img1.cols, mRows, CV_8UC3);
        warpPerspective(img1, stitchedImage, H2, Size(img1.cols + img2.cols, mRows));
        imshow("temp", stitchedImage);
     
        //计算仿射变换后的四个端点
        vector<Point2f>corners(4);
        vector<Point2f>corners2(4);
        corners[0] = Point(0, 0);
        corners[1] = Point(0, img1.rows);
        corners[2] = Point(img1.cols, img1.rows);
        corners[3] = Point(img1.cols, 0);
     
        perspectiveTransform(corners, corners2, H2);  //仿射变换对应端点
        /*
        circle(stitchedImage, corners2[0], 5, Scalar(0, 255, 0), 2, 8);
        circle(stitchedImage, corners2[1], 5, Scalar(0, 255, 255), 2, 8);
        circle(stitchedImage, corners2[2], 5, Scalar(0, 255, 0), 2, 8);
        circle(stitchedImage, corners2[3], 5, Scalar(0, 255, 0), 2, 8); */
        cout << corners2[0].x << ", " << corners2[0].y << endl;
        cout << corners2[1].x << ", " << corners2[1].y << endl;
     
        Mat half(stitchedImage, Rect(0, 0, img2.cols, img2.rows));
        img2.copyTo(half);
        imshow("result", stitchedImage);
     
      }
      imwrite("result.bmp", stitchedImage);
      return true;
    }
    

    OpenCV常用图像拼接方法(四) :SURF特征匹配拼接方法
    参考链接:
    https://www.cnblogs.com/skyfsm/p/7411961.html
    https://www.cnblogs.com/skyfsm/p/7401523.html

    展开全文
  • opencv实现图像全景拼接

    千次阅读 2020-12-15 16:06:07
    图片进行基于SIFT的特征检测算法,如果符合最小拼接要求大的关键点`matchKeypoints`数量,使用`OpenCV-Python`自带的`stitching`方法进行全景拼接,但是对于拼接后的黑边裁剪效果不好,可以修改优化。...
  • Opencv实战——图像拼接

    千次阅读 2022-06-01 15:44:32
      图像拼接(Image Stitching)是一种利用实景图像组成全景空间的技术,它将多幅图像拼接成一幅大尺度图像或360度全景图,接可以看做是场景重建的一种特殊情况,其中图像仅通过平面单应性进行关联。图像拼接在运动...
  • 图像拼接(七):OpenCV单应变换模型拼接多幅图像

    万次阅读 热门讨论 2017-03-06 10:50:05
    求取每相邻两幅图像的单应矩阵拼接多幅图像,需要计算每相邻两幅图像的单应矩阵,上篇已经封装了求取单应矩阵的类,可以拿来用。 现有4幅图像:img1img1,img2img2,img3img3,img4img4。依次从右向左排列,拼接...
  • 在图像拼接(十三):OpenCV单应变换模型拼接多幅图像 这篇博客中实现了用单应变换模型拼接多幅图像,图像拼接使用的OpenCV库函数warpPerspective()。因为这个函数只有在右侧图像变换到左侧图像时才能完整显示,所以...
  • 由于已经计算出单应矩阵,可以使用该矩阵将第一张图像转换到第二张图像的平面上。对于在同一平面上的两张图像,一个很直观的思路是,迭代两幅图像,发现匹配的区域则覆盖,否则置为0。.........
  • C++ Opencv图像基础处理,图像的直接拼接
  • 利用C++中的opencv进行图像拼接

    千次阅读 2022-05-25 16:37:36
    这篇文章依旧是记录采用C++复现...OpenCV常用图像拼接方法(二):基于模板匹配拼接_Color Space的博客-CSDN博客_图像拼接素材 图像拼接的程序的目的是将imgL(1)与imgR(2)拼接起来,方法是通过截取imgL中的一小.
  • 初级的图像拼接为将两幅图像简单的粘贴在一起,仅仅是图像几何空间的转移与合成,与图像内容无关。高级图像拼接也叫作基于特征匹配的图像拼接拼接时消去两幅图像相同的部分,实现拼接合成全景图。具有相同尺寸的图...
  • OpenCV C++案例实战十二《图像全景拼接

    千次阅读 热门讨论 2022-01-02 10:59:09
    OpenCV C++案例实战十二《图像全景拼接》前言一、OpenCV Stitcher1.功能源码2.效果二、图像全景拼接1.特征检测2.计算单应性矩阵3.透视变换4.图像拼接5.功能源码6.效果三、源码总结 前言 本文将使用OpenCV C++ 进行...
  • 利用OpenCV实现图像的全景拼接 案例:实现图像的全景拼接: 代码如下所示: import cv2 import numpy as np class Stitcher(): # 拼接函数 def stitch(self, images, ratio=0.75, reprojThresh=4.0, ...
  • python opencv 图像拼接

    万次阅读 多人点赞 2018-08-21 10:24:24
    高级图像拼接也叫作基于特征匹配的图像拼接拼接时消去两幅图像相同的部分,实现拼接合成全景图。 具有相同尺寸的图A和图B含有相同的部分与不同的部分,如图所示:   用基于特征的图像拼接实现后: 设图像...
  • 基于python编程下opencv库实现方向图片的自动识别拼接,可应用于大幅纸质地图扫描成个文件后自动拼接恢复电子版原图。
  • 5.OpenCV图像拼接

    2022-07-15 19:15:13
    图像拼接(Image Stitching)是一种利用实景图像组成全景空间的技术,它将多幅图像拼接成一幅大尺度图像或360°全景图,可视作场景重建的一种特殊情况,其中图像仅通过平面单应性进行关联。图像拼接在运动检测和跟踪...
  • 如何使用OpenCV实现图像拼接

    万次阅读 2019-09-03 10:52:10
    先来看看OpenCV官方的例子得到效果是非常的好,输入...低级别函数封装在detail命名空间中,展示了OpenCV算法实现的很步骤和细节,使熟悉如下拼接流水线的用户,方便自己定制。 这涉及到以下算法流程: 命令行调...
  • 图像拼接、配准与美化,从涉及的个知识点出发,结合代码实践加深理解
  • opencv-python 使用stitcher.stitch进行全景的拼接】将图片拼接成全景,采用了stitcher.stitch
  • 使用python-opencv进行图像拼接

    万次阅读 多人点赞 2019-02-01 22:12:27
    如果找到了足够的匹配点,就能将两幅图拼接起来,拼接前,可能需要将第二图透视旋转一下,利用找到的关键点,将第二图透视旋转到一个与第一图相同的可以拼接的角度; 进行拼接; 进行拼接后的一些处理,让...
  • 网络上大都是在已排序的情况下进行全景拼接。...以方便后续的全景图像拼接。 源图像 x 10 ,顺序为(4 -8-6-3-5-2-10-9-1-7) 如何排序得到(1-2-3-4-5-6-7-8-9-10) 全景图像(1-2-3-4-5-6-7-8-9-10)
  • 么是图像拼接呢?简单来说,对于输入应该有一组图像,输出是合成图像。同时,必须保留图像之间的逻辑流。首先让我们了解图像拼接的概念。基本上,如果你想捕捉一个大的...获取多幅图像并将其转换成全景图的整个过...
  • VS2012开发的,融合钟图像拼接和融合方法并进行对比,可以对两幅或四幅图像进行拼接,有助于各种方法的对比和学习,原图片存放于data文件夹即可
  • 利用OpenCV实现图像拼接的代码

    万次阅读 2016-07-30 10:30:08
    图像拼接操作对序列图像一般要求重叠区域不少于10%,对序列图像进行特征点检测,可利用OpenCV中提供的角点检测方法来对序列图像进行特征点提取。特征点筛选采用RANSAC提取有效样本特征点,OpenCV提供了函数Find........

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,647
精华内容 658
关键字:

多幅图像拼接opencv