opencv--相关系数法影像匹配(数字摄影测量)

一、程序内容

  1. 以灰度的形式读入两副核线影像。 

  2. 读入左影像提取的特征点。

  3. 沿核线在右影像上计算每个候选匹配点的相关系数值。

  4. 取极值点以及NCC大于阈值的点作为同名点。

  5. 输出同名点到文件中,将同名点画到影像上,并用直线连接同名点。

二、设计思路

  • 同名点结构体:

    struct MatchPt2i//同名点结构体
    
    {
        Point2i lpt;//左核线影像上的点
    
        Point2i rpt;//右核线影像上的点
    
    };

     

  • CFeatureMatch类设计

私有数据成员:左核线影像,右核线影像,模板窗口大小(默认11),相关系数的阈值,同名点的个数,保存同名点的结构体数组。

成员函数:计算相关系数,给结果影像分配内存,影像匹配主函数。

  • 影像匹配算法流程

  1. 以灰度的形式读入两张核线影像,同时以彩色的形式读入核线影像(用于显示彩色结果)。

  2. 对左核线影像进行Moravec特征提取。

  3. 以提取到的特征点为中心开辟11X11的模板窗口。

  4. 在右影像的搜索区域内,以每一像素位置为中心,形成与模板窗口同样大小的搜索窗口,计算两个窗口的相关系数。搜索区域的确定:在核线影像中,同名点所在的同名核线的y坐标相同;x坐标在“视差±30”的范围内搜索。

  5. 将相关系数取得最大值并且大于阈值的点作为匹配到的同名点。

  6. 将同名点保存在一个结构体数组中,比你高将结果输出到“match_point。txt”文件中,第一行为点数,第二行开始为同名点坐标 x1 y1 x2 y2。

  7. 将两张彩色图像合并为一张影像,并将同名点用直线连起来。

三、注意事项

  • 在搜索匹配点时要注意的问题:

左影像的模板窗口中心的行号要从“5(窗口宽度的一半)”开始,到“影像的行数-5”结束,列号要从“530(视差大小加搜索范围)”开始,到“影像的行数-5”结束。

右影像的匹配窗口中心的行号和左影像保持一致,列号的搜索范围为“500(视差)±30”。

  • 显示结果为彩色的解决方法:

在以灰度的形式读入影像的同时,以彩色的形式再读入一张用于显示结果。

四、主要代码

//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:实现文件
#include "StdAfx.h"
#include "FeatureMatch.h"
#include "math.h"
#include "Moravec.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个
	Mat Interest;//兴趣矩阵
	CMoravec CM;
	int FeatureNum;//特征点个数
	CM.Moravec(LeftImgEpi,LeftImgColor,Interest,FeatureNum);//Moravec特征提取
	Mpt2i=new struct MatchPt2i[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),cvScalar(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
// ZQL_0107150120_3Dlg.h : 头文件
//

#pragma once
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"
using namespace cv;
// CZQL_0107150120_3Dlg 对话框
class CZQL_0107150120_3Dlg : public CDialogEx
{
public:
	Mat m_leftimg;            //左影像灰度矩阵
	Mat m_rightimg;           //右影像灰度矩阵
	Mat m_leftimgcolor;       //左影像彩色
	Mat m_rightimgcolor;      //右影像彩色
	CString strFileNameLeft;  //左影像文件路径
	CString strFileNameRight; //右影像文件路径
	bool bReadLeft;           //判断是否读入左影像
	bool bReadRight;          //判断是否读入右影像
	afx_msg void OnBnClickedBtnOpenimgleft(); //打开左影像
	afx_msg void OnBnClickedBtnOpenimgright();//打开右影像
	afx_msg void OnBnClickedCancel();         //退出对话框
	afx_msg void OnBnClickedBtnNccmatch();    //影像匹配

};
// ZQL_0107150120_3Dlg.cpp : 实现文件
//

#include "stdafx.h"
#include "ZQL_0107150120_3.h"
#include "ZQL_0107150120_3Dlg.h"
#include "afxdialogex.h"
#include "FeatureMatch.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CZQL_0107150120_3Dlg 对话框
CZQL_0107150120_3Dlg::CZQL_0107150120_3Dlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CZQL_0107150120_3Dlg::IDD, pParent)
	, strFileNameLeft(_T(""))
	, strFileNameRight(_T(""))
	, bReadLeft(FALSE)
	, bReadRight(FALSE)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CZQL_0107150120_3Dlg::OnBnClickedBtnOpenimgleft()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData(TRUE);
	CFileDialog FileDlg(TRUE,"*.jpg;*.bmp","*.jpg;*.bmp",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"影像文件()");
	if (FileDlg.DoModal()!=IDOK)
	{
		return;
	}
	strFileNameLeft=FileDlg.GetPathName();
	bReadLeft=TRUE;         //标记已经读入影像
	UpdateData(FALSE);  //将影像名字显示到对话框中
	m_leftimg=imread(strFileNameLeft.GetBuffer(),CV_LOAD_IMAGE_GRAYSCALE);//打开影像
	m_leftimgcolor=imread(strFileNameLeft.GetBuffer(),CV_LOAD_IMAGE_COLOR);//打开影像
	//imshow(_T("左影像"),m_leftimg); //图像显示
	cvWaitKey();  
}


void CZQL_0107150120_3Dlg::OnBnClickedBtnOpenimgright()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData(TRUE);
	CFileDialog FileDlg(TRUE,"*.jpg;*.bmp","*.jpg;*.bmp",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"影像文件()");
	if (FileDlg.DoModal()!=IDOK)
	{
		return;
	}
	strFileNameRight=FileDlg.GetPathName();
	bReadRight=TRUE;         //标记已经读入影像
	UpdateData(FALSE);  //将影像名字显示到对话框中
	m_rightimg=imread(strFileNameRight.GetBuffer(),CV_LOAD_IMAGE_GRAYSCALE);//打开影像
	m_rightimgcolor=imread(strFileNameRight.GetBuffer(),CV_LOAD_IMAGE_COLOR);//打开影像
	//imshow(_T("右影像"),m_rightimg); //图像显示
	cvWaitKey();  
}


void CZQL_0107150120_3Dlg::OnBnClickedCancel()
{
	// TODO: 在此添加控件通知处理程序代码
	CDialogEx::OnCancel();
}

void CZQL_0107150120_3Dlg::OnBnClickedBtnNccmatch()
{
	// TODO: 在此添加控件通知处理程序代码
	if (bReadLeft==FALSE)
	{
		MessageBox(_T("请读入左影像"));
		return;
	}
	if (bReadRight==FALSE)
	{
		MessageBox(_T("请读入右影像"));
		return;
	}
 	CFeatureMatch CFM;
	CFM.FeatureMatchMain(m_leftimg,m_rightimg,m_leftimgcolor,m_rightimgcolor);
}

 

五、运行结果

opencv--相关系数法影像匹配(数字摄影测量)_第1张图片

 

你可能感兴趣的:(c++代码,数字摄影测量,摄影测量,VC++,相关系数,影像匹配,opencv)