参考博客(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)(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;cmaxscore)
{
maxscore=score;//计算相关系数的最大值
}
}
for (int c=j-530;cThreshold))
{
//用直线连接同名点
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;
}
Original: https://blog.csdn.net/rjswsq1998/article/details/121847527
Author: rjswsq1998
Title: opencv–相关系数法影像匹配
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/704084/
转载文章受原作者版权保护。转载请注明原作者出处!