参考博客(5条消息) opencv--相关系数法影像匹配(数字摄影测量)_qiulanz的博客-CSDN博客_相关系数影像匹配
参考的代码分成了3部分,将3部分代码整合并且由于使用的opencv编译版本不一样,部分opencv自带的函数使用不一样
ZQLImgPro.h #pragma once #include"opencv2\core\core.hpp" using namespace cv; class CZQLImgPro { public: CZQLImgPro(void); ~CZQLImgPro(void); CZQLImgPro(int n_windowsize,float d_sigma);//构造函数重载(设置高斯滤波参数) CZQLImgPro(int i_binaryT); //构造函数重载(设置阈值分割参数) private: int nwindowsize; //高斯滤波器的大小 float sigma; //高斯滤波器方差 Mat Gauss; //高斯滤波器 int binaryT; //二值化阈值 private: void CreatGauss(); //生成高斯滤波器 public: void setGauss(int n_windowsize,float d_sigma); //设置高斯滤波参数 void setBinaryT(int i_binaryT); //设置二值化阈值 void BinaryImg(const Mat srcimg,Mat &result); //阈值分割函数 void Gaussianfilter(const Mat srcimg,Mat &result);//高斯滤波 }; ZQLImgPro.cpp #include"ZQLImgPro.h" #include"math.h" const float PI=4.0*atan(1.0); //默认构造函数 CZQLImgPro::CZQLImgPro(void) { nwindowsize=0; sigma=0; Gauss.create(nwindowsize,nwindowsize,CV_32F); } //析构函数 CZQLImgPro::~CZQLImgPro(void) { } //构造函数重载(设置高斯滤波参数) CZQLImgPro::CZQLImgPro(int n_windowsize,float d_sigma) { nwindowsize=n_windowsize; sigma=d_sigma; Gauss.create(nwindowsize,nwindowsize,CV_32F); } //构造函数重载(设置阈值分割参数) CZQLImgPro::CZQLImgPro(int iBinaryT) { binaryT=iBinaryT; } //设置高斯滤波参数 void CZQLImgPro::setGauss(int n_windowsize,float d_sigma) { nwindowsize=n_windowsize; sigma=d_sigma; Gauss.create(nwindowsize,nwindowsize,CV_32F); } //设置二值化阈值 void CZQLImgPro::setBinaryT(int iBinaryT) { binaryT=iBinaryT; } //阈值分割函数 void CZQLImgPro::BinaryImg(const Mat srcimg,Mat&result) { //给目标影像分配内存 result.create(srcimg.rows,srcimg.cols,srcimg.type()); for (int i=0;i(i,j); if (graytmp>binaryT) //大于阈值赋予255否则赋予0 result.at (i,j)=255; else result.at (i,j)=0; } } } //生成高斯滤波器 void CZQLImgPro::CreatGauss() { float sum=0; for(int i=0;i (i,j)=exp(-(x*x+y*y)/(2*sigma*sigma)) /(2*PI*sigma*sigma);//利用高斯公式计算计算滤波器 //float m=exp(-(x*x+y*y)/(2*sigma*sigma)); //float q=Gauss.at (i,j); sum+=Gauss.at (i,j); } } //进行归一化处理 for(int i=0;i (i,j)/=sum; } } } //高斯滤波 void CZQLImgPro::Gaussianfilter(const Mat srcimg,Mat&result) { CreatGauss();//计算高斯滤波器 //给目标影像分配内存 result.create(srcimg.rows,srcimg.cols,srcimg.type()); int rows=srcimg.rows; int cols=srcimg.cols; for (int i=0;i (i,j)=0; //将结果矩阵初始化为零矩阵 } } int nhalfw=nwindowsize/2; int sum=0; for (int i=nhalfw;i (m+nhalfw,n+nhalfw)*srcimg.at (i+m,j+n); //利用高斯滤波器进行卷积 } } result.at (i,j)=sum; } } }
CMoravec.h #pragma once #include "opencv2\highgui\highgui.hpp" using namespace cv; class CMoravec { public: CMoravec(void); ~CMoravec(void); Mat Interest; //兴趣值矩阵 int IVwindowsize; //兴趣值计算窗口大小 int NMSwindowsize; //抑制局部非最大窗口大小 int intvalueT; //兴趣阈值 int FeatureNum; //特征点个数 private: void InterestValue(const Mat srcimg); //计算兴趣值 void CandidatePoint(); //选择候选点 void FeaturePoint (); //抑制局部非最大 void Mark (Mat &dstimg); //标记特征点 public: void Moravec(const Mat srcimg,Mat &dstimg,Mat Interest);// Moravec算法主函数 };
CMoravec.cpp #include#include "Moravec.h" #include "ZQLImgPro.h" CMoravec::CMoravec(void) { IVwindowsize=5; NMSwindowsize=5; intvalueT=200; } CMoravec::~CMoravec(void) { } //计算兴趣值 void CMoravec::InterestValue(const Mat srcimg) { Interest.create(srcimg.rows,srcimg.cols,CV_32S); int rows=srcimg.rows; int cols=srcimg.cols; for (int i=0;i (i,j)=0; //将兴趣值矩阵初始化为零矩阵 } } int k=int(IVwindowsize/2); for (int r=k;r (r,c+i)-srcimg.at (r,c+i+1))* (srcimg.at (r,c+i)-srcimg.at (r,c+i+1)); v2+=(srcimg.at (r+i,c+i)-srcimg.at (r+i+1,c+i+1))* (srcimg.at (r+i,c+i)-srcimg.at (r+i+1,c+i+1)); v3+=(srcimg.at (r+i,c)-srcimg.at (r+i+1,c))* (srcimg.at (r+i,c)-srcimg.at (r+i+1,c)); v4+=(srcimg.at (r-i,c+i)-srcimg.at (r-i-1,c+i+1))* (srcimg.at (r-i,c+i)-srcimg.at (r-i-1,c+i+1)); } Interest.at (r,c)=min(min(min(v1,v2),v3),v4); //取v1,v2,v3,v4中的最小值作为兴趣值 } } } //选择候选点 void CMoravec::CandidatePoint() { for (int i=0;i (i,j)<=intvalueT) Interest.at (i,j)=0; } } } //抑制局部非最大 void CMoravec::FeaturePoint() { int halfw=NMSwindowsize/2; for (int i=halfw;i (i,j) (i+m,j+n)) Interest.at (i,j)=0; } } } } } //标记特征点 void CMoravec::Mark(Mat &dstimg) { FILE *fp=fopen("result.txt","w"); if (fp == NULL) { return; } fprintf(fp,"%s\t%s\n","像素位置","兴趣值"); for (int i=3;i (i,j)!=0) { circle(dstimg,Point(j,i),1,Scalar(0,0,255),-1); //将特征点标记为实心点 fprintf(fp,"(%1i,\t%1i)\t%1i\n",i,j,Interest.at (i,j)); // FeatureNum++; } } } fclose(fp); //显示影像 //imshow(_T("结果影像"),dstimg); //waitKey(); } void CMoravec::Moravec(const Mat srcimg, Mat &dst, Mat Gauss) { CZQLImgPro CIP(3,1.5); CIP.Gaussianfilter(srcimg,Gauss);// 高斯滤波 InterestValue(Gauss); CandidatePoint(); FeaturePoint(); Mark(dst); }
FeatureMatch.h
//FeatureMatch.h:头文件 #pragma once #include "opencv2/highgui/highgui.hpp" #include "opencv2/core/core.hpp" #include "Moravec.h" using namespace cv; struct MatchPt2i//同名点结构体 { Point2i lpt;//左核线影像上的点 Point2i rpt;//右核线影像上的点 }; class CFeatureMatch { public: CFeatureMatch(void); ~CFeatureMatch(void); private: Mat LeftImgEpi; //左核线影像 Mat RightImgEpi; //右核线影像 int windowsize; //模板窗口的大小 double Threshold;//相关系数的阈值 int num; //匹配同名点个数 MatchPt2i *Mpt2i;//同名点结构体数组 private: double NCCScore(int lr,int lc,int rr,int rc);//计算相关系数 void showresult(const Mat LeftImgColor,const Mat RightImgColor,Mat &ResultImg);//给结果影像分配内存 public: void FeatureMatchMain(Mat LeftImg,Mat RightImg,Mat LeftImgColor,Mat RightImgColor);//影像匹配主函数 };
FeatureMatch.cpp
//FeatureMatch.cpp:实现文件 #include#include #include "FeatureMatch.h" #include "math.h" CFeatureMatch::CFeatureMatch(void) { windowsize=11; Threshold=0.7; Mpt2i=NULL; num=0; } CFeatureMatch::~CFeatureMatch(void) { } void CFeatureMatch::showresult(const Mat LeftImgColor,const Mat RightImgColor,Mat &ResultImg) { ResultImg.create(2*LeftImgColor.rows,LeftImgColor.cols,LeftImgColor.type()); for (int i=0;i (i,j)=LeftImgColor.at (i,j); } } for (int i=0;i (i+LeftImgColor.rows,j)=RightImgColor.at (i,j); } } } double CFeatureMatch::NCCScore(int lr,int lc,int rr,int rc) { double gLeftAverage=0;//左影像窗口灰度平均值 double gRightAverage=0;//右影像窗口灰度平均值 int halfsize=windowsize/2; for (int i=-halfsize;i (lr+i,lc+j); gRightAverage+=RightImgEpi.at (rr+i,rc+j); } } gLeftAverage/=windowsize*windowsize; gRightAverage/=windowsize*windowsize; double a=0; double b=0; double c=0; for (int i=-halfsize;i (lr+i,lc+j)-gLeftAverage; double right_av=RightImgEpi.at (rr+i,rc+j)-gRightAverage; a+=left_av*right_av; b+=left_av*left_av; c+=right_av*right_av; } } return a/sqrt(b*c);//返回相关系数的大小 } void CFeatureMatch::FeatureMatchMain(Mat LeftImg,Mat RightImg,Mat LeftImgColor,Mat RightImgColor) { LeftImgEpi=LeftImg; RightImgEpi=RightImg; Mat Result; showresult(LeftImgColor,RightImgColor,Result);//将两张彩色影像和合并1个 CMoravec CM; CM.Moravec(LeftImgEpi,LeftImgColor,CM.Interest);//Moravec特征提取 Mpt2i=new struct MatchPt2i[CM.FeatureNum];//给同名点结构体数组分配内存空间 int halfsize=windowsize/2; //搜索匹配点 for (int i=halfsize;i (i,j)!=0) //特征点作为模板中心 { double maxscore=0; for (int c=j-530;c maxscore) { maxscore=score;//计算相关系数的最大值 } } for (int c=j-530;c Threshold)) { //用直线连接同名点 line(Result,Point(j,i),Point(c,i+RightImgEpi.rows),Scalar(0,0,255)); //将匹配结果存入数组 Mpt2i[num].lpt=Point(j,i); Mpt2i[num].rpt=Point(c,i); num+=1; } } } } } imwrite("result.jpg",Result); //将匹配结果写入文件 FILE *fp=fopen("match_point.txt","w"); if (fp == NULL) { return; } fprintf(fp,"%1i\n",num); for (int i=0;i 主函数就随手写了一个
#include#include #include "FeatureMatch.h" using namespace std; using namespace cv; int main() { Mat LeftImg = imread("D:\\exam_jpg\\uavl.jpg",0); Mat RightImg = imread("D:\\exam_jpg\\uavr.jpg",0); Mat LeftImgColor = imread("D:\\exam_jpg\\uavr.jpg",1); Mat RightImgColor = imread("D:\\exam_jpg\\uavr.jpg",1); CFeatureMatch CFM; CFM.FeatureMatchMain(LeftImg,RightImg,LeftImgColor,RightImgColor); return 0; }