|
自己做的圖像拼接程序
51hei.png (18.85 KB, 下載次數(shù): 61)
下載附件
2021-3-6 01:12 上傳
51hei.png (48.4 KB, 下載次數(shù): 54)
下載附件
2021-3-6 01:11 上傳
DJI_0058.JPG (3.89 MB, 下載次數(shù): 60)
下載附件
2021-3-3 09:36 上傳
DJI_0059.JPG (4.42 MB, 下載次數(shù): 67)
下載附件
待拼接圖2
2021-3-3 09:36 上傳
較均勻分布且融合拼接圖拼接圖.jpg (211.65 KB, 下載次數(shù): 77)
下載附件
拼接圖
2021-3-3 09:37 上傳
源程序如下:
- //根據(jù)輸入圖像srcImg及其角點(diǎn)坐標(biāo)和篩選過的keypoints向量,拼接兩幅圖像,輸出拼接后的圖像及新圖像的角點(diǎn)
- class corners
- {
- public:
-
- Mat left_top,left_bottom,right_top,right_bottom;
-
- };
- //圖像融合總函數(shù)
- void FuseImg(Mat srcImg1, corners srcImg1_in_srcImg1,
- Mat srcImg2, corners srcImg2_in_srcImg2,
- vector<KeyPoint> FilterdKeypoints,
- vector<KeyPoint> matchedFilterdKeypoints,
- Mat &dstImg, corners &dstimg_in_dstimg);
- ////將原圖像角點(diǎn)變換至目標(biāo)圖像坐標(biāo)系下,確保corners_be_transformed里的矩陣數(shù)據(jù)類型為float型
- void put_value_2_transformed_corners(vector<Mat> corners_2_be_transformed,
- Mat H_inverted,
- vector<Mat> &corners_be_transformed);
- //根據(jù)兩幅圖像在新圖像中的位置,確定平移量
- void get_transformation(vector<Mat> corner_srcImg1_in_dstImg,
- vector<Mat> corner_srcImg2_in_dstImg,
- Mat &trf);
- //根據(jù)輸入圖角點(diǎn)在最終圖中的位置向量和位移,更新輸入圖角點(diǎn)在最終圖中的位置類corners,保證坐標(biāo)為int型
- void update_corners_in_dst(vector<Mat> corner_srcImg_in_dstImg,
- Mat trf, corners &mat_src_in_dst);
- //-----------------------------------------------計(jì)算dst的尺寸大小-----------------------------------------
- void cal_size_dstImg(vector<Mat> corner_srcImg1_in_dstImg,
- vector<Mat> corner_srcImg2_in_dstImg,
- Mat trsf, int &rows_dst, int &cols_dst);
- //計(jì)算像素點(diǎn)權(quán)值
- float get_frac(int i_rows, int j_cols, corners corner_mat);
- //根據(jù)輸入圖像角點(diǎn)位置更新輸出圖像角點(diǎn)
- void get_union_corner(corners corner_mat_src1_in_dst, corners corner_mat_src2_in_dst, corners &corner_mat_dstImg_in_dstImg);
- //將srcImg變換至dstImg上
- void transf_srcImg2dst(Mat srcImg2, Mat transformation, vector<KeyPoint> FilterdKeypoints, vector<KeyPoint> matchedFilterdKeypoints, Mat &dst);
- //用圖像src更新圖像dst
- void updateDstImg(Mat srcImg,corners corner_mat_src_in_dst, corners corner_mat_dst_in_dst,Mat &dstImg);
復(fù)制代碼- #include<iostream>
- #include <cxcore.h>
- #include <stdlib.h>
- #include <time.h>
- #include "opencv2/legacy/legacy.hpp"
- #include <E:\xunfei\stitch_sift20200330_vc10\stitch_sift20200330_vc10\runRansac.h>
- using namespace std;
- using namespace cv;
- /***************************** Function Prototypes ***************************/
- /**
- Calculates a best-fit image transform from image feature correspondences
- using RANSAC.
- @ keyPoints,matchedkeyPoints 特征點(diǎn)
- @ unFilteredMatches未篩選的特征匹配
- @ n 匹配數(shù)
- @ m 用來計(jì)算單應(yīng)性矩陣的最少特征匹配數(shù)
- @param p_badxform 模型允許的最大錯(cuò)誤概率
- @param err_tol 匹配誤差,通過單應(yīng)性矩陣變換后,計(jì)算匹配誤差,在此誤差內(nèi),認(rèn)為是內(nèi)點(diǎn)
- @param n_in 內(nèi)點(diǎn)數(shù)
- @filteredPoints, matchedFilteredPoints最終的內(nèi)點(diǎn)序列
- @filteredMatches,最終的特征匹配
- @返回最終單應(yīng)性矩陣
-
- */
- extern void ransac_xform( vector<KeyPoint> keyPoints,
- vector<KeyPoint> matchedkeyPoints,
- vector<DMatch> unFilteredMatches,
- int n, int m,double p_badxform,double err_tol ,
- int &n_in,
- vector<KeyPoint> &FilteredPoints,
- vector<KeyPoint> &matchedFilteredPoints,
- vector<DMatch> &FilteredMatches)
- {
- n=(int)unFilteredMatches.size();
- Mat M;//單應(yīng)性矩陣
- m=N;
- DMatch sample[N];//暫存被隨機(jī)抽取到的匹配
- DMatch* consensus;//當(dāng)前一致集
- DMatch* consensus_max = NULL;//當(dāng)前最大一致集
- double p, in_frac = RANSAC_INLIER_FRAC_EST;//p為當(dāng)前計(jì)算出的模型的錯(cuò)誤概率,當(dāng)p小于p_badxform時(shí)迭代終止,in_frac為內(nèi)點(diǎn)所占比例
- //in為當(dāng)前一致集元素個(gè)數(shù),in_min為一致集中元素個(gè)數(shù)允許的最小值,保證RANSAC最終計(jì)算出的轉(zhuǎn)換矩陣錯(cuò)誤的概率小于p_badxform所需的最小內(nèi)點(diǎn)數(shù)目
- //im_max為當(dāng)前最優(yōu)一致集中的元素個(gè)數(shù)
- //k為迭代次數(shù)
- //k_max為迭代次數(shù)最大值,即初始值
- int i, in, in_min, in_max = 0, k = 0, k_max;
- if(n<m)
- {
- cout<<"實(shí)際匹配數(shù)小于計(jì)算模型需用的最小匹配數(shù)"<<endl;
- }
- srand( (int)time(NULL) );//初始化隨機(jī)數(shù)發(fā)生器
- //計(jì)算保證RANSAC最終計(jì)算出的轉(zhuǎn)換矩陣錯(cuò)誤的概率小于p_badxform所需的最小內(nèi)點(diǎn)數(shù)目
- in_min = calc_min_inliers( n, m, RANSAC_PROB_BAD_SUPP, p_badxform );
- //計(jì)算k的最大值
- k_max = calc_max_k(in_frac, p_badxform, m);
- k=k_max;
- for(int j=0;j<k;j++)
- //for(int j=0;j<5;j++)
- {
- //pts與mpts為之后要用到的m個(gè)隨機(jī)特征點(diǎn)對(duì)
- vector<Point2f> pts,mpts;
- //隨機(jī)選擇m(4)個(gè)匹配
- draw_ransac_sample( unFilteredMatches, m, n,sample );
- //提取m個(gè)匹配對(duì)應(yīng)的特征點(diǎn)對(duì)
- extract_corresp_pts( keyPoints,matchedkeyPoints,sample, m, pts, mpts );
- //計(jì)算單應(yīng)性矩陣M
- xform_fn( pts, mpts, M );
- //計(jì)算一致集和內(nèi)點(diǎn)數(shù)
- consensus = new DMatch[n];
- in = find_consensus( keyPoints, matchedkeyPoints, unFilteredMatches, n, M, (double)err_tol, consensus);
- //更新最優(yōu)一致集的元素個(gè)數(shù)和最優(yōu)一致集
- if(in>in_max)
- {
- in_max = in;
- consensus_max=consensus;
- in_frac=((double)in_max)/((double)n);
- }
- else delete [] consensus;
- //根據(jù)當(dāng)前最優(yōu)一致集的元素個(gè)數(shù)是否大于要求的最小內(nèi)點(diǎn)數(shù),判斷是否繼續(xù)迭代
- if(in_max>in_min)
- {
- break;
- }
- //更新迭代次數(shù)k
- if(calc_max_k(in_frac, p_badxform, m)>5)
- {
- k = calc_max_k(in_frac, p_badxform, m);
- }
- }
- if(in_max>in_min)
- {
- for(int j=0; j<in_max; j++)
- {
- FilteredPoints.push_back(keyPoints[consensus_max[j].queryIdx]);
- matchedFilteredPoints.push_back(matchedkeyPoints[consensus_max[j].trainIdx]);
- FilteredMatches.push_back(consensus_max[j]);
-
- }
- n_in=in_max;
- }
- else
- {
- n_in=0;
- }
- }
- //計(jì)算計(jì)算保證RANSAC最終計(jì)算出的轉(zhuǎn)換矩陣錯(cuò)誤的概率小于p_badxform所需的最小內(nèi)點(diǎn)數(shù)目
- static int calc_min_inliers( int n, int m, double p_badsupp, double p_badxform )
- {
- double pi, sum;
- int i, j;
- for( j = m+1; j <= n; j++ )
- {
- sum = 0;
- for( i = j; i <= n; i++ )
- {
- pi = (i-m) * log( p_badsupp ) + (n-i+m) * log( 1.0 - p_badsupp ) +
- log_factorial( n - m ) - log_factorial( i - m ) -
- log_factorial( n - i );
- /*
- * Last three terms above are equivalent to log( n-m choose i-m )
- */
- sum += exp( pi );
- }
- if( sum < p_badxform )
- break;
- }
- return j;
- }
- //計(jì)算階乘的對(duì)數(shù)
- static inline double log_factorial( int n )
- {
- double f = 0;
- int i;
- for( i = 1; i <= n; i++ )
- f += log((double) i );
- return f;
- }
- //計(jì)算迭代次數(shù)k的初始值,也是最大值,程序運(yùn)行后不斷更新k;
- int calc_max_k(double in_frac, double p_badxform, int m)
- {
- double p;
- p=pow(in_frac, m);
- p=1-p;
- double s=0;
- int i=0;
- for(i=0;i<10000;i++)
- {
- s=pow(p, i);
- if(s<p_badxform)
- break;
- }
- return i;
- }
- //隨機(jī)選擇四個(gè)匹配作為計(jì)算單應(yīng)性矩陣的樣本值
- void draw_ransac_sample( vector<DMatch> unFilteredMatches, int m, int n, DMatch* sample )
- {
- for(int i=0;i<m;i++)
- {
- int id;
- for(int j=0;j<1000;j++)
- {
- id=rand()%n;
- if(id>(((int)unFilteredMatches.size())))
- break;
- }
- sample[i]=unFilteredMatches[id];
- }
- }
- //提取匹配關(guān)鍵點(diǎn)KeyPoints中的點(diǎn)坐標(biāo)輸入到Point2f點(diǎn)對(duì)中
- void extract_corresp_pts( vector<KeyPoint> kpts,
- vector<KeyPoint> mkpts,
- DMatch* sample, int m,
- vector<Point2f> &pts,
- vector<Point2f> &mpts )
- {
- for(int i=0;i<m;i++)
- {
- pts.push_back( kpts[sample[i].queryIdx].pt);
- mpts.push_back( mkpts[sample[i].trainIdx].pt);
- }
- }
- //根據(jù)4對(duì)匹配點(diǎn)坐標(biāo)計(jì)算單應(yīng)性矩陣
- void xform_fn( vector<Point2f> pts, vector<Point2f> mpts, Mat &M )
- {
- Mat mat(8,8,CV_32FC1,Scalar::all(0));
- Mat mat_invert(8,8,CV_32FC1,Scalar::all(0));
- //初始化系數(shù)矩陣行0,2,4,6
- for(int i_rows = 0; i_rows < 4; i_rows++)
- {
- mat.at<float>(2*i_rows,0) = pts[i_rows].x;//0列
- mat.at<float>(2*i_rows,1) = pts[i_rows].y;//1列
-
- mat.at<float>(2*i_rows,2) = 1.0;//2列
-
- mat.at<float>(2*i_rows,3) = 0.0;//3列
-
- mat.at<float>(2*i_rows,4) = 0.0;//4列
-
- mat.at<float>(2*i_rows,5) = 0.0;//5列
-
- mat.at<float>(2*i_rows,6) = -pts[i_rows].x*mpts[i_rows].x;//6列
-
- mat.at<float>(2*i_rows,7) = -pts[i_rows].y*mpts[i_rows].x;//7列
- }
- //初始化系數(shù)矩陣行1,3,5,7
- for(int i_rows = 0; i_rows<4; i_rows++)
- {
-
- mat.at<float>(1+2*i_rows,0) = 0.0;//0列
-
- mat.at<float>(1+2*i_rows,1) = 0.0;//1列
-
- mat.at<float>(1+2*i_rows,2) = 0.0;//2列
-
- mat.at<float>(1+2*i_rows,3) = pts[i_rows].x;//3列
-
- mat.at<float>(1+2*i_rows,4) = pts[i_rows].y;//4列
-
- mat.at<float>(1+2*i_rows,5) = 1.0;//5列
-
- mat.at<float>(1+2*i_rows,6) = -pts[i_rows].x*mpts[i_rows].y;//6列
-
- mat.at<float>(1+2*i_rows,7) = -pts[i_rows].y*mpts[i_rows].y;//7列
- }
- invert(mat,mat_invert);
-
- //計(jì)算得到向量or數(shù)組
- float vct_mat_invert[8][8],vctr2[8];
- for(int i_rows=0; i_rows<8; i_rows++)
- {
- for(int j_cols=0; j_cols<8; j_cols++)
- {
- vct_mat_invert[i_rows][j_cols] = mat_invert.at<float>(i_rows,j_cols);
- }
- }
- for(int id=0; id<4;id++)
- {
- vctr2[id*2] = mpts[id].x;
- vctr2[id*2+1] = mpts[id].y;
- }
- //計(jì)算homo
- Mat homo(3,3,CV_32FC1,Scalar::all(0));
- for(int i_rows = 0;i_rows < 3;i_rows++)
- {
- for(int j_cols = 0; j_cols<3 ; j_cols++)
- {
- if((i_rows*3+j_cols) < 8)
- {
- homo.at<float>(i_rows,j_cols) = calc_vct_in_prdct(vct_mat_invert[i_rows*3+j_cols], vctr2, 8);
- }
- else homo.at<float>(2,2)=1.0;
-
- }
- }
- M=homo;
- }
- //計(jì)算向量(or數(shù)組)內(nèi)積
- float calc_vct_in_prdct(float* vctr1, float* vctr2, int dim)
- {
- float VectorInnerProduct=0.0;
- for(int j=0;j<dim;j++)
- {
- VectorInnerProduct= VectorInnerProduct+vctr1[j]*vctr2[j];
- }
- return VectorInnerProduct;
- }
- //計(jì)算在單應(yīng)性矩陣下,一對(duì)匹配特征點(diǎn)的像素距離的平方,即誤差平方,返回值即為誤差平方
- float err_fn( KeyPoint pot, KeyPoint mpot, Mat M )
- {
- if((((int)M.rows)>3)||(((int)M.cols)>3))
- return 1000.0;
- float point[3],matched_point[3];
- point[0] = pot.pt.x;
- point[1] = pot.pt.y;
- point[2] = 1.0;
- matched_point[0] = mpot.pt.x;
- matched_point[1] = mpot.pt.y;
- matched_point[2] = 1.0;
-
- float transformed_point[3] = {0.0,0.0,0.0};
- for(int i=0; i<3; i++)
- {
- for(int j=0; j<3;j++)
- {
- transformed_point[i] = transformed_point[i] + M.at<float>(i,j)*point[j];
- }
- }
- //變換后的像素坐標(biāo)歸一化,即將各坐標(biāo)都除以Z坐標(biāo)
- for(int j=0; j<3; j++)
- {
- transformed_point[j] = transformed_point[j] / transformed_point[2];
- }
- float err_pixl_sqr = 0.0;
- for(int i=0; i<3; i++)
- {
- err_pixl_sqr = err_pixl_sqr + ( matched_point[i] - transformed_point[i] ) * ( matched_point[i] - transformed_point[i] );
- }
- return err_pixl_sqr;
- }
- //尋找一致集,返回一致集元素?cái)?shù)
- int find_consensus( vector<KeyPoint> kpts, vector<KeyPoint> mkpts, vector<DMatch> uFMaches, int n, Mat M, int err_tol, DMatch* consensus)
- {
- int num_matches = (int)uFMaches.size();
- int num_consensus=0;
- double err_sqr = pow((float)err_tol, 2);
- for(int i=0; i<num_matches; i++)
- {
- if(err_fn( kpts[uFMaches[i].queryIdx], mkpts[uFMaches[i].trainIdx], M )<err_sqr)
- {
- *(consensus + num_consensus)=uFMaches[i];
- num_consensus++;
- }
- }
- return num_consensus;
- }
復(fù)制代碼
下載:
代碼stitch_sift20200421_vc10.7z
(7.94 MB, 下載次數(shù): 7)
2021-3-6 01:15 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
圖片1.7z
(16.18 MB, 下載次數(shù): 5)
2021-3-6 01:16 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
圖片2.7z
(11.82 MB, 下載次數(shù): 5)
2021-3-6 01:17 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|