用opencv開源包實現了下圖像拼接


網上搜的都是一行代碼Stitcher::Status status = stitcher.stitch(imgs, pano);就出來的傻瓜拼接,連opencv基本的包都沒用。

自己好歹用了下基本的包實現了下。

魯棒性不太好,圖片少的時候沒事,圖片一多就出現了內存錯誤和木有特征點的錯誤。

#include <iostream>
#include <fstream>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/stitching/stitcher.hpp"
#include "opencv2/stitching/warpers.hpp"

#define MaxPics 30
//F:\Program Files\opencv\modules\stitching\include\opencv2\stitching
using namespace std;
using namespace cv;
bool try_use_gpu = false;
int filenum;
vector<Mat> imgs;
string result_name = "result.jpg";
//void printUsage();
//int parseCmdArgs(int argc, char** argv);
int readDir(char *path,char fnames[MaxPics][100]);

int readDir(char *path,char fnames[MaxPics][100])
{
 struct _finddata_t c_file;
 intptr_t hFile;
 filenum=0;

 char fullpath[100];

 sprintf(fullpath,"%s\\*.jpg",path);
 // Find first .c file in current directory
 if( (hFile = _findfirst( fullpath, &c_file )) == -1L )
  printf( "No *.jpg files in current directory %s!\n",fullpath);
 else
 {
  printf( "Listing of .jpg files in %s directory\n\n",path);
  printf( "RDO HID SYS ARC  FILE                  SIZE\n", ' ' );
  printf( "--- --- --- ---  ----                  ----\n", ' ' );
  do {
   printf( ( c_file.attrib & _A_RDONLY ) ? " Y  " : " N  " );
   printf( ( c_file.attrib & _A_SYSTEM ) ? " Y  " : " N  " );
   printf( ( c_file.attrib & _A_HIDDEN ) ? " Y  " : " N  " );
   printf( ( c_file.attrib & _A_ARCH )   ? " Y  " : " N  " );
   //ctime_s( buffer, _countof(buffer), &c_file.time_write );
   printf( " %-15s  %9ld\n",c_file.name, c_file.size );
   sprintf(fnames[filenum],"%s\\%s",path,c_file.name);
   filenum++;
  } while( _findnext( hFile, &c_file ) == 0 );
  _findclose( hFile );
 }
 return filenum;
}
int main(int argc, char* argv[])
{
 clock_t start,finish;
   double totaltime;
   start=clock();

  
 argv[1]="pic";
 char fdir[MaxPics][100];
 filenum = readDir(argv[1],fdir);
 Mat img, pano;
 for(int i=0 ; i<filenum ;i++){
  img = imread(fdir[i]);
  imgs.push_back(img);
 }
 Stitcher stitcher =  Stitcher::createDefault(try_use_gpu);
 stitcher.setRegistrationResol(0.1);//為了加速,我選0.1,默認是0.6,最大值1最慢,此方法用於特征點檢測階段,如果找不到特征點,調高吧
    //stitcher.setSeamEstimationResol(0.1);//默認是0.1
    //stitcher.setCompositingResol(-1);//默認是-1,用於特征點檢測階段,找不到特征點的話,改-1
 stitcher.setPanoConfidenceThresh(1);//默認是1,見過有設0.6和0.4的
    stitcher.setWaveCorrection(false);//默認是true,為加速選false,表示跳過WaveCorrection步驟
    //stitcher.setWaveCorrectKind(detail::WAVE_CORRECT_HORIZ);//還可以選detail::WAVE_CORRECT_VERT ,波段修正(wave correction)功能(水平方向/垂直方向修正)。因為setWaveCorrection設的false,此語句沒用
 
 //找特征點surf算法,此算法計算量大,但對剛體運動、縮放、環境影響等情況下較為穩定
 detail::SurfFeaturesFinder *featureFinder = new detail::SurfFeaturesFinder();
 stitcher.setFeaturesFinder(featureFinder);
 
 //找特征點ORB算法,但是發現草地這組圖,這個算法不能完成拼接
 //detail::OrbFeaturesFinder *featureFinder = new detail::OrbFeaturesFinder();
 //stitcher.setFeaturesFinder(featureFinder);

    //Features matcher which finds two best matches for each feature and leaves the best one only if the ratio between descriptor distances is greater than the threshold match_conf.
 detail::BestOf2NearestMatcher *matcher = new detail::BestOf2NearestMatcher(false, 0.5f/*=match_conf默認是0.65,我選0.8,選太大了就沒特征點啦,0.8都失敗了*/);
 stitcher.setFeaturesMatcher(matcher);
   
 // Rotation Estimation,It takes features of all images, pairwise matches between all images and estimates rotations of all cameras.
 //Implementation of the camera parameters refinement algorithm which minimizes sum of the distances between the rays passing through the camera center and a feature,這個耗時短
 stitcher.setBundleAdjuster(new detail::BundleAdjusterRay());
 //Implementation of the camera parameters refinement algorithm which minimizes sum of the reprojection error squares.
 //stitcher.setBundleAdjuster(new detail::BundleAdjusterReproj());
 
 //Seam Estimation
 //Minimum graph cut-based seam estimator
  //stitcher.setSeamFinder(new detail::GraphCutSeamFinder(detail::GraphCutSeamFinderBase::COST_COLOR));//默認就是這個
 //stitcher.setSeamFinder(new detail::GraphCutSeamFinder(detail::GraphCutSeamFinderBase::COST_COLOR_GRAD));//GraphCutSeamFinder的第二種形式
 //啥SeamFinder也不用,Stub seam estimator which does nothing.
 stitcher.setSeamFinder(new detail::NoSeamFinder);
 //Voronoi diagram-based seam estimator.
 //stitcher.setSeamFinder(new detail::VoronoiSeamFinder);

 //exposure compensators曝光補償
 //stitcher.setExposureCompensator(new detail::BlocksGainCompensator());//默認的就是這個
 //不要曝光補償
 stitcher.setExposureCompensator(new detail::NoExposureCompensator());
 //Exposure compensator which tries to remove exposure related artifacts by adjusting image intensities
 //stitcher.setExposureCompensator(new detail::detail::GainCompensator());
 //Exposure compensator which tries to remove exposure related artifacts by adjusting image block intensities 
 //stitcher.setExposureCompensator(new detail::detail::BlocksGainCompensator());
 
 //Image Blenders
 //Blender which uses multi-band blending algorithm
 //stitcher.setBlender(new detail::MultiBandBlender(try_use_gpu));//默認的是這個
 //Simple blender which mixes images at its borders
 stitcher.setBlender(new detail::FeatherBlender());//這個簡單,耗時少

 //柱面?球面OR平面?默認為球面
 PlaneWarper*  cw = new PlaneWarper();
 //SphericalWarper*  cw = new SphericalWarper();
 //CylindricalWarper*  cw = new CylindricalWarper();
 stitcher.setWarper(cw);

 Stitcher::Status status = stitcher.estimateTransform(imgs);
    if (status != Stitcher::OK)
    {
  cout << "Can't stitch images, error code = " << int(status) << endl;
  return -1;
 }
    status = stitcher.composePanorama(pano);
 if (status != Stitcher::OK)
    {
  cout << "Can't stitch images, error code = " << int(status) << endl;
  return -1;
 }
 cout<<"程序開始";
 imwrite(result_name, pano);
 finish=clock();
   totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
   cout<<"\n此程序的運行時間為"<<totaltime<<"秒!"<<endl;
 return 0;
}

至於其他的拼接方式,http://academy.nearsoft.com/project-updates/makingapanoramapicture寫的挺好。我引用之,並總結如下

1,Stitcher class from OpenCV library

 

  • Pros
    • Extremely simple. Build panorama in just one command.
    • It performs from finding features through blending in the selected projection by itself.
  • Cons
    • Uses SURF algorithm (patented, not allowed for commercial use).
    • Slow at searching for features, running on a smartphone

2,BoofCV

 

  • Pros
    • Still easy to use.
    • Java native.
  • Cons
    • It blends without warping into the spherical projection.
    • Still uses SURF.

當然自己實現最好,我的上述代碼就是第一種了

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM