以灰度的形式读入两副核线影像。
读入左影像提取的特征点。
沿核线在右影像上计算每个候选匹配点的相关系数值。
取极值点以及NCC大于阈值的点作为同名点。
输出同名点到文件中,将同名点画到影像上,并用直线连接同名点。
同名点结构体:
struct MatchPt2i//同名点结构体
{
Point2i lpt;//左核线影像上的点
Point2i rpt;//右核线影像上的点
};
CFeatureMatch类设计
私有数据成员:左核线影像,右核线影像,模板窗口大小(默认11),相关系数的阈值,同名点的个数,保存同名点的结构体数组。
成员函数:计算相关系数,给结果影像分配内存,影像匹配主函数。
影像匹配算法流程
以灰度的形式读入两张核线影像,同时以彩色的形式读入核线影像(用于显示彩色结果)。
对左核线影像进行Moravec特征提取。
以提取到的特征点为中心开辟11X11的模板窗口。
在右影像的搜索区域内,以每一像素位置为中心,形成与模板窗口同样大小的搜索窗口,计算两个窗口的相关系数。搜索区域的确定:在核线影像中,同名点所在的同名核线的y坐标相同;x坐标在“视差±30”的范围内搜索。
将相关系数取得最大值并且大于阈值的点作为匹配到的同名点。
将同名点保存在一个结构体数组中,比你高将结果输出到“match_point。txt”文件中,第一行为点数,第二行开始为同名点坐标 x1 y1 x2 y2。
将两张彩色图像合并为一张影像,并将同名点用直线连起来。
在搜索匹配点时要注意的问题:
左影像的模板窗口中心的行号要从“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);
}