• 简单的图片拼接


    图片能够拼接的前提是:两幅图片的边缘有重叠的部分

    在CSDN上看到一篇关于《图像拼接原理》的博客,讲的不错。

    拼接思路简述

    使用Hu矩匹配两幅图片的指定区域,符合条件则记录该像素或模板的位置,供拼接时使用。

    程序:

    #include "stdafx.h"
    #include <iostream>
    #include <highgui.h>
    #include "cv.h"
    #include <vector>
    #include <functional>
    
    using namespace std;
    using namespace cv;
    
    struct MatchR
    {
        int  PositionX;    //存储位置的X坐标
        double MResult;    //存储轮廓匹配结果
        bool operator < (const MatchR& rhs) const   //升序排序时必须写的函数
        {   
            return MResult < rhs.MResult; 
        }
    };
    
    vector<MatchR> vec;
    
    //获取输入图像的轮廓
    CvSeq* getImageContour(IplImage* srcIn);
    
    int main(int argc, char* argv[])
    {
        const char * LeftPath="leftpic.bmp";
        const char * RightPath="rightpic.bmp";
        
        IplImage * Lpic=cvLoadImage(LeftPath,CV_LOAD_IMAGE_GRAYSCALE);
        IplImage * Rpic=cvLoadImage(RightPath,CV_LOAD_IMAGE_GRAYSCALE);
    
        assert(Lpic && Rpic);
    
        //选取左图的一部分作为兴趣区域
        const int TemplWi=(int)(Lpic->width)/10;
        CvRect RectROI=cvRect((Lpic->width-TemplWi),0,TemplWi,Lpic->height);
    
        //准备模板图像ImgTemplt
        cvSetImageROI(Lpic,RectROI);
        IplImage * ImgTemplt=cvCreateImage(cvSize(TemplWi,Lpic->height),Lpic->depth,1);
        cvCopy(Lpic,ImgTemplt,NULL);
        cvResetImageROI(Lpic);    
        
        //获取图像1的轮廓
        CvSeq* contour1;
        contour1 = getImageContour(ImgTemplt);
    
        //循环计算右图特定区域的轮廓与模板图像contour1对比        
        IplImage * TempImg=cvCreateImage(cvSize(TemplWi,Rpic->height),Rpic->depth,1);//临时图像
        for(int i=0;i<(int)(Rpic->width-TemplWi)/10;++i)
        {
            CvRect rROI =cvRect(i,0,TemplWi,Rpic->height);
            cvSetImageROI(Rpic,rROI);
            cvCopy(Rpic,TempImg,NULL);
            cvResetImageROI(Rpic);        
            
            //获取图像2的轮廓
            CvSeq* contour2;
            contour2 = getImageContour(TempImg);
    
            MatchR resultS;
            resultS.PositionX=i;
            //计算匹配程度
            resultS.MResult=cvMatchShapes(contour1,contour2,1);
            
            vec.push_back(resultS);
            //释放轮廓存储空间
            cvReleaseMemStorage(&contour2->storage);
        }
    
        CvPoint StartPt;
        //排序找出vector中MResult最小的元素
        sort(vec.begin(),vec.end());
    
        StartPt.x=vec[0].PositionX+TemplWi;
        StartPt.y=0;
    
        //加载原图
        IplImage * LpicColor=cvLoadImage(LeftPath,CV_LOAD_IMAGE_COLOR);
        IplImage * RpicColor=cvLoadImage(RightPath,CV_LOAD_IMAGE_COLOR);
    
        //创建长度宽度合适的图像ResukltImage作拼接用
        int StitchImgWidth=LpicColor->width+(RpicColor->width-StartPt.x);
        IplImage * ResukltImage=cvCreateImage(cvSize(StitchImgWidth,LpicColor->height),LpicColor->depth,LpicColor->nChannels);
    
        //将左图复制到ResukltImage中
        CvRect ROI1=cvRect(0,0,LpicColor->width,LpicColor->height);
        cvSetImageROI(ResukltImage,ROI1);
        cvCopy(LpicColor,ResukltImage);
        cvResetImageROI(ResukltImage);
    
        //将右图的以StartPt为左上角的区域复制到ResukltImage的右侧剩余部分
        ROI1=cvRect(LpicColor->width,0,(ResukltImage->width-LpicColor->width),RpicColor->height);
        cvSetImageROI(ResukltImage,ROI1);
    
        CvRect ROI2=cvRect(StartPt.x,0,RpicColor->width-StartPt.x,RpicColor->height);
        cvSetImageROI(RpicColor,ROI2);
        cvCopy(RpicColor,ResukltImage,NULL);
        cvResetImageROI(RpicColor);
        cvResetImageROI(ResukltImage);
    
        //创建窗口显示拼接结果
        cvNamedWindow("拼接后图像",0);    
        cvShowImage("拼接后图像",ResukltImage);
    
        cvWaitKey(0);
    
        //释放轮廓存储空间
        cvReleaseMemStorage(&contour1->storage);
        //释放图像
        cvReleaseImage(&Lpic);
        cvReleaseImage(&Rpic);
        cvReleaseImage(&ImgTemplt);
        cvReleaseImage(&TempImg);
        cvReleaseImage(&ResukltImage);
        cvReleaseImage(&LpicColor);
        cvReleaseImage(&RpicColor);
        //销毁窗口
        cvDestroyWindow("拼接后图像");
        
        return 0;
    }
    
    /// <summary>
    /// 函数功能:获取输入图像的轮廓
    /// </summary>
    /// <param name="srcIn"></param>
    /// <returns>CvSeq* : 存储轮廓信息</returns>
    CvSeq* getImageContour(IplImage* srcIn)
    {
        IplImage* src;
        src = cvCreateImage(cvGetSize(srcIn),8,1);
        
        //拷贝图像 
        cvCopy(srcIn,src);
    
        //创建空间
        CvMemStorage* mem = cvCreateMemStorage(0);
        CvSeq* seq;
    
        if(!mem)
        {
            printf("mem is null");
        }
    
        //二值化图像
        cvThreshold(src,src,100,255,0);
        //cvCanny(src,src,15,30,3);
    
        //计算图像轮廓
        cvFindContours(src,mem,&seq,sizeof(CvContour),CV_RETR_CCOMP);
    
        //释放图像空间
        cvReleaseImage(&src);    
    
        //返回轮廓信息
        return seq;
    }

    待拼接的图像左图-->leftpic:

    待拼接的图像右图-->rightpic:

    结果图片:

     

      

    ‖==========钟于原创 乐于分享 宁静致远 毋忆典藏==========‖
  • 相关阅读:
    高手详解SQL性能优化十条经验
    大并发大数量中的MYSQL瓶颈与NOSQL介绍
    数据库索引的作用和优点缺点
    数据库优化方法整理
    Java中Date和Calender类的使用方法
    常用正则表达式大全 (转)
    java 反射的实例
    JAVA路径问题
    jsp ${param.id}用法
    jsp base标签与meta标签学习小结
  • 原文地址:https://www.cnblogs.com/tingshuixuan2012/p/ImageStitching.html
Copyright © 2020-2023  润新知