opencv--相关系数法影像匹配(数字摄影测量)
来源:互联网 发布:淘宝智能仓库 编辑:程序博客网 时间:2024/04/29 08:18
一、程序内容
1.以灰度的形式读入两副核线影像。
2.读入左影像提取的特征点。
3.沿核线在右影像上计算每个候选匹配点的相关系数值。
4.取极值点以及NCC大于阈值的点作为同名点。
5.输出同名点到文件中,将同名点画到影像上,并用直线连接同名点。
二、设计思路
1.同名点结构体:
struct MatchPt2i//同名点结构体
{
Point2i lpt;//左核线影像上的点
Point2i rpt;//右核线影像上的点
};
2.CFeatureMatch类设计
私有数据成员:左核线影像,右核线影像,模板窗口大小(默认11),相关系数的阈值,同名点的个数,保存同名点的结构体数组。
成员函数:计算相关系数,给结果影像分配内存,影像匹配主函数。
3.影像匹配算法流程
(1)以灰度的形式读入两张核线影像,同时以彩色的形式读入核线影像(用于显示彩色结果)。
(2)对左核线影像进行Moravec特征提取。
(3)以提取到的特征点为中心开辟11X11的模板窗口。
(4)在右影像的搜索区域内,以每一像素位置为中心,形成与模板窗口同样大小的搜索窗口,计算两个窗口的相关系数。
搜索区域的确定:在核线影像中,同名点所在的同名核线的y坐标相同;x坐标在“视差±30”的范围内搜索。
(5)将相关系数取得最大值并且大于阈值的点作为匹配到的同名点。
(6)将同名点保存在一个结构体数组中,比你高将结果输出到“match_point。txt”文件中,第一行为点数,第二行开始为同名点坐标 x1 y1 x2 y2。
(7)将两张彩色图像合并为一张影像,并将同名点用直线连起来。
三、注意事项
1. 在搜索匹配点时要注意的问题:
左影像的模板窗口中心的行号要从“5(窗口宽度的一半)”开始,到“影像的行数-5”结束,列号要从“530(视差大小加搜索范围)”开始,到“影像的行数-5”结束。
右影像的匹配窗口中心的行号和左影像保持一致,列号的搜索范围为“500(视差)±30”。
2. 显示结果为彩色的解决方法:
在以灰度的形式读入影像的同时,以彩色的形式再读入一张用于显示结果。
四、主要代码
//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<LeftImgColor.rows;i++){for (int j=0;j<LeftImgColor.cols;j++){ResultImg.at<Vec3b>(i,j)=LeftImgColor.at<Vec3b>(i,j);}}for (int i=0;i<RightImgColor.rows;i++){for (int j=0;j<RightImgColor.cols;j++){ResultImg.at<Vec3b>(i+LeftImgColor.rows,j)=RightImgColor.at<Vec3b>(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<windowsize-halfsize;i++){for (int j=-halfsize;j<windowsize-halfsize;j++){gLeftAverage+=LeftImgEpi.at<uchar>(lr+i,lc+j);gRightAverage+=RightImgEpi.at<uchar>(rr+i,rc+j);}}gLeftAverage/=windowsize*windowsize;gRightAverage/=windowsize*windowsize;double a=0;double b=0;double c=0;for (int i=-halfsize;i<windowsize-halfsize;i++){for (int j=-halfsize;j<windowsize-halfsize;j++){double left_av=LeftImgEpi.at<uchar>(lr+i,lc+j)-gLeftAverage;double right_av=RightImgEpi.at<uchar>(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<LeftImgEpi.rows-halfsize;i++){for (int j=530;j<LeftImgEpi.cols-halfsize;j++){if (Interest.at<int>(i,j)!=0)//特征点作为模板中心{double maxscore=0;for (int c=j-530;c<j-470;c++){double score=NCCScore(i,j,i,c);//计算相关系数if (score>maxscore){maxscore=score;//计算相关系数的最大值}} for (int c=j-530;c<j-470;c++){double score=NCCScore(i,j,i,c);if ((score==maxscore)&&(score>Threshold)){//用直线连接同名点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<num;i++){fprintf(fp,"%04d %04d %04d %04d\n",Mpt2i[i].lpt.x,Mpt2i[i].lpt.y,Mpt2i[i].rpt.x,Mpt2i[i].rpt.y);}fclose(fp);}
// 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--相关系数法影像匹配(数字摄影测量)
- 数字近景摄影测量
- 基于opencv的Morevec算子特征提取(数字摄影测量)
- 数字摄影测量的思考
- 摄影测量 数字近景摄影测量 相机标定 光束法平差优化
- opencv双目视觉标定、匹配和测量 (附代码)
- opencv双目视觉标定、匹配和测量 (附代码)
- 模板匹配与相关系数法
- 模板匹配与相关系数法
- 基于全数字摄影测量工作站制作DOM简介
- 【摄影测量】简单说说反解法数字微分纠正
- opencv双目视觉标定、匹配和测量
- 摄影测量实习报告
- 摄影测量知识日积月累
- 全息摄影测量
- 摄影测量后方交会
- 摄影测量--共线方程
- 摄影测量笔记
- DexIndexOverflowException两种情况的解决方法
- NetApp3120存储数据恢复_RAID数据恢复过程
- 编辑器-WebStorm常用快捷键
- format函数中用于格式化日期时间的字符
- hexo简介
- opencv--相关系数法影像匹配(数字摄影测量)
- 同时获得深度/彩色/骨骼
- 利用java编写发送邮件
- 自定义View 实现左右拖动脉象图
- 微信自动发朋友圈源码
- QtCreater添加外部库编译error: C1083: 无法打开包括文件: “openssl/pkcs12.h”: No such file or directory原因分析
- Linux系统配置mysql允许被远程访问
- Python学习笔记--线程锁
- Nginx+tomcat配置https后出现400 Bad Request问题