windows VS2013实测可以,我自己改了一些东西,以便能运行
在项目|属性|配置属性|C/C++|预处理器|预处理定义中加入 _CRT_SECURE_NO_DEPRECATE
头文件:
points.h
////////////////////////////////////////////////////////////////////////////
// File: points.h
// Author: Changchang Wu ([email protected])
// Description :
//
// Copyright (c) 2011 Changchang Wu ([email protected])
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// Version 3 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef POINTS_H_INCLUDED
#define POINTS_H_INCLUDED
#pragma once
template class Points;
//#define USE_MEM_COLLECT
template
class Points
{
typedef T (*TV2)[2];
typedef T (*TV3)[3];
typedef T (*TV5)[5];
typedef T (*TV128)[128];
protected:
T * _data;
T ** _matrix;
int _width;
int _height;
bool _subset;
private:
void init(int width, int height)
{
_subset = 0;
if( width >0 && height >0 )
{
_matrix = (T**) malloc(sizeof(T)*width*height+sizeof(T*)*height);
if(_matrix)
{
_data = (T* ) (_matrix+height);
T* temp = _data;
for( int i =0 ; i < height; _matrix[i++]=temp, temp+=width);
_width = width;
_height = height;
}else
{
_width = _height = 0;
_data = NULL;
}
}else
{
_width = _height = 0;
_data = NULL;
_matrix = NULL;
}
}
public:
Points()
{
_data = NULL;
_matrix = NULL;
_height = 0;
_width = 0;
_subset = 0;
}
Points(const Points &ref)
{
init(ref.width(), ref.height());
copy_from(ref, 0, 0);
}
Points(int width, int height)
{
init(width, height);
}
Points(int width, int height, T v)
{
init(width, height);
fill(v);
}
Points(T** sup, int ndim, int num)
{
_subset = true;
_width = ndim;
_height = num;
_data = NULL;
if(num>0 && ndim>0)
{
_matrix = (T**) malloc(sizeof(T*)*num);
for (int i = 0; i < num; i++) _matrix[i]= sup[i];
}else
{
_matrix = NULL;
}
}
void setx(int width, int height, T* data)
{
release();
_subset = 1;
_width = width;
_height = height;
_data = data;
_matrix = (T**) malloc(sizeof(T*) * height);
for(int i = 0; i < height; i++, data += width) _matrix[i] = data;
}
template
Points(POINTS& sup, int index [], int num)
{
_subset = true;
_width = sup.width();
_height = num;
_data = sup.data();
if(num>0 && _width>0)
{
_matrix = (T**) malloc(sizeof(T*)*num);
for (int i = 0; i < num; i++) _matrix[i]=sup[index[i]];
}else
{
_matrix = NULL;
}
}
private:
void release()
{
if(_matrix) free(_matrix);
}
public:
void resize(int width, int height)
{
if(width == _width && height ==_height) return;
release();
init(width, height);
}
void resize(int width, int height, T v)
{
resize(width, height);
fill(v);
}
void expand(int width, int height)
{
//make sure size are
if(width < _width || height < _height) return;
if(width ==_width && height ==_height && _subset ==0) return;
T* newdata, **newmatrix, *temp;
int i;
newmatrix = (T**) malloc(sizeof(T)*width*height+sizeof(T*)*height);
temp = newdata = (T* ) (newmatrix+height);
for( i =0 ; i < height;i++, temp+=width)
{
newmatrix[i]=temp;
}
for( i = 0; i< _height; i++)
{
memcpy(newmatrix[i], _matrix[i], _width*sizeof(T));
}
release();
_subset = 0;
_width = width;
_height = height;
_matrix = newmatrix;
_data = newdata;
}
void expand(int width, int height, T v)
{
//make sure size are
if(width < _width || height < _height) return;
if(width ==_width && height ==_height && _subset ==0) return;
T* newdata, **newmatrix, *temp;
int i, j;
newmatrix = (T**) malloc(sizeof(T)*width*height+sizeof(T*)*height);
temp = newdata = (T* ) (newmatrix+height);
for( i =0 ; i < height;i++, temp+=width)
{
newmatrix[i]=temp;
}
for( i = 0; i< _height; i++)
{
memcpy(newmatrix[i], _matrix[i], _width*sizeof(T));
for(j = _width; j < width; ++j) newmatrix[i][j] = v;
}
for(; i < height; i++)
{
for(j = 0; j < width; ++j) newmatrix[i][j] = v;
}
release();
_subset = 0;
_width = width;
_height = height;
_matrix = newmatrix;
_data = newdata;
}
void copy_from(const Points& src, int dx, int dy)
{
int nw = min(src.width() , width() - dx);
int nh = min(src.height(), height() - dy);
/////////////////////////////////////////////
for(int i = 0; i < nh; ++i)
{
for(int j = 0; j < nw; ++j)
{
_matrix[i + dy][j + dx] = src._matrix[i][j];
}
}
}
void swap(Points& temp)
{
T * data = _data;
T ** matrix = _matrix;
int width = _width;
int height = _height;
bool subset = _subset;
_data = temp._data;
_matrix = temp._matrix;
_width = temp._width;
_height = temp._height;
_subset = temp._subset;
temp._data = data;
temp._matrix = matrix;
temp._width = width;
temp._height = height;
temp._subset = subset;
}
void make_sub_from(Points& src, int dx, int dy)
{
int nw = min(src.width() - dx , width());
int nh = min(src.height()- dy, height() );
/////////////////////////////////////////////
for(int i = 0; i < nh; ++i)
{
for(int j = 0; j < nw; ++j)
{
_matrix[i][j] = src._matrix[i + dy][j + dx];
}
}
}
void shrink(int width, int height)
{
//make sure size are
if(width > _width || height > _height) return;
if(width ==_width && height ==_height) return;
T* newdata, **newmatrix, *temp;
int i;
newmatrix = (T**) malloc(sizeof(T)*width*height+sizeof(T*)*height);
temp = newdata = (T* ) (newmatrix+height);
for( i =0 ; i < height;i++, temp+=width)
{
newmatrix[i]=temp;
}
for( i = 0; i< height; i++)
{
memcpy(newmatrix[i], _matrix[i], width*sizeof(T));
}
release();
_subset = 0;
_width = width;
_height = height;
_matrix = newmatrix;
_data = newdata;
}
~Points()
{
release();
}
T* data()
{
return _data;
}
T* end()
{
return _data + _width * _height;
}
int invalid()
{
return _width == 0 || _height == 0;
}
int bsize()
{
return _width*_height*sizeof(T);
}
int width() const
{
return _width;
}
int height() const
{
return _height;
}
int ndim() const
{
return _width;
}
int npoint() const
{
return _height;
}
T* operator[](int i)
{
return _matrix[i];
}
T* operator[](int i) const
{
return _matrix[i];
}
Points& operator = (const Points& ref)
{
resize(ref.width(), ref.height());
if(_width > 0 && _height > 0)
{
if(ref._subset)
{
for(int i = 0; i < _height; ++i)
{
memcpy(_matrix[i], ref._matrix[i], _width * sizeof(T));
}
}else
{
memcpy(_data, ref._data, bsize());
}
}
return * this;
}
void own_data()
{
if(_subset)expand(_width, _height);
}
operator T** const () const
{
return _matrix;
}
operator T** ()
{
return _matrix;
}
operator TV2()
{
#ifdef _DEBUG
return _width==2 && _subset == 0 ? (T (*)[2]) _data : NULL;
#else
return (T (*)[2]) _data;
#endif
}
operator TV3()
{
#ifdef _DEBUG
return _width==3 && _subset == 0 ? (T (*)[3]) _data : NULL;
#else
return (T (*)[3]) _data ;
#endif
}
operator TV5()
{
#ifdef _DEBUG
return _width==5 && _subset == 0 ? (T (*)[5]) _data : NULL;
#else
return (T (*)[5]) _data ;
#endif
}
operator TV128()
{
#ifdef _DEBUG
return _width==128 && _subset == 0 ? (T (*)[128]) _data : NULL;
#else
return (T (*)[128]) _data ;
#endif
}
int checkdim(int dim)
{
if(dim >= _width) expand(_width * 2, _height);
return _width;
}
T* getpt(int i)
{
return _matrix[i];
}
T* getpt(int i)const
{
return _matrix[i];
}
void fill(T v)
{
int i= _width*_height;
T* temp= _data;
for (; i>0; i--)*temp++= v;
}
void reorder(const int* index)
{
//
if(0 ==_width && 0 ==_height) return;
T* newdata, **newmatrix, *temp;
int i;
newmatrix = (T**) malloc(sizeof(T)*_width*_height+sizeof(T*)*_height);
temp = newdata = (T* ) (newmatrix+_height);
for( i =0 ; i < _height;i++)
{
newmatrix[i]=temp;
temp+=_width;
}
for( i = 0; i< _height; i++)
{
memcpy(newmatrix[i], _matrix[index[i]], _width*sizeof(T));
}
release();
_subset = 0;
_matrix = newmatrix;
_data = newdata;
}
};
//triangle matrix
template
class PointsT
{
protected:
T ** _matrix;
int _width;
private:
T** allocate(int width)
{
if( width >0 )
{
T** mat = (T**) malloc(sizeof(T*) * width);
for(int i = 0; i < _width; ++i)
{
mat[i] = ((T*) malloc(sizeof(T) * (width - i))) - i;
}
return mat;
}else
{
return NULL;
}
}
public:
PointsT()
{
_matrix = NULL;
_width = 0;
}
PointsT(int width, int height)
{
_width = width > height ? width :height;
_matrix = allocate(_width);
}
void release()
{
if(_matrix && _width > 0)
{
for(int i = 0; i < _width; ++i)
{
free(_matrix[i] + i);
}
free(_matrix);
_matrix = NULL;
_width = 0;
}
}
public:
void expand(int width, int height, T v)
{
expand(width > height ? width : height, v);
}
void expand(int width, T v)
{
//make sure size are
if(width <= _width ) return;
T** newmatrix = (T**) malloc(sizeof(T*)*width);
int i = 0, dw = width - _width;
if(dw <= _width)
{
for(; i < dw; ++i)
{
newmatrix[i] = ((T*) malloc(sizeof(T) * (width - i))) - i;
memcpy(newmatrix[i] + i, _matrix[i] + i, (_width - i) * sizeof(T));
//memset(newmatrix[i] + _width, 0, dw * sizeof(T));
for(int j = _width; j < width; ++j)newmatrix[i][j] = v;
}
for(; i < _width; ++i)
{
newmatrix[i] = _matrix[i - dw] - dw;
memcpy(newmatrix[i] + i, _matrix[i] + i, (_width - i) * sizeof(T));
//memset(newmatrix[i] + _width, 0, dw * sizeof(T));
for(int j = _width; j < width; ++j)newmatrix[i][j] = v;
}
}else
{
for(; i < _width; ++i)
{
newmatrix[i] = ((T*) malloc(sizeof(T) * (width - i))) - i;
memcpy(newmatrix[i] + i, _matrix[i] + i, (_width - i) * sizeof(T));
//memset(newmatrix[i] + _width, 0, dw * sizeof(T));
for(int j = _width; j < width; ++j)newmatrix[i][j] = v;
}
for(; i < dw; ++i)
{
newmatrix[i] = ((T*) malloc(sizeof(T) * (width - i))) - i;
//memset(newmatrix[i] + _width, 0, dw * sizeof(T));
for(int j = i; j < width; ++j)newmatrix[i][j] = v;
}
}
for(; i < width; ++i)
{
newmatrix[i] = _matrix[i - dw] - dw;
for(int j = i; j < width;++j) newmatrix[i][j] = v;
}
free(_matrix);
_matrix = newmatrix;
_width = width;
}
~PointsT()
{
release();
}
int invalid()
{
return _width == 0;
}
int width() const
{
return _width;
}
int ndim() const
{
return _width;
}
T* operator[](int i)
{
return _matrix[i];
}
T* operator[](int i) const
{
return _matrix[i];
}
operator T** const () const
{
return _matrix;
}
operator T** ()
{
return _matrix;
}
void fill(T v)
{
for(int i = 0; i < _width; ++i)
{
for(int j = i; j < _width; ++j)
{
_matrix[i][j] = v;
}
}
}
};
#endif
FeaturePoints.h
////////////////////////////////////////////////////////////////////////////
// File: FeaturePoints.h
// Author: Changchang Wu ([email protected])
// Description :
//
// Copyright (c) 2011 Changchang Wu ([email protected])
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// Version 3 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
////////////////////////////////////////////////////////////////////////////////
#if !defined(FEATURE_POINTS_H_INCLUDED)
#define FEATURE_POINTS_H_INCLUDED
#pragma once
#include
#include
#include
using std::vector;
using std::ifstream;
using std::ofstream;
using std::string;
#include "points.h"
///////////////////////////////////////////////////////////////////
//DESCRIPTOR TYPE
typedef unsigned char DTYPE;
//FEATURE LOCATION TYPE
typedef float LTYPE;
//#define DEBUG_DESCRIPTOR_BUG
////////////////////////////////////////////////////////////////////
////feature set with position info
//#define SIFT_LOCATION_NEW
class FeatureData
{
typedef struct sift_fileheader_v2
{
int szFeature;
int szVersion;
int npoint;
int nLocDim;
int nDesDim;
}sift_fileheader_v2;
typedef struct sift_fileheader_v1
{
int npoint;
int nLocDim;
int nDesDim;
}sift_fileheader_v1;
enum
{
// READ_BUFFER_SIZE = 0x100000,
SIFT_NAME= ('S'+ ('I'<<8)+('F'<<16)+('T'<<24)),
MSER_NAME= ('M'+ ('S'<<8)+('E'<<16)+('R'<<24)),
RECT_NAME= ('R'+ ('E'<<8)+('C'<<16)+('T'<<24)),
//SIFT_VERSION_2=('V'+('2'<<8)+('.'<<16)+('0'<<24)),
//SIFT_VERSION_3=('V'+('3'<<8)+('.'<<16)+('0'<<24)),
SIFT_VERSION_4=('V'+('4'<<8)+('.'<<16)+('0'<<24)),
SIFT_VERSION_5=('V'+('5'<<8)+('.'<<16)+('0'<<24)),
SIFT_EOF = (0xff+('E'<<8)+('O'<<16)+('F'<<24)),
};
// static char readBuf[READ_BUFFER_SIZE];
// static char sift_version[8];
static inline int IsValidFeatureName(int value)
{
return value == SIFT_NAME || value == MSER_NAME;
}
static inline int IsValidVersionName(int value)
{
return value == SIFT_VERSION_4 || value == SIFT_VERSION_5;
}
public:
class LocationData: public Points
{
public:
int _file_version;
public:
//each feature has x,y, z, size, orientation
//for rect feature, there is x, y, width, height
//for eclips feature, there is u,v,a,b,c +z
public:
void glPaint2D(int style);
LocationData(int d, int n):Points(d,n), _file_version(0){ };
LocationData( LocationData& sup, int index[], int n): Points(sup,index,n), _file_version(0){};
static void glPaintTexSIFT(const float * loc, float td[3]);
static void glPaintTexFrontalVIP(const float * loc, float td[3]);
static void glPaintSIFT(const LTYPE* loc);
static void glPaintSIFTSQ(LTYPE* loc);
static void glPaintELIPS(LTYPE* loc);
static void glPaintRECT(LTYPE* loc);
static void SetPaintColor(LTYPE sz);
};
class DescriptorData: public Points
{
//generally d is 128
public:
DescriptorData(DescriptorData& sup, int index[], int n): Points(sup,index,n){};
DescriptorData(int d, int n):Points(d,n){};
};
static float gSiftDisplayScale;
static int gSiftVisualStyle;
protected:
void ReadFeatureDataA(ifstream & is, int npt, int locDim, int desDim, int szFeatureName);
// the set of feature descriptors
DescriptorData * _desData;
// the set of feature locations
LocationData * _locData;
int _npoint;
int _updated;
public:
void SetUpdated(){_updated = 1;}
int GetUpdated(){return _updated;}
void CopyToFeatureData(FeatureData &fd);
int appendSIFTB(const char* szFile,int pos);
int validate() { return _locData && _desData; }
void ResizeFeatureData(int npoint, int locDim = 5, int desDim = 128)
{
if(npoint ==0)
{
if(_locData) delete _locData;
if(_desData) delete _desData;
_locData = NULL;
_desData = NULL;
}else
{
if(_locData)
_locData->resize(locDim, npoint);
else
_locData = new LocationData(locDim, npoint);
if(_desData)
_desData->resize(desDim, npoint);
else
_desData = new DescriptorData(desDim, npoint);
_locData->_file_version = SIFT_VERSION_4;
}
_npoint = npoint;
}
void operator = (FeatureData& ref) { ref.CopyToFeatureData(*this); }
void ResizeLocationData(int npoint, int locDim)
{
if(npoint ==0)
{
if(_locData) delete _locData;
if(_desData) delete _desData;
_locData = NULL;
_desData = NULL;
}else
{
if(_locData)
_locData->resize(locDim, npoint);
else
_locData = new LocationData(locDim, npoint);
if(_desData)
{
delete _desData;
_desData = NULL;
}
_locData->_file_version = SIFT_VERSION_4;
}
}
void ShrinkLocationData(int ndim = 2, int npoint = -1);
void ReleaseDescriptorData()
{
if(_desData)
{
delete _desData;
_desData = NULL;
}
}
public:
void SortSIFT();
void SaveSIFTBClip(const char* szFileName, int x1, int x2, int y1, int y2);
int ValidateIndex(int index[], int n);
void ConvertA2B(const char* szFile);
void SaveDescriptorFile(const char* szFeatureFile);
void SaveLocationFile(const char* szFeatureFile);
static int ReadRandomFeature(const char* path, double* pt, int nDim);
static int ExportSIFT(const char*featurefile, Points& points);
static int OpenSeekSIFT(const char* featurefile, int& npoint, int& ndim);
static int ExportSIFT(const char* featurefile, int fdx);
int ReadSIFTB(const char* szFile);
int ReadSIFTB_LOC(const char* szFile);
int ReadSIFTB_LOCT(const char* szFile, int fmax);
int ReadSIFTB_DES(const char* szFile, int fmax);
static int ReadSIFTB_DES(const char* szFile, unsigned char * buf, int nmax);
static int ReadSIFTA_DES(const char* szFile, unsigned char * buf, int nmax);
static int ReadSIFTB_LOC(const char* szFile, float * buf, int nmax );
static int ReadSIFTB(const char* szFile, float * locbuf, unsigned char * desbuf, int nmax);
void offsetFeatures(int ox, int oy);
void saveSIFTB2(const char* szFile);
void saveSIFTA(const char* szFile, const int nDesDim = 128);
void Overwrite_SIFTLOC(const char* szFile);
void CreateFeatureClip(FeatureData& src, int x1, int x2, int y1, int y2, int smax =100000 );
void SetFeatureClip(FeatureData&src, int nsf, int index[], int subset = 1);
void ReleaseFeatureData();
void FlipLocation(float imheight);
int ReadSIFTA(const char* szFile);
FeatureData();
virtual ~FeatureData();
DescriptorData& getDescriptorData() {return *_desData;}
LocationData& getLocationData()const {return *_locData;}
int IsValidFeatureData(){return getFeatureNum() > 0;}
int getFeatureNum(){return _npoint;}
int getLoadedFeatureNum(){return _locData? _locData->npoint(): 0;}
};
typedef FeatureData::LocationData FeatureLocationData;
typedef FeatureData::DescriptorData FeatureDescriptorData;
#endif // !defined(FEATURE_POINTS_H_INCLUDED)
MatchFile.h
////////////////////////////////////////////////////////////////////////////
// File: MatchFile.h
// Author: Changchang Wu ([email protected])
// Description :
//
// Copyright (c) 2011 Changchang Wu ([email protected])
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// Version 3 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef MATCH_FILE_H_INCLUDED
#define MATCH_FILE_H_INCLUDED
#pragma once
#include
#include
using std::vector;
using std::string;
#include "points.h"
#define MAX_PATH 260
////////////////////////////////////////////////////////////////////////
//+++To read the number of matches of iamge1 and image2------------------------------
//Ues member funcation -----MatchFile::GetMatchCount--------------------------------
//int NM; //number of putative matches
//int NF; //number of inlier matches
//MatchFile mat(image1_full_path); //image1
//if(mat.IsValid() && mat.GetMatchCount(image2_full_path, NM, NF)) {/*we have it*/}
////////////////////////////////////////////////////////////////////////
//+++To read back putative matches----------------------------------------------------
//use member function ----MatchFile::GetPMatch----------------------------------------
//int FC; //feature count of image2, input
//int NM; //number of putative matches, output
//Points matches;// feature index of putative matches, output
//MatchFile mat(image1_full_path); //image1's match database
//if(mat.IsValid() && mat.GetPMatch(image2_full_path, FC, NM, matches)) {/* we have it*/};
//////////////////////////////////////////////////////////////////////////
//+++To write puattive matching----------------------------------------------------------
//Use static function ----MatchFile::WritePMatch---------------------------------------
//You can call MatchFile::WritePMatch(
// char* image1_full_path_no_extension,
// char* image2_full_path_no_extension,
// int feature_count_of_image1,
// int feature_count_of_image2,
// int number_of_matches,
// Points& matches)
//
// You should call matches.resize(number_of_matches, 2) to form the matrix
// matches[0][] are the indices of image1
// matches[1][] are the indices of image2
struct TwoViewGeometry{
int NF, NE; // ni fundamental/essential matrix
int NH, NH2; // ni homogrphy
float F[3][3]; // fundamental matrix
float R[3][3]; // rotation
float T[3]; // translation
float F1, F2; //
float H[3][3]; //
float GE; // geometric error
float AA; // triangulation angle
TwoViewGeometry()
{
NF = NE = NH = NH2 = 0;
AA = F1 = F2 = 0.0;
GE = 100.0f;
}
//simple geometry
TwoViewGeometry(int Num, float FMat[3][3])
{
NF = Num;
NE = NH = NH2 = 0;
AA = F1 = F2 = 0.0;
GE = 100.0f;
memcpy(F, FMat, sizeof(F));
}
void ResetGeometry()
{
NF = NE = NH = NH2 = 0;
AA = F1 = F2 = 0.0;
GE = 100.0f;
}
void ExchangeView()
{
float RT[3][3] = { {R[0][0], R[1][0], R[2][0]},
{R[0][1], R[1][1], R[2][1]},
{R[0][2], R[1][2], R[2][2]}};
float TT[3] = { -R[0][0] * T[0] - R[1][0] * T[1] - R[2][0] * T[2],
-R[0][1] * T[0] - R[1][1] * T[1] - R[2][1] * T[2],
-R[0][2] * T[0] - R[1][2] * T[1] - R[2][2] * T[2]};
float FT[3][3] = { {F[0][0], F[1][0], F[2][0]},
{F[0][1], F[1][1], F[2][1]},
{F[0][2], F[1][2], F[2][2]} };
memcpy(F, FT, sizeof(F));
memcpy(R, RT, sizeof(R));
memcpy(T, TT, sizeof(T));
float TF = F1; F1 = F2; F2 = TF;
}
static void TransposeMatrix33(const float M[3][3], float MT[3][3])
{
MT[0][0] = M[0][0]; MT[0][1] = M[1][0]; MT[0][2] = M[2][0];
MT[1][0] = M[0][1]; MT[1][1] = M[1][1]; MT[1][2] = M[2][1];
MT[2][0] = M[0][2]; MT[2][1] = M[1][2]; MT[2][2] = M[2][2];
}
void SetGeometryR(const TwoViewGeometry& g)
{
NF = g.NF; NE = g.NE;
NH = g.NH; NH2 = g.NH2;
GE = g.GE; AA = g.AA;
F1 = g.F2; F2 = g.F1;
if(g.NF > 0)
{
TransposeMatrix33(g.F, F);
if(g.NE > 0)
{
/////////////////////////////////////////////////////////////
TransposeMatrix33(g.R, R);
//////////////////////////////////////////////////////////////////
T[0] = -R[0][0] * g.T[0] - R[0][1] * g.T[1] - R[0][2] * g.T[2];
T[1] = -R[1][0] * g.T[0] - R[1][1] * g.T[1] - R[1][2] * g.T[2];
T[2] = -R[2][0] * g.T[0] - R[2][1] * g.T[1] - R[2][2] * g.T[2];
}
}
if(g.NH2 > 0) TransposeMatrix33(g.H, H);
}
void SetGeometry(const TwoViewGeometry& g)
{
NF = g.NF; NE = g.NE;
NH = g.NH; NH2 = g.NH2;
GE = g.GE; AA = g.AA;
F1 = g.F1; F2 = g.F2;
if(g.NF > 0)
{
memcpy(F, g.F, sizeof(F));
if(g.NE > 0)
{
memcpy(R, g.R, sizeof(R));
T[0] = g.T[0]; T[1] = g.T[1]; T[2] = g.T[2];
}
}
if(g.NH2 > 0) memcpy(H, g.H, sizeof(H));
}
};
class NamedMutex;
class MatchFile
{
enum
{
MATCH_FILE_VERSION_3= ('M'+ ('T'<<8)+('0'<<16)+('3'<<24)),
MATCH_FILE_LATEST_VERSION = MATCH_FILE_VERSION_3,
MATCH_RECORD_V3 = ('M'+ ('R'<<8)+('V'<<16)+('3'<<24)),
};
struct MatchRecordV3{
int version;
TwoViewGeometry tvg;
int extra[7]; //reserved data for future change;
////////////////////////////////////////////////////
MatchRecordV3()
{
version = MatchFile::MATCH_RECORD_V3;
memset(extra, 0, sizeof(extra));
}
};
//image file can change..
//number of features can change.
//exif focal length can change.
struct FileHeader
{
int version;
int file_count;
int definition_size; //
int definition_buf; //
int feature_count; //this might change..
};
struct RecordLoc
{
int fcount;
int read_loc; // read location
int block_size; // block size
int trash_size; // trash size after
int extra_size; //
char file_name[4];
};
private:
static int multi_thread_mode;
static int file_title_mode;
static int delay_header_update;
static int record_reservation;
static int num_match_verification;
private:
NamedMutex* _mutex;
int _fid;
int _opened_for_write;
int _header_changed;
size_t _recordloc_unchanged;
int _matchfile_mode;
FileHeader _header;
char _filepath[MAX_PATH];
const char* _title;
vector _record_definition;
vector _match_records;
private:
void DeleteMatchRecord(const char* pattern = "extra");
void GetRecordList();
void MoveRecordToEnd(int i);
void GetMatchFilePath(char* match_path);
void GetMatchFolderPath(char* match_path);
int AddImageMatch(const char* relative_path);
int GetImageIndex(const char* relative_path);
void GetRelativePath(const char* image_match, char* relative_path);
void UpdateHeaderAndRecordLoc();
void ResetMatchFile();
public:
//print out messages
static int (*matchfile_printf)(const char* format,... ) ;
static void SetPrintFunction(int (*printf_func)(const char* format,... ));
static void GetRelativePath(const char* path1, const char* path2, char* relative_path);
static void SetMultiThreadMode(int multi_thread) { multi_thread_mode = multi_thread; }
static void SetFileTitleMode(int use_title) { file_title_mode = use_title; }
static void SetRecordReservation(int num) { record_reservation = (num > 1? num : 1); }
public:
MatchFile();
MatchFile(const char* image_path, int guided = 0);
~MatchFile();
int IsValid(){return _fid >0;}
int IsMatchFileOfImage(const char* fullpath, const char* title);
public:
int OpenMatchFile(const char* image_path, int write, int mode = 0);
int MakeWritable();
int HaveMatchRecord(const char* absolute_path);
void DeleteMatchFile();
void VerifyFeatureCount(int feature_count);
void CloseMatchFile();
void GetMatchedImageList(vector& paths);
void SaveSubsetMatch(vector& paths, vector& fc);
public:
//////////////////////////read matches
int GetMatchCount(const char* image_path, int&NM, int& NF);
int GetPMatch(const char* image_path, int FC, int& NM, Points& matches);
int GetIMatch(const char* image_path, int FC, TwoViewGeometry& tvg, Points&inliers);
int GetPMatchR(const char* image_path, int FC, int& NM, Points& matches);
int GetIMatchR(const char* image_path, int FC, TwoViewGeometry& tvg, Points&inliers);
public:
//////////////////////////////write matches
void WriteIMatch(const char* image_match, int reverse, int NM, TwoViewGeometry& tvg, Points&inliers);
void WritePMatch(const char* image_match, int FC, int NM, Points&matches, int reverse);
public:
////////////////////static functions
static void WriteIMatch(const char* image1, const char* image2, int NM, TwoViewGeometry& tvg, Points&inliers);
static void WriteIMatch(MatchFile* mat, const char* image1, const char* image2, int NM, TwoViewGeometry& tvg, Points&inliers);
static void WritePMatch(const char* image1, const char* image2, int fc1, int fc2, int NM, Points& matches);
static void WriteFMatch(const char* image1, const char* image2, int NF, int * index1, int * index, float F[3][3]);
///////////////////////////////////////
friend struct MatchFile::MatchRecordV3;
};
#endif
FeaturePoints.cpp
////////////////////////////////////////////////////////////////////////////
// File: FeaturePoints.cpp
// Author: Changchang Wu ([email protected])
// Description :
//
// Copyright (c) 2011 Changchang Wu ([email protected])
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// Version 3 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
////////////////////////////////////////////////////////////////////////////////
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#include "FeaturePoints.h"
float FeatureData::gSiftDisplayScale = 6.0f;
int FeatureData::gSiftVisualStyle = 0;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
FeatureData::FeatureData()
{
_desData = NULL;
_locData = NULL;
_updated = 0;
_npoint = 0;
}
FeatureData::~FeatureData()
{
if (_desData) delete _desData;
if (_locData) delete _locData;
}
int FeatureData::ReadSIFTA(const char* szFile)
{
int npt=0, nd=0;
ifstream is(szFile);
if(!is.is_open())return 0;
is>> npt >> nd;
if (npt <= 0 || nd <= 0 )
{
_npoint = 0;
is.close();
return 0;
}else
{
ReadFeatureDataA(is, npt, 4, nd, SIFT_NAME);
is.close();
SetUpdated();
return 1;
}
}
void FeatureData::ReadFeatureDataA(ifstream &is, int npt, int locDim, int desDim, int szFeatureName)
{
int i, j;
///////////////////////////////////////
_npoint = npt;
_locData = new LocationData( locDim +1, npt);//one more column for z
_desData = new DescriptorData(desDim, npt);
LTYPE * pLoc = _locData->data();
DTYPE * pDes = _desData->data();
////////////////////////////////////////////////
for ( i = 0 ; i< npt; i++)
{
if( locDim ==4)
{
is>> *(pLoc+1); //x
is>> *pLoc; //
}else
{
is>> *pLoc; //x
is>> *(pLoc+1); //y
}
//SIFT_LOCATION_NEW
pLoc[0] += 0.5f;
pLoc[1] += 0.5f;
pLoc[2] = 0;
pLoc+=3;
if (locDim ==4)
{
is>> pLoc[0];
is>> pLoc[1];
pLoc[1] = - pLoc[1];//flip the angle
pLoc+=2;
}else
{
is>> *pLoc++;
is>> *pLoc++;
is>> *pLoc++;
}
for ( j = 0 ; j< desDim; j++)
{
unsigned int value;
is >> value;
*pDes++ = value;
}
}
}
void FeatureData::CopyToFeatureData(FeatureData &fd)
{
if(getFeatureNum()>0)
{
fd.ResizeFeatureData(getFeatureNum(), getLocationData().ndim(), 128);
fd.getLocationData() = getLocationData();
fd.getDescriptorData() = getDescriptorData();
//memcpy(fd.getLocationData().data(), getLocationData().data(), getLocationData().bsize());
//memcpy(fd.getDescriptorData().data(), getDescriptorData().data(), getDescriptorData().bsize());
}
}
void FeatureData::FlipLocation(float imheight)
{
if(_locData == NULL) return;
LTYPE * feature;
if(_locData->ndim()==5)
{
for (int i = 0 ; i< _locData->npoint();i++)
{
feature = _locData->getpt(i);
feature[1] = imheight - feature[1];
}
}else if(_locData->ndim()==6)
{
for (int i = 0 ; i< _locData->npoint();i++)
{
feature = _locData->getpt(i);
// SIFT_LOCATION_NEW
feature[1] = imheight - feature[1];
feature[4] = - feature[4];
}
}
}
void FeatureData::ReleaseFeatureData()
{
if (_locData ) delete _locData;
if (_desData ) delete _desData;
_locData = NULL;
_desData = NULL;
_npoint = 0;
}
void FeatureData::SetFeatureClip(FeatureData&src, int nsf, int index[], int subset)
{
ReleaseFeatureData();
if(subset)
{
if(src._locData) _locData = new LocationData(src.getLocationData(), index, nsf);
if(src._desData) _desData = new DescriptorData(src.getDescriptorData(), index, nsf);
}else
{
FeatureData fd2;
fd2.SetFeatureClip(src, nsf, index, 1);
ResizeFeatureData(nsf, src._locData->width(), src._desData->width());
getLocationData() = fd2.getLocationData();
getDescriptorData() = fd2.getDescriptorData();
}
SetUpdated();
}
void FeatureData::offsetFeatures(int ox, int oy)
{
if(_locData == NULL) return;
LTYPE dox = (LTYPE) ox, doy = (LTYPE) oy;
LTYPE * feature;
for (int i = 0 ; i< _locData->npoint();i++)
{
feature = _locData->getpt(i);
feature[0] = feature[0] + dox ;
feature[1] = feature[1] + doy;
}
}
void FeatureData:: saveSIFTA(const char* szFile, const int nDesDim)
{
if(_locData == NULL) return ;
int n = _locData->npoint();
if(n <=0) return;
ofstream out(szFile);
out << n << " " << nDesDim <<"\n";
//
for(int i = 0; i < n; i++)
{
LTYPE * loc = _locData->getpt(i);
unsigned char * des = _desData->getpt(i);
out << loc[1] << " " << loc[0] << " " << loc[3] << " " << loc[4] << endl;
for(int k = 0; k < nDesDim; k ++)
{
out<< ((unsigned int)des[k])<<" ";
if ( (k+1)%20 == 0 ) out<npoint();
sfh.nLocDim = _locData->ndim();
sfh.nDesDim = _desData->ndim();
_write(fd, &sfh, sizeof(sfh));
////
LTYPE * lp;
DTYPE * dp;
unsigned char* fph;
float *fp;
unsigned char * ucp;
int Max, MemNum;
lp = _locData->data();
MemNum = sfh.nDesDim * sfh.npoint;
Max = sfh.npoint*sfh.nLocDim;
fph= new unsigned char[MemNum]; //MemCollect::Malloc(MemNum);
fp = (float*) fph;
for( i = 0; i < sfh.npoint; i++)
{
lp = (*_locData)[i];
for(j=0;jdata();
Max = sfh.npoint*sfh.nDesDim;
ucp = (unsigned char*) fph;
for( i = 0; i < sfh.npoint; i++)
{
dp = (*_desData)[i];
for(j=0;j0 && nLocDim >0 && nDesDim==128)
{
ResizeFeatureData(npoint,nLocDim,nDesDim);
_read(fd,_locData->data(), nLocDim *npoint*sizeof(float));
_read(fd,_desData->data(), nDesDim*npoint*sizeof(unsigned char));
_read(fd,&sift_eof,sizeof(int));
//assert(sift_eof == SIFT_EOF);
_close(fd);
_locData->_file_version = version;
SetUpdated();
#ifdef DEBUG_DESCRIPTOR_BUG
unsigned char * pb = desData->data();
int bad_descriptor_count = 0;
for(int i = 0; i < npoint; ++i, pb+=128)
{
int good_descriptor = 0;
for(int j = 0; j < 128; ++j)
{
if(pb[j]!=45)
{
good_descriptor = 1;
break;
}
}
if(good_descriptor==0) bad_descriptor_count++;
}
if(bad_descriptor_count) printf("xxxxxx %d bad descriptor xxxxxx\r\n", bad_descriptor_count);
#endif
}else
{
ResizeFeatureData(0, 0, 0);
_close(fd);
return 0;
}
return 1;
}else
{
_close(fd);
return 0;
}
}
int FeatureData::ReadSIFTB_DES(const char* szFile, int fmax)
{
sift_fileheader_v2 sfh;
int fd = _open(szFile, _O_BINARY|_O_RDONLY,_S_IREAD);
if (fd<0) return 0;
///
_read(fd, &sfh, sizeof(sfh));
int npoint = fmax > 0 ? min(sfh.npoint, fmax) : sfh.npoint;
if(_desData)
_desData->resize(sfh.nDesDim, npoint);
else
_desData = new DescriptorData(sfh.nDesDim, npoint);
_lseek(fd, sfh.nLocDim *sfh.npoint*sizeof(float), SEEK_CUR);
_read(fd,_desData->data(), sfh.nDesDim*npoint*sizeof(unsigned char));
_close(fd);
return 1;
}
int FeatureData::ReadSIFTB_LOC(const char* szFile, float * buf, int nmax )
{
sift_fileheader_v2 sfh;
int fd = _open(szFile, _O_BINARY|_O_RDONLY,_S_IREAD);
if (fd<0) return 0;
///
_read(fd, &sfh, sizeof(sfh));
nmax = min(nmax, sfh.npoint);
_read(fd, buf, sfh.nLocDim *sfh.npoint*sizeof(float));
_close(fd);
return nmax;
}
int FeatureData::ReadSIFTB_DES(const char* szFile, unsigned char * buf, int nmax )
{
sift_fileheader_v2 sfh;
int fd = _open(szFile, _O_BINARY|_O_RDONLY,_S_IREAD);
if (fd<0) return 0;
///
_read(fd, &sfh, sizeof(sfh));
nmax = min(nmax, sfh.npoint);
_lseek(fd, sfh.nLocDim *sfh.npoint*sizeof(float), SEEK_CUR);
_read(fd, buf, sfh.nDesDim* nmax*sizeof(unsigned char));
_close(fd);
return nmax;
}
int FeatureData::ReadSIFTA_DES(const char* szFile, unsigned char * buf, int nmax )
{
FeatureData fd;
fd.ReadSIFTA(szFile);
if(fd.getLocationData().getpt(0)[3] < fd.getLocationData().getpt(fd.getFeatureNum() -1)[3])
{
//sort
fd.SortSIFT();
}
nmax = min(nmax, fd.getFeatureNum());
if(nmax > 0)
{
memcpy(buf, fd.getDescriptorData().data(), nmax * 128);
}
return nmax;
}
int FeatureData::ReadSIFTB(const char* szFile, float * locbuf, unsigned char * desbuf, int nmax)
{
sift_fileheader_v2 sfh;
int fd = _open(szFile, _O_BINARY|_O_RDONLY,_S_IREAD);
if (fd<0) return 0;
///
_read(fd, &sfh, sizeof(sfh));
nmax = min(nmax, sfh.npoint);
_read(fd, locbuf, sfh.nLocDim *sfh.npoint*sizeof(float));
_read(fd, desbuf, sfh.nDesDim* nmax*sizeof(unsigned char));
_close(fd);
return nmax;
}
int FeatureData::ReadSIFTB_LOC(const char* szFile)
{
sift_fileheader_v2 sfh;
int fd = _open(szFile, _O_BINARY|_O_RDONLY,_S_IREAD);
if (fd<0) return 0;
///
_read(fd, &sfh, sizeof(sfh));
if(IsValidFeatureName(sfh.szFeature) && IsValidVersionName(sfh.szVersion))
{
//version 2 file
if(sfh.npoint>0 && sfh.nLocDim >0 && sfh.nDesDim==128)
{
_npoint = sfh.npoint;
ResizeLocationData(sfh.npoint,sfh.nLocDim);
if(_locData->data())
{
_read(fd,_locData->data(), sfh.nLocDim *sfh.npoint*sizeof(float));
_locData->_file_version = sfh.szVersion;
}else
{
printf("ERROR: ReadSIFTB_LOC allocatoin faled\r\n");
}
_close(fd);
SetUpdated();
}else
{
ResizeFeatureData(0, 0, 0);
_close(fd);
return 0;
}
return 1;
}else
{
_npoint = 0;
_close(fd);
return 0;
}
}
int FeatureData::appendSIFTB(const char* szFile, int pos)
{
int npoint, nLocDim, nDesDim;
int fd = _open(szFile, _O_BINARY|_O_RDONLY,_S_IREAD);
if (fd<0) return pos;
///
///
_read(fd, &npoint, sizeof(int));
_read(fd, &nLocDim, sizeof(int));
if(npoint == SIFT_NAME && IsValidVersionName(nLocDim))
{
_read(fd, &npoint, sizeof(int));
_read(fd, &nLocDim, sizeof(int));
//assert(nLocDim == 5);
_read(fd, &nDesDim, sizeof(int)); //assert(nDesDim == 128);
_read(fd,(float*)_locData->data()+ pos*nLocDim, nLocDim*npoint*sizeof(float));
_read(fd,(unsigned char*)_desData->data()+ pos*nDesDim, nDesDim*npoint*sizeof(unsigned char));
}
_close(fd);
return pos + npoint;
}
int FeatureData::OpenSeekSIFT(const char *featurefile,int&npoint, int&ndim)
{
sift_fileheader_v2 sfh={SIFT_NAME,SIFT_VERSION_4,0,0,0};
int fd = _open(featurefile, _O_BINARY|_O_RDONLY);
if (fd<0) return 0;
///
_read(fd, &sfh, sizeof(sfh));
if( sfh.szFeature != SIFT_NAME || !IsValidVersionName(sfh.szVersion)||
sfh.npoint <=0 || sfh.nLocDim<=0 || sfh.nDesDim !=128)
{
// incorrect version
_close(fd);
return 0;
}else
{
_lseek(fd, sfh.nLocDim*sfh.npoint*sizeof(float), SEEK_CUR);
npoint = sfh.npoint;
ndim = sfh.nDesDim;
return fd;
}
}
void FeatureData::SaveLocationFile(const char* szFeatureFile)
{
int nf = _locData->npoint();
if(nf ==0) return;
// struct _stat buf;
// if(_stat(szFeatureFile, &buf)!=-1) return; //already saved
vector loc(nf*2);
float * p = &loc[0];
int fid = _open(szFeatureFile, _O_CREAT|_O_BINARY|_O_WRONLY|_O_TRUNC,_S_IREAD | _S_IWRITE);
if(fid ==-1) return;
for(int i = 0; i < nf ; i++)
{
*p++ =(float) _locData->getpt(i)[0];
*p++ =(float) _locData->getpt(i)[1];
}
_write(fid, &loc[0], loc.size()*sizeof(float));
_close(fid);
}
void FeatureData::SaveDescriptorFile(const char* szFeatureFile)
{
int fid = _open(szFeatureFile, _O_CREAT|_O_BINARY|_O_WRONLY|_O_TRUNC,_S_IREAD | _S_IWRITE);
int nf = _desData->npoint();
DTYPE * dp = _desData->data();
_write(fid, dp, nf*128*sizeof(unsigned char));
_close(fid);
}
void FeatureData::ConvertA2B(const char* szFile)
{
//LET'S AUTOMATICALLY GENERATE A BINARY VRSION
//make sure it is the same format of sift
double normal = 0;
DTYPE* d = _desData->data();
for(int i = 0; i < 128; i++) normal += d[i] * d[i];
normal = sqrt(normal);
if ( normal < 400)
{
//__asm int 03h;
for(int i = 0; i < _desData->npoint(); i++)
{
d = _desData->getpt(i);
normal = 0;
for(int j = 0; j < 128; j ++)
{
normal += d[j]*d[j];
}
normal = 512.0/sqrt(normal);
for(int k = 0; k < 128; k++)
{
d[k] = (DTYPE) floor (normal * d[k] +0.5);
}
}
for(int j = 0; j < _locData->npoint(); j++)
{
LTYPE* l= _locData->getpt(j);
LTYPE temp = l[0];
l[0] = l[1];
l[1] = temp;
}
}
int len = strlen(szFile);
if(len>10 && strcmp(szFile + len -10, ".sift.sift")==0)
{
char szNewFile[260];
strcpy(szNewFile, szFile);
szNewFile[len-5] = 0;
saveSIFTB2(szNewFile);
remove(szFile);
}else if(len >5 && strcmp(szFile + len - 5, ".sift") ==0)
{
saveSIFTB2(szFile);
}
}
int FeatureData::ValidateIndex(int index[], int n)
{
int num = getFeatureNum();
for (int i = 0 ; i < n ; i ++)
{
if( index[i]>= num || index[i] < 0)
{
return 0;
}
}
return 1;
}
void FeatureData::SortSIFT()
{
int i, j, nf = getFeatureNum();
if(nf ==0 || _locData == NULL || _desData == NULL) return;
LTYPE * loc = _locData->data();
DTYPE * des = _desData->data();
vector orderv(nf);
vector sizes(nf);
int* order = &orderv[0];
LTYPE* size = &sizes[0];
//bubble sort
for( i = 0; i < nf; i++) order[i] = nf - i - 1;
for( i = 0; i < nf; i++) size[i] = loc[5 * (nf - i -1) + 3];
for( i =0; i < nf; i ++)
{
int swaped = 0;
for( j = nf -1 ; j > i; j--)
{
if(size[j] > size[j-1])
{
//size
LTYPE dtemp = size[j];
size[j] = size[j-1];
size[j-1] = dtemp;
//order
int itemp = order[j];
order[j] = order[j-1];
order[j-1] = itemp;
swaped = 1;
}
}
if(!swaped) break;
}
_locData->reorder(order);
_desData->reorder(order);
//printf("\r\n");
}
void FeatureData::ShrinkLocationData(int ndim, int npoint)
{
if(_locData) _locData->shrink(ndim,
npoint < 0? _locData->npoint() : min(npoint, _locData->npoint()));
}
MatchFile.cpp
////////////////////////////////////////////////////////////////////////////
// File: MatchFile.cpp
// Author: Changchang Wu ([email protected])
// Description :
//
// Copyright (c) 2011 Changchang Wu ([email protected])
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// Version 3 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
////////////////////////////////////////////////////////////////////////////////
#include "stdio.h"
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#include "MatchFile.h"
//////////////////////////////////////
int MatchFile::multi_thread_mode = 0;
int MatchFile::file_title_mode = 0;
int MatchFile::num_match_verification = 1;
int MatchFile::delay_header_update = 0;
int MatchFile::record_reservation = 20;
//function for printing out messages.
int (*MatchFile::matchfile_printf)(const char* format,... ) = ::printf;
#define printf matchfile_printf
#ifdef _WIN64
#define _lseek _lseeki64
#endif
#ifdef WIN32
#define PATH_SLASH '\\'
#define PATH_SLASH_X '/'
#define PATH_PARENT "..\\"
#else
#define PATH_SLASH '/'
#define PATH_SLASH_X '\\'
#define PATH_PARENT "../"
#endif
void MatchFile::SetPrintFunction(int (*printf_func)(const char* format,... ))
{
matchfile_printf = printf_func;
}
MatchFile::MatchFile()
{
_fid = 0;
_header.definition_size = 0;
_header.file_count = 0;
_header.feature_count = 0;
_recordloc_unchanged = 0;
_header_changed = 0;
_opened_for_write = 0;
_mutex = NULL;
_matchfile_mode= 0;
_title = _filepath;
}
MatchFile::~MatchFile()
{
CloseMatchFile();
}
MatchFile::MatchFile(const char* image_path, int mode)
{
_fid = 0;
_mutex = NULL;
_header.definition_size = 0;
_header.file_count = 0;
_header.feature_count = 0;
_recordloc_unchanged = 0;
_header_changed = 0;
OpenMatchFile(image_path, 0, mode);
}
int MatchFile::IsMatchFileOfImage(const char* fullpath, const char* title)
{
if(file_title_mode && title) return strcmp(_title, title) == 0;
else return strcmp(_filepath, fullpath) == 0;
}
void MatchFile::GetMatchFilePath(char* match_path)
{
strcpy(match_path, _filepath);
if(_matchfile_mode == 0) strcat(match_path, ".mat");
else if(_matchfile_mode == 1)strcat(match_path, ".gmat");
else strcat(match_path, ".xmat");
//////////////////////
_title = strrchr(_filepath, PATH_SLASH);
if(_title == NULL) _title = _filepath;
else _title++;
}
void MatchFile::GetMatchFolderPath(char* match_path)
{
strcpy(match_path, _filepath);
char* p = strrchr(match_path, PATH_SLASH); p[1] = 0;
}
int MatchFile::MakeWritable()
{
char match_path[MAX_PATH];
//already opened for write
if(_fid <=0) return 0;
if(_opened_for_write) return 1;
//////////////////////////////
GetMatchFilePath(match_path);
_close(_fid);
_fid = _open(match_path, _O_BINARY|_O_CREAT|_O_RDWR, _S_IWRITE|_S_IREAD);
if(_fid > 0)
{
_opened_for_write = 1;
return 1;
}else
{
_opened_for_write = 0;
return 0;
}
}
void MatchFile::VerifyFeatureCount(int feature_count)
{
if(_fid <= 0 ) return ;
if(_header.feature_count <= 0)
{
//update the feature count
if(feature_count > 0)
{
_header.feature_count = feature_count;
if(MakeWritable())
{
_lseek(_fid, 0, SEEK_SET);
_write(_fid, &_header, sizeof(_header));
//printf("Update feature count [%d]!\r\n", feature_count);
}
}
}else if(feature_count > 0 && _header.feature_count != feature_count)
{
//destroy all match record.
DeleteMatchFile();
printf("Delete match record: feature changed!\r\n");
}
}
void MatchFile::DeleteMatchRecord(const char* pattern)
{
if(_fid <= 0) return;
int changed = 0;
for(int i = 0; i < _match_records.size(); ++i)
{
if(strstr(_match_records[i]->file_name, pattern))
{
int NM;
RecordLoc * loc = _match_records[i];
_lseek(_fid, loc->read_loc, SEEK_SET);
_read(_fid, &NM, sizeof(int));
////////////////////////////////
if(NM == 0) continue;
MakeWritable();
_lseek(_fid, loc->read_loc, SEEK_SET);
NM = 0; _write(_fid, &NM, sizeof(int));
changed = 1;
}
}
}
void MatchFile::DeleteMatchFile()
{
char match_path[MAX_PATH];
GetMatchFilePath(match_path);
CloseMatchFile();
remove(match_path);
}
int MatchFile::OpenMatchFile(const char* imagepath, int write, int mode)
{
char match_path[MAX_PATH];
CloseMatchFile();
//
_matchfile_mode = mode;
///////////////
strcpy(_filepath, imagepath);
GetMatchFilePath(match_path);
if(!write)
_fid = _open(match_path, _O_BINARY|_O_RDONLY);
else
_fid = _open(match_path, _O_BINARY|_O_CREAT|_O_RDWR, _S_IWRITE|_S_IREAD);
if(_fid > 0)
{
//read file _header
int readsz = _read(_fid, (char*) (&_header), sizeof(_header));
_opened_for_write = write;
if( sizeof(_header) == readsz && _header.definition_size >0 &&
_header.definition_buf >= _header.definition_size &&
_header.version == MATCH_FILE_VERSION_3)
{
assert(_header.file_count>=0);
_record_definition.resize(_header.definition_buf, 0);
_read(_fid, (char*) &_record_definition[0], _header.definition_size);
GetRecordList();
_header_changed = 0;
_recordloc_unchanged = _header.definition_size;
}else if (readsz > 0)
{
printf("Unsupported MatchFile [%s]\r\n", _filepath );
ResetMatchFile();
if(write)UpdateHeaderAndRecordLoc();
}
return 1;
} else
{
_filepath[0] = 0;
return 0;
}
}
void MatchFile::GetRecordList()
{
char * p = &_record_definition[0];
_match_records.resize(_header.file_count);
for(int i = 0; i < _match_records.size(); ++i)
{
RecordLoc* rp = (RecordLoc*) p;
_match_records[i] = rp;
if(rp->read_loc <= 0 || rp->block_size == 0 ||
rp->extra_size > MAX_PATH ||
(rp->fcount > 1000000 || rp->fcount < 0))
{
_match_records.resize(i);
_header.file_count = i;
_header.definition_size = (p - &_record_definition[0]);
break;
}else
{
p += sizeof(RecordLoc) + _match_records[i]->extra_size;
//convert file name for different operation system
for(char* c = rp->file_name; *c; ++c) {if (*c == PATH_SLASH_X) *c = PATH_SLASH; }
}
}
}
void MatchFile::GetMatchedImageList(vector& paths)
{
char match_path[MAX_PATH];
GetMatchFolderPath(match_path);
string folder = match_path;
paths.resize(0);
for(int i = 0; i < _match_records.size(); ++i)
{
paths.push_back(folder + _match_records[i]->file_name);
}
}
void MatchFile::SaveSubsetMatch(vector& paths, vector&fc)
{
MatchFile sub;
sub.OpenMatchFile(_filepath, 1, 2);
sub.ResetMatchFile();
////
int NM;
Points matches;
TwoViewGeometry tvg;
Points inliers;
/////////////////////////////
for(int i = 0; i < paths.size(); ++i)
{
if(GetPMatch(paths[i].c_str(), fc[i], NM, matches))
{
sub.WritePMatch(paths[i].c_str(), fc[i], NM, matches, 0);
if(GetIMatch(paths[i].c_str(), fc[i], tvg, inliers))
{
sub.WriteIMatch(paths[i].c_str(), 0, NM, tvg, inliers);
}
}
}
}
int MatchFile::HaveMatchRecord(const char* absolute_path)
{
char relative_path[MAX_PATH];
GetRelativePath(absolute_path, relative_path);
return GetImageIndex(relative_path) >= 0;
}
int MatchFile::GetImageIndex(const char* relative_path)
{
if(file_title_mode)
{
const char * ps = strrchr(relative_path, PATH_SLASH);
ps = (ps == NULL? relative_path : ps + 1);
for(int i = 0; i < _match_records.size(); i++)
{
RecordLoc* loc = _match_records[i];
const char * p = strrchr(loc->file_name, PATH_SLASH);
p = (p == NULL ) ? loc->file_name : p + 1;
if(strcmp(p, ps) == 0) return i;
}
}else
{
for(int i = 0; i < _match_records.size(); i++)
{
if(strcmp(_match_records[i]->file_name, relative_path) == 0) return i;
}
}
return -1;
}
void MatchFile::GetRelativePath(const char* path1, const char* path2, char* relative_path)
{
int i = 0;
while(path2[i] == path1[i] && path2[i] && path1[i]) i++;
while(i > 0 && path1[i] != PATH_SLASH) i--;
if( i == 0)
{
strcpy(relative_path, path2);
}else
{
relative_path[0] = 0;
const char* p = path1 + i + 1;
char * rp = relative_path;
int rc1 = 0, rc2 = 0;
while(*p)
{
if(p[0] == PATH_SLASH && p[1] != PATH_SLASH)
{
strcpy(rp, PATH_PARENT);
rp += 3;
rc1 ++;
}
p++;
}
p = path2 + i + 1;
while(*p)
{
if(p[0] == PATH_SLASH && p[1] != PATH_SLASH) rc2 ++;
p++;
}
if(rc1 <=1 || rc2 <=1) strcpy(rp, path2 + i + 1);
else strcpy(relative_path, path2);
}
}
inline void MatchFile::GetRelativePath(const char* image_match, char* relative_path)
{
if(file_title_mode)
{
const char* pslash = strrchr(image_match, PATH_SLASH);
if(pslash) strcpy(relative_path, pslash + 1);
else strcpy(relative_path, image_match);
}else
{
GetRelativePath(_filepath, image_match, relative_path);
}
}
void MatchFile::MoveRecordToEnd(int i)
{
if(i >= _header.file_count - 1 || i < 0 || _header.file_count < 2) return;
char* p0 = (char*) _match_records[0];
char* p1 = (char*) _match_records[i];
char* p2 = (char*) _match_records[i + 1];
size_t loc1 = p1 - p0;
size_t loc2 = p2 - p0;
int len = loc2 - loc1;
vector temp;
temp.insert(temp.begin(), p1, p2);
_record_definition.erase(_record_definition.begin() + loc1, _record_definition.begin() + loc2);
//_record_definition.insert(_record_definition.end(), temp.begin(), temp.begin() + len);
_record_definition.insert(_record_definition.begin() + _header.definition_size - len, temp.begin(), temp.begin() + len);
_recordloc_unchanged = min(_recordloc_unchanged, loc1);
GetRecordList();
if(i == 0)
{
_header.definition_buf += len;
_header_changed = 1;
}else
{
_match_records[i -1]->trash_size += len;
}
//
_match_records[_header.file_count -1]->read_loc =
_match_records[_header.file_count - 2]->read_loc + _match_records[_header.file_count - 2]->block_size;
printf("MoveRecordToEnd [%s]\r\n", _filepath );
}
int MatchFile::AddImageMatch(const char* relative_path)
{
//see if the name buffer has enough space..
int slen = (strlen(relative_path) / 4 + 1) * 4;
int elen = slen - 4;
int rlen = elen + sizeof(RecordLoc);
//////////////////
_header_changed = 1;
//////////////
if(_header.file_count == 0)
{
_header.version = MATCH_FILE_LATEST_VERSION;
_header.file_count = 1;
_header.definition_buf = max(20, record_reservation) * (MAX_PATH + sizeof(RecordLoc));
_record_definition.resize(_header.definition_buf, 0);
_header.definition_size = rlen;
RecordLoc* loc = (RecordLoc*) (&_record_definition[0]);
_match_records.resize(1);
_match_records[0] = loc;
strcpy(loc->file_name, relative_path);
loc->extra_size = elen;
loc->trash_size = 0;
loc->block_size = 0;
loc->read_loc = sizeof(FileHeader) + _header.definition_buf;
// should write the _header now?
return 0;
}
else if(_header.definition_size + rlen < _header.definition_buf)
{
RecordLoc* rec = (RecordLoc*) (&_record_definition[_header.definition_size]);
rec->block_size = 0;
rec->extra_size = elen;
rec->read_loc = _match_records.back()->read_loc + _match_records.back()->block_size;
strcpy(rec->file_name, relative_path);
_match_records.push_back(rec);
_header.definition_size += rlen ;
_header.file_count++;
return _header.file_count -1;
}else
{
//size_t szr = max(((int) (_match_records.size() + 1)), record_reservation) * (MAX_PATH + sizeof(RecordLoc));
int extra_needed = rlen + _header.definition_buf;
int match_move_needed = 0;
int extra_space = 0;
// move the match data
while(extra_space < extra_needed)
{
RecordLoc* loc = _match_records[match_move_needed];
extra_space+= (loc->block_size + loc->trash_size);
match_move_needed++;
}
assert(match_move_needed > 0);
//read match data that needs to move
vector read_buffer(extra_space);
char* pbuf = &read_buffer[0];
_lseek(_fid, _match_records[0]->read_loc, SEEK_SET);
_read(_fid, &read_buffer[0], extra_space);
//write match data to the end of file
int match_write_location = _match_records.back()->read_loc + _match_records.back()->block_size;
_lseek(_fid, match_write_location, SEEK_SET);
for(int i = 0; i < match_move_needed; i++)
{
RecordLoc* loc = _match_records[i];
_write(_fid, pbuf, loc->block_size);
pbuf += (loc->block_size + loc->trash_size);
loc->read_loc = match_write_location;
match_write_location += loc->block_size;
loc->trash_size = 0;
}
//organize file names
int definition_move = ((char*)_match_records[match_move_needed]) - &_record_definition[0];
if(match_move_needed < _header.file_count)
{
//reorganize strings..move several string to the end
vector temp = _record_definition;
std::copy(temp.begin() + definition_move, temp.begin() + _header.definition_size, _record_definition.begin() );
std::copy(temp.begin(), temp.begin() + definition_move, _record_definition.begin() + _header.definition_size - definition_move);
}
_header.definition_buf = _header.definition_buf * 2 + rlen;
_record_definition.resize(_header.definition_buf, 0);
GetRecordList();
RecordLoc* rec = (RecordLoc*) (&_record_definition[_header.definition_size]);
rec->read_loc = match_write_location;
rec->trash_size = 0;
rec->block_size = 0;
rec->extra_size = elen;
_match_records.push_back(rec);
strcpy(rec->file_name, relative_path);
//write all previous data to file
_lseek(_fid, sizeof(_header), SEEK_SET);
_write(_fid, &_record_definition[0], _header.definition_size);
////
_header.definition_size += rlen;
_header.file_count++;
_recordloc_unchanged = 0;
return _header.file_count -1;
}
}
void MatchFile::ResetMatchFile()
{
_header.file_count = 0;
_header.definition_size = 0;
_header.definition_buf = 0;
_header.version = MATCH_FILE_LATEST_VERSION;
_match_records.resize(0);
_record_definition.resize(0);
_recordloc_unchanged = 0;
_header_changed = 1;
}
void MatchFile::CloseMatchFile()
{
if(_fid > 0)
{
if(_opened_for_write && delay_header_update) UpdateHeaderAndRecordLoc();
ResetMatchFile();
_close(_fid);
_fid = 0;
_opened_for_write = 0;
_matchfile_mode = 0;
}
}
void MatchFile::WriteFMatch(const char* image1, const char* image2,
int NF, int* index1, int* index2, float F[3][3])
{
if(index1 == NULL || index2 == NULL) return;
int* indices [2] = {index1, index2};
Points inliers(indices, NF, 2);
TwoViewGeometry tvg(NF, F);
WriteIMatch(image1, image2, 0, tvg, inliers);
}
void MatchFile::WriteIMatch(MatchFile* mat, const char* image1, const char* image2,
int NM, TwoViewGeometry& tvg, Points&inliers)
{
if(mat == NULL || ! mat->IsValid())
{
WriteIMatch(image1, image2, NM, tvg, inliers);
}else if(_stricmp(mat->_filepath, image1) ==0)
{
if(mat->MakeWritable())
{
mat->WriteIMatch(image2, 0, NM, tvg, inliers);
}
MatchFile file2;
if(file2.OpenMatchFile(image2, 1))
{
file2.WriteIMatch(image1, 1, NM, tvg, inliers);
}
}else if(_stricmp(mat->_filepath, image2) == 0)
{
if(mat->MakeWritable())
{
mat->WriteIMatch(image1, 1, NM, tvg, inliers);
}
MatchFile file1;
if(file1.OpenMatchFile(image1, 1))
{
file1.WriteIMatch(image2, 0, NM, tvg, inliers);
}
}
}
void MatchFile::WriteIMatch(const char* image1, const char* image2, int NM, TwoViewGeometry& tvg, Points&inliers)
{
MatchFile file1, file2;
if(file1.OpenMatchFile(image1, 1))
{
file1.WriteIMatch(image2, 0, NM, tvg, inliers);
file1.CloseMatchFile();
}
if(file2.OpenMatchFile(image2, 1))
{
file2.WriteIMatch(image1, 1, NM, tvg, inliers);
file2.CloseMatchFile();
}
}
void MatchFile::WriteIMatch(const char* image_match, int reverse, int NM,
TwoViewGeometry& tvg, Points&inliers)
{
int index, fnm, szmin;
char relative_path[MAX_PATH];
if(image_match == NULL || image_match[0] == 0) return;
GetRelativePath(image_match, relative_path);
index = GetImageIndex(relative_path);
if(index < 0) return;
RecordLoc* loc = _match_records[index];
MatchRecordV3 rec;
assert(loc->read_loc > 0);
//read in the number of
if(num_match_verification || NM == 0)
{
_lseek(_fid, loc->read_loc, SEEK_SET);
_read(_fid, &fnm, sizeof(int));
NM = fnm;
}else
{
_lseek(_fid, loc->read_loc + sizeof(int), SEEK_SET);
}
assert(tvg.NF<=0 || tvg.NE==0 || tvg.NF == tvg.NE);
szmin = (1 + (NM + tvg.NF) * 2 )* sizeof(int) + sizeof(rec);
if(szmin > loc->block_size) //this is unlikey to happen, right?
{
//not enough size.
size_t offset = ((char*)loc) - ((char*)_match_records[0]);
_recordloc_unchanged = min (_recordloc_unchanged, offset);
if(loc->block_size ==0 || index == _header.file_count - 1)
{
int bs = sizeof(MatchRecordV3) + max(NM + tvg.NF, 8) * sizeof(int) * 4;
//last one in the file
loc->block_size = bs;
}else if(szmin > loc->block_size + loc->trash_size)
{
// not enough space?
MoveRecordToEnd(index);
index = _header.file_count -1;
loc = _match_records[index];
loc->block_size = sizeof(MatchRecordV3) + max(NM + tvg.NF, 8) * sizeof(int) * 4;
}else
{
loc->block_size += loc->trash_size;
loc->trash_size = 0;
}
if(!delay_header_update)
{
printf("Reallocate space fo record %d\r\n", index);
UpdateHeaderAndRecordLoc();
_lseek(_fid, loc->read_loc + sizeof(int), SEEK_SET);
}
}
//
//Write inlier pairs
if(reverse == 0)
{
rec.tvg.SetGeometry(tvg);
//write inlier match record
_write(_fid, &rec, sizeof(rec));
_lseek(_fid, NM * sizeof(int) * 2, SEEK_CUR);
if(tvg.NF >0)
{
_write(_fid, inliers[0], sizeof(int) * tvg.NF);
_write(_fid, inliers[1], sizeof(int) * tvg.NF);
}
}else
{
rec.tvg.SetGeometryR(tvg);;
//write inlier match record
_write(_fid, &rec, sizeof(rec));
_lseek(_fid, NM * sizeof(int) * 2, SEEK_CUR);
if(tvg.NF > 0)
{
_write(_fid, inliers[1], sizeof(int) * tvg.NF);
_write(_fid, inliers[0], sizeof(int) * tvg.NF);
}
}
}
void MatchFile::WritePMatch(const char* image1, const char* image2,
int fc1, int fc2, int NM, Points& matches)
{
MatchFile file1, file2;
if(file1.OpenMatchFile(image1, 1))
{
file1.WritePMatch(image2, fc2, NM, matches, 0);
file1.CloseMatchFile();
}
if(file2.OpenMatchFile(image2, 1))
{
file2.WritePMatch(image1, fc1, NM, matches, 1);
file2.CloseMatchFile();
}
}
void MatchFile::WritePMatch(const char* image_match, int FC, int NM, Points&matches, int reverse)
{
int index;
char relative_path[MAX_PATH];
if(image_match == NULL || image_match[0] == 0) return;
GetRelativePath(image_match, relative_path);
index = GetImageIndex(relative_path);
if(index < 0) index = AddImageMatch(relative_path);
RecordLoc* loc = _match_records[index];
loc->fcount = FC;
assert(loc->read_loc > 0);
size_t offset = ((char*)loc) - ((char*)_match_records[0]);
_recordloc_unchanged = min (_recordloc_unchanged, offset);
if(loc->block_size ==0 || index == _header.file_count - 1)
{
int bs = sizeof(MatchRecordV3) + max(NM, 8) * sizeof(int) * 6;
//last one in the file
loc->block_size = bs;
}else
{
int bsmin = sizeof(MatchRecordV3) + max(NM, 0) * sizeof(int) * 4;
if(bsmin > loc->block_size)
{
if(bsmin > loc->block_size + loc->trash_size)
{
// not enough space?
MoveRecordToEnd(index);
index = _header.file_count -1;
loc = _match_records[index];
loc->block_size = sizeof(MatchRecordV3) + max(NM, 8) * sizeof(int) * 6;
}else
{
loc->block_size += loc->trash_size;
loc->trash_size = 0;
}
}
}
//update file _header and locs
if(!delay_header_update)
{
UpdateHeaderAndRecordLoc();
}
MatchRecordV3 rec;
//write pmatch
_lseek(_fid, loc->read_loc, SEEK_SET);
//write match record
_write(_fid, &NM, sizeof(int));
_write(_fid, &rec, sizeof(rec));
//write matched pairs
if(NM <=0) return;
if(reverse == 0)
{
_write(_fid, matches[0], sizeof(int) * NM);
_write(_fid, matches[1], sizeof(int) * NM);
}else
{
_write(_fid, matches[1], sizeof(int) * NM);
_write(_fid, matches[0], sizeof(int) * NM);
}
}
void MatchFile::UpdateHeaderAndRecordLoc()
{
//the file _header
if(_header_changed)
{
_lseek(_fid, 0, SEEK_SET);
//VERIFY(_header.version == MATCH_FILE_LATEST_VERSION);
_write(_fid, &_header, sizeof(_header));
_header_changed = 0;
}
if(_header.definition_size > _recordloc_unchanged)
{
//recordloc
_lseek(_fid, sizeof(_header) + _recordloc_unchanged, SEEK_SET);
_write(_fid, &_record_definition[_recordloc_unchanged], _header.definition_size - _recordloc_unchanged);
_recordloc_unchanged = _header.definition_size;
}
}
///////////////////////
int MatchFile::GetPMatch(const char* image_path, int FC, int& NM, Points& matches)
{
int index;
char relative_path[MAX_PATH];
GetRelativePath(image_path, relative_path);
index = GetImageIndex(relative_path);
if(index < 0)
{
NM = 0;
matches.resize(0, 0);
return 0;
}else
{
RecordLoc * loc = _match_records[index];
if(loc->fcount == FC)
{
_lseek(_fid, loc->read_loc, SEEK_SET);
_read(_fid, &NM, sizeof(int));
_lseek(_fid, sizeof(MatchRecordV3), SEEK_CUR);
if(NM >0 && NM <= FC)
{
matches.resize(NM, 2);
_read(_fid, matches[0], 2 * NM * sizeof(int));
}else
{
matches.resize(0, 0);
NM = 0;
}
return NM;
} else
{
NM = 0;
matches.resize(0, 0);
return 0;
}
}
}
int MatchFile::GetPMatchR(const char* image_path, int FC, int& NM, Points& matches)
{
int index;
char relative_path[MAX_PATH];
GetRelativePath(image_path, relative_path);
index = GetImageIndex(relative_path);
if(index < 0)
{
NM = 0;
matches.resize(0, 0);
return 0;
}else
{
RecordLoc * loc = _match_records[index];
if(loc->fcount == FC)
{
_lseek(_fid, loc->read_loc, SEEK_SET);
_read(_fid, &NM, sizeof(int));
_lseek(_fid, sizeof(MatchRecordV3), SEEK_CUR);
if(NM > 0 && NM <= FC)
{
matches.resize(NM, 2);
_read(_fid, matches[1], NM * sizeof(int));
_read(_fid, matches[0], NM * sizeof(int));
}else
{
matches.resize(0, 0);
}
return NM;
} else
{
NM = 0;
matches.resize(0, 0);
return 0;
}
}
}
int MatchFile:: GetMatchCount(const char* image_path, int&NM, int& NF)
{
int index;
char relative_path[MAX_PATH];
GetRelativePath(image_path, relative_path);
index = GetImageIndex(relative_path);
if(index < 0 )
{
NM = NF = 0;
return 0;
}else
{
int counts[3];
RecordLoc * loc = _match_records[index];
_lseek(_fid, loc->read_loc, SEEK_SET);
_read(_fid, counts, sizeof(counts));
NM = counts[0]; NF = counts[2];
return 1;
}
}
int MatchFile::GetIMatch(const char* image_path, int FC, TwoViewGeometry& tvg, Points&inliers)
{
int index;
char relative_path[MAX_PATH];
GetRelativePath(image_path, relative_path);
index = GetImageIndex(relative_path);
if(index < 0 )
{
tvg.ResetGeometry();
inliers.resize(0, 0);
return 0;
}else
{
RecordLoc * loc = _match_records[index];
if(loc->fcount != FC)
{
tvg.ResetGeometry();
inliers.resize(0, 0);
printf("# features changed: [%s][%d->%d]!!!\r\n", image_path, loc->fcount, FC);
return 0;
}else
{
int NM;
MatchRecordV3 rec;
_lseek(_fid, loc->read_loc, SEEK_SET);
_read(_fid, &NM, sizeof(int));
_read(_fid, &rec, sizeof(rec));
if(NM > loc->fcount || NM < 0)
{
tvg.ResetGeometry();
inliers.resize(0, 0);
printf("ERROR: incorrect matching count [%d, %d]\r\n", NM, loc->fcount);
return 0;
}else if(NM == 0 || rec.version != MatchFile::MATCH_RECORD_V3 || rec.tvg.NF > loc->fcount)
{
tvg.ResetGeometry();
inliers.resize(0, 0);
//printf("#--BAD matching record---###\r\n");
return 0;
}else
{
//////////////////////////
tvg.SetGeometry(rec.tvg);
//
if(tvg.NF > 0)
{
_lseek(_fid, NM * 2 * sizeof(int), SEEK_CUR);
inliers.resize(tvg.NF, 2);
_read(_fid, inliers[0], 2 * tvg.NF * sizeof(int));
}else
{
inliers.resize(0, 0);
}
return NM;
}
}
}
}
int MatchFile::GetIMatchR(const char* image_path, int FC, TwoViewGeometry& tvg, Points&inliers)
{
int index;
char relative_path[MAX_PATH];
GetRelativePath(image_path, relative_path);
index = GetImageIndex(relative_path);
if(index < 0 )
{
tvg.ResetGeometry();
inliers.resize(0, 0);
return 0;
}else
{
RecordLoc * loc = _match_records[index];
if(loc->fcount != FC)
{
tvg.ResetGeometry();
inliers.resize(0, 0);
printf("# feature changed: [%s][%d->%d]!!!\r\n", image_path, loc->fcount, FC);
return 0;
}else
{
int NM;
MatchRecordV3 rec;
_lseek(_fid, loc->read_loc, SEEK_SET);
_read(_fid, &NM, sizeof(int));
_read(_fid, &rec, sizeof(rec));
if(NM > loc->fcount || NM < 0)
{
tvg.ResetGeometry();
inliers.resize(0, 0);
printf("ERROR: incorrect matching count [%d, %d]\r\n", NM, loc->fcount);
return 0;
}else if(NM == 0 || rec.version != MatchFile::MATCH_RECORD_V3 || rec.tvg.NF > loc->fcount)
{
tvg.ResetGeometry();
inliers.resize(0, 0);
//printf("#--BAD matching record---###\r\n");
return 0;
}else
{
///
tvg.SetGeometryR(rec.tvg);
//
if(tvg.NF > 0)
{
_lseek(_fid, NM * 2 * sizeof(int), SEEK_CUR);
inliers.resize(tvg.NF, 2);
_read(_fid, inliers[1], tvg.NF * sizeof(int));
_read(_fid, inliers[0], tvg.NF * sizeof(int));
}else
{
inliers.resize(0, 0);
}
return NM;
}
}
}
}
然后自己随便加一个头文件,尝试读取.mat
main.cpp
/*
error C4996: '_open': This function or variable may be unsafe. Consider using _sopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
根据提示,use _CRT_SECURE_NO_DEPRECATE
在项目|属性|配置属性|C/C++|命令行|附加选项,加入{/D "_CRT_SECURE_NO_DEPRECATE"}(注:加入中括号中完整的内容)
或者在项目|属性|配置属性|C/C++|预处理器|预处理定义中加入 _CRT_SECURE_NO_DEPRECATE
*/
#include
#include
#include
#include
#include
using namespace std;
#include "FeaturePoints.h"
#include "MatchFile.h"
int main()
{
//MatchFile match;
//int flag = match.OpenMatchFile("D:\\code\\SFM\\ImageDataset_SceauxCastle-master\\images\\100_7100", 0, 0);
return 0;
}