www.gusucode.com > VC++遥感原理与数字摄影测量实习源码程序 > VC++遥感原理与数字摄影测量实习源码程序\code\ImgMatch\ImgMatch.cpp

    //Download by http://www.NewXing.com
// ImgMatch.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "ImgMatch.h"
#include <vector>
#include <math.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define FAILURE	-1

struct FEATUREPOINT
{
	int x;
	int y;		//坐标
	float IV;	//兴趣值
};

struct MATCHEDPOINTS 
{
	int x1;
	int y1;
	int x2;
	int y2;				//坐标
	float coefficient;	//相关系数
};

double CalcCorrelation(LPBYTE pDl,LPBYTE pDr,int xl,int yl,int xr,int yr,int wm,int wn,
					   int widthLeft,int widthRight, int heightLeft, int heightRight);

/////////////////////////////////////////////////////////////////////////////
// The one and only application object

CWinApp theApp;

using namespace std;

void Moravec(BYTE* pSrcBits, vector<FEATUREPOINT> *FeaturePoint,
			 int m_threshold, int m_window1, int m_window2, int width, int height, int* Count1)
{
	int i(0), j(0), m(0), n(0);
	
	int k = m_window1 / 2;

	DWORD _width = (width*8 + 31)/32*4;	//saved width in files
	
	float v1(0), v2(0), v3(0), v4(0);
	float IV(0);

	float* pInterest = new float[width*height];	//new 3
	ZeroMemory(pInterest, sizeof(float)*width*height);

	for (i = k; i < height - k; ++i)
	{
		for (j = k; j < width - k; ++j)
		{
			//计算一个点
			v1 = v2 = v3 = v4 = 0.0;
			for (m = 0; m < m_window1-1; ++m)
			{
				v1 += (pSrcBits[(i-k+m)*_width + (j)] - pSrcBits[(i-k+1+m)*_width + (j)])*
					(pSrcBits[(i-k+m)*_width + (j)] - pSrcBits[(i-k+1+m)*_width + (j)]);
				
				v2 += (pSrcBits[(i-k+m)*_width + (j-k+m)] - pSrcBits[(i-k+1+m)*_width + (j-k+m+1)])*
					(pSrcBits[(i-k+m)*_width + (j-k+m)] - pSrcBits[(i-k+1+m)*_width + (j-k+m+1)]);
				
				v3 += (pSrcBits[(i)*_width + (j-k+m)] - pSrcBits[(i)*_width + (j-k+1+m)])*
					(pSrcBits[(i)*_width + (j-k+m)] - pSrcBits[(i)*_width + (j-k+1+m)]);
				
				v4 += (pSrcBits[(i-k+m)*_width + (j+k-m)] - pSrcBits[(i-k+m+1)*_width + (j+k-m-1)])*
					(pSrcBits[(i-k+m)*_width + (j+k-m)] - pSrcBits[(i-k+m+1)*_width + (j+k-m-1)]);
			}
			
			IV = min(v1, v2);
			IV = min(IV, v3);
			IV = min(IV, v4);
			
			if (IV > m_threshold)
			{
				//成为候选点
				pInterest[i*width+j] = IV;
				*Count1 ++;
			}
		}
	}
	
	int k2 = m_window2 / 2;
	
	float max2(0);
	int tempX(0), tempY(0);
	bool b(false);

	FEATUREPOINT tempFP;
	ZeroMemory(&tempFP, sizeof(FEATUREPOINT));
	
	for(i = k2; i < height - k2; i += m_window2)
	{
		for(j = k2; j < width - k2; j += m_window2)	//i,j为小窗口中心点
		{
			max2 = 0;
			b = false;
			for (int m = i-k2; m < i+k2+1; ++m)
			{
				for (int n = j-k2; n < j+k2+1; ++n)
				{
					if(pInterest[m*width + n]>max2)
					{
						max2 = pInterest[m*width + n];
						tempY = m;
						tempX = n;
						b = true;
					}
				}
			}
			if (b)
			{
				tempFP.IV = pInterest[tempY*width+tempX];
				tempFP.x = tempX;
				tempFP.y = tempY;
				FeaturePoint->push_back(tempFP);
			}
		}
	}

	delete[] pInterest;
	pInterest = NULL;
}

vector<FEATUREPOINT> RemoveReplicative(vector<FEATUREPOINT> v)
{
	vector<FEATUREPOINT> ret;
	
	vector<FEATUREPOINT>::iterator iter = v.begin();
	
	ret.clear();
	
	ret.push_back(*iter);
	
	vector<FEATUREPOINT>::iterator iter2;
	
	BOOL b(FALSE);
	
	for (iter = v.begin(); iter != v.end(); ++iter)
	{
		b = false;
		
		for (iter2 = ret.begin(); iter2 != ret.end(); ++iter2)
		{
			if (iter->x == iter2->x && iter->y == iter2->y)
			{
				b = TRUE;	//存在
				break;
			}
		}
		
		if (b == FALSE)
		{
			ret.push_back(*iter);
		}
	}
	return ret;
}

void SaveBand(int width, int height, int byteCount, int biBitCount, LPBYTE pBits, CString SavePath)
{
	BITMAPFILEHEADER bmfh;
	BITMAPINFOHEADER bmih;
	
	bmfh.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M"	
	bmfh.bfReserved1 = 0;
	bmfh.bfReserved2 = 0;
	
	if (biBitCount == 8)
	{
		bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256*4;
		bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256*4 + byteCount;
	}
	else if (biBitCount == 24)
	{
		bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
		bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + byteCount;
	}
	else
	{
		MessageBox(NULL, "8bit or 24bit accepted", "错误", MB_ICONERROR);
		return;
	}
	
	
	bmih.biBitCount = biBitCount;
	bmih.biWidth = width;
	bmih.biHeight = height;
	bmih.biSize = 40;
	bmih.biPlanes = 1;
	bmih.biCompression = BI_RGB;
	bmih.biSizeImage = bmfh.bfSize;
	bmih.biClrImportant = 0;
	bmih.biClrUsed = 0;
	bmih.biXPelsPerMeter = 0;
	bmih.biYPelsPerMeter = 0;
	
	CFile f;
	
	//保存位图
	if (f.Open(SavePath, CFile::modeCreate | CFile::modeWrite))
	{
		f.Write(&bmfh, sizeof(bmfh));
		
		f.Write(&bmih, sizeof(bmih));
		
		if (biBitCount == 8)
		{
			RGBQUAD rgb[256];
			int i(0);
			for (; i < 256; ++i)
			{
				rgb[i].rgbBlue = i;
				rgb[i].rgbGreen = i;
				rgb[i].rgbRed = i;
				rgb[i].rgbReserved = 0;
			}
			
			//修改颜色表255对应的颜色
			rgb[255].rgbBlue = 0;
			rgb[255].rgbGreen = 0;
			rgb[255].rgbRed = 255;
			f.Write(rgb, sizeof(RGBQUAD)*256);
		}
		
		f.Write(pBits, byteCount);
		
		f.Close();
	}
	else
	{
		MessageBox(NULL, "保存图像失败", "错误", MB_ICONERROR);
		return;
	}
}

void DrawCross(BYTE* pBits, vector<FEATUREPOINT> FeaturePoint, int _width, int byteCount)
{
	vector<FEATUREPOINT>::iterator iter;

	int i(0), j(0);

	for (i = 0; i < byteCount; ++i)
	{
		if (pBits[i] == 255)
			pBits[i] = 254;
	}

	for (iter = FeaturePoint.begin(); iter != FeaturePoint.end(); ++iter)
	{
		i = iter->y;
		j = iter->x;
		
		pBits[i*_width+j] = 255;
		
		pBits[i*_width+j+1] = 255;
		pBits[i*_width+j-1] = 255;
		pBits[(i+1)*_width+j] = 255;
		pBits[(i-1)*_width+j] = 255;
		
		pBits[i*_width+j+2] = 255;
		pBits[i*_width+j-2] = 255;
		pBits[(i+2)*_width+j] = 255;
		pBits[(i-2)*_width+j] = 255;
	}
}

void DrawCross(BYTE* pBits1, BYTE* pBits2, vector<MATCHEDPOINTS> MatchedPoints,
			   int _width1, int _width2, int byteCount1, int byteCount2)
{
	vector<MATCHEDPOINTS>::iterator iter;
	
	int i(0), j(0);
	
	for (i = 0; i < byteCount1; ++i)
	{
		if (pBits1[i] == 255)
			pBits1[i] = 254;
	}

	for (j = 0; j < byteCount2; ++j)
	{
		if (pBits2[j] == 255)
			pBits2[j] = 254;
	}
	
	for (iter = MatchedPoints.begin(); iter != MatchedPoints.end(); ++iter)
	{
		i = iter->y1;
		j = iter->x1;
		
		pBits1[i*_width1+j] = 255;
		
		pBits1[i*_width1+j+1] = 255;
		pBits1[i*_width1+j-1] = 255;
		pBits1[(i+1)*_width1+j] = 255;
		pBits1[(i-1)*_width1+j] = 255;
		
		pBits1[i*_width1+j+2] = 255;
		pBits1[i*_width1+j-2] = 255;
		pBits1[(i+2)*_width1+j] = 255;
		pBits1[(i-2)*_width1+j] = 255;

		i = iter->y2;
		j = iter->x2;
		
		pBits2[i*_width2+j] = 255;	//
		
		pBits2[i*_width2+j+1] = 255;
		pBits2[i*_width2+j-1] = 255;
		pBits2[(i+1)*_width2+j] = 255;
		pBits2[(i-1)*_width2+j] = 255;
		
		pBits2[i*_width2+j+2] = 255;
		pBits2[i*_width2+j-2] = 255;
		pBits2[(i+2)*_width2+j] = 255;
		pBits2[(i-2)*_width2+j] = 255;

	}
}

void SaveList(vector<FEATUREPOINT> FeaturePoint, CString txtFile)
{
	FILE*  pTxtFile= fopen(txtFile, "wt");
	
	if (!pTxtFile)
		return;
	
//	fprintf(pTxtFile, "#\t阈值: %d\n", m_threshold);
//	fprintf(pTxtFile, "#\t窗口1: %d×%d\n#\t窗口2: %d×%d\n", m_window1, m_window1, m_window2, m_window2);
//	fprintf(pTxtFile, "#\t兴趣点数: %d\n", Count1);
	fprintf(pTxtFile, "#\t特征点数: %d\n\n", FeaturePoint.size());
	fprintf(pTxtFile, "坐标X\t坐标Y\t兴趣值\n");
	
	vector<FEATUREPOINT>::iterator iter;
	
	for (iter = FeaturePoint.begin(); iter != FeaturePoint.end(); ++iter)
		fprintf(pTxtFile, "%d\t%d\t%d\n", iter->x, iter->y, (int)iter->IV);
	
	fclose(pTxtFile);

}

void SaveList(vector<MATCHEDPOINTS> MatchedPoints, CString txtFile)
{
	FILE*  pTxtFile= fopen(txtFile, "wt");
	
	if (!pTxtFile)
		return;
	
	//	fprintf(pTxtFile, "#\t阈值: %d\n", m_threshold);
	//	fprintf(pTxtFile, "#\t窗口1: %d×%d\n#\t窗口2: %d×%d\n", m_window1, m_window1, m_window2, m_window2);
	//	fprintf(pTxtFile, "#\t兴趣点数: %d\n", Count1);
	fprintf(pTxtFile, "#同名点对数: %d\n\n",MatchedPoints.size());
	fprintf(pTxtFile, "坐标X\t坐标Y\t兴趣值\n");
	
	vector<MATCHEDPOINTS>::iterator iter;
	
	for (iter = MatchedPoints.begin(); iter != MatchedPoints.end(); ++iter)
		fprintf(pTxtFile, "%d\t%d\t%d\t%d\t%f\n",
		iter->x1, iter->y1, iter->x2, iter->y2, iter->coefficient);
	
	fclose(pTxtFile);
	
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	if (argc != 15)
	{
		::MessageBox(NULL,"启动参数不正确,请从GUI.exe或命令行参数启动","",MB_ICONASTERISK);
		return FAILURE;
	}
	system("Mode con: COLS=50 LINES=150");
	system("title Image_Match");
	int nRetCode = 0;
	
	// initialize MFC and print and error on failure
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
	{
		// TODO: change error code to suit your needs
		cerr << _T("Fatal Error: MFC initialization failed") << endl;
		nRetCode = 1;
		return nRetCode;
	}
	
	CString srcFileLeft, srcFileRight, dstFileLeft, dstFileRight, txtFile;
	CString threshold_Left,window1_Left,window2_Left;
	CString threshold_Right,window1_Right,window2_Right;
	CString CoRelated,window3,flag1;	//启动参数
	
	srcFileLeft = argv[1];
	srcFileRight = argv[2];
	dstFileLeft = argv[3];
	dstFileRight = argv[4];
	txtFile = argv[5];
	
	threshold_Left = argv[6];	//阈值
	window1_Left = argv[7];
	window2_Left = argv[8];
	
	threshold_Right = argv[9];
	window1_Right = argv[10];
	window2_Right = argv[11];
	
	CoRelated = argv[12];
	window3 = argv[13];
	flag1 = argv[14];		//判断是否在创建结果文件后显示
	
	int m_threshold_L = atoi(threshold_Left);
	int m_window1_L = atoi(window1_Left);
	int m_window2_L = atoi(window2_Left);
	
	int m_threshold_R = atoi(threshold_Right);
	int m_window1_R = atoi(window1_Right);
	int m_window2_R = atoi(window2_Right);
	
	double m_CoRelated = (double)atoi(CoRelated) / 100;
	int m_window3 = atoi(window3);
	int m_flag1 = atoi(flag1);
	
	if (GetFileAttributes(srcFileLeft) == -1)
	{
		CString err;
		err.Format("文件:%s不存在", srcFileLeft);		
		::MessageBox(NULL,err, "Error", MB_ICONERROR);
		return FAILURE;
	}
	
	if (GetFileAttributes(srcFileRight) == -1)
	{
		CString err;
		err.Format("文件:%s不存在", srcFileRight);		
		::MessageBox(NULL,err, "Error", MB_ICONERROR);
		return FAILURE;
	}

	//打开2幅影像
	FILE* pSrcFileLeft = NULL;
	pSrcFileLeft = fopen(srcFileLeft,"rb");
	if(pSrcFileLeft == NULL)
	{
		printf("原始左片影像打开失败\n");
		return FAILURE;
	}

	FILE* pSrcFileRight = NULL;
	pSrcFileRight = fopen(srcFileRight,"rb");
	if(pSrcFileRight == NULL)
	{
		printf("原始右片影像打开失败\n");
		return FAILURE;
	}

	//读取左片数据
	BITMAPFILEHEADER bmfhLeft;
	BITMAPINFOHEADER bmihLeft;

	fread(&bmfhLeft, sizeof(BITMAPFILEHEADER), 1, pSrcFileLeft);
	fread(&bmihLeft, sizeof(BITMAPINFOHEADER), 1, pSrcFileLeft);

	if(bmihLeft.biBitCount != 8)
	{
		printf("只支持8位位图: 左片\n");
		return FAILURE;
	}

	DWORD widthLeft = bmihLeft.biWidth;
	DWORD heightLeft = bmihLeft.biHeight;
	DWORD _widthLeft = (widthLeft*8 + 31)/32*4;	//saved widthLeft in files
	DWORD pixelCountLeft = _widthLeft*heightLeft;

	fseek(pSrcFileLeft, 256*sizeof(RGBQUAD), SEEK_CUR);

	BYTE* pSrcBitsLeft = new BYTE[pixelCountLeft];		//new 1

	fread(pSrcBitsLeft, sizeof(BYTE), pixelCountLeft, pSrcFileLeft);

	fclose(pSrcFileLeft);
	pSrcFileLeft = NULL;

	//读取右片数据
	BITMAPFILEHEADER bmfhRight;
	BITMAPINFOHEADER bmihRight;
	
	fread(&bmfhRight, sizeof(BITMAPFILEHEADER), 1, pSrcFileRight);
	fread(&bmihRight, sizeof(BITMAPINFOHEADER), 1, pSrcFileRight);
	
	if(bmihRight.biBitCount != 8)
	{
		printf("只支持8位位图: 右片\n");
		return FAILURE;
	}
	
	DWORD widthRight = bmihRight.biWidth;
	DWORD heightRight = bmihRight.biHeight;
	DWORD _widthRight = (widthRight*8 + 31)/32*4;	//saved widthRight in files
	DWORD pixelCountRight = _widthRight*heightRight;
	
	fseek(pSrcFileRight, 256*sizeof(RGBQUAD), SEEK_CUR);
	
	BYTE* pSrcBitsRight = new BYTE[pixelCountRight];	//new 2
	
	fread(pSrcBitsRight, sizeof(BYTE), pixelCountRight, pSrcFileRight);
	
	fclose(pSrcFileRight);
	pSrcFileRight = NULL;

	//////////////////////////////////////////////////////////////////////////
	//开始计算左片特征点

	//计算左片的兴趣点存储于该vector中
	vector<FEATUREPOINT> FeaturePoint;

	int Count1(0);

	Moravec(pSrcBitsLeft, &FeaturePoint, m_threshold_L, m_window1_L, m_window2_L,
		widthLeft, heightLeft, &Count1);

	int Count2(0);

	cout << FeaturePoint.size() << endl;
	
	FeaturePoint = RemoveReplicative(FeaturePoint);

	cout << "FeaturePoint.size() == " << FeaturePoint.size() << endl;

	SaveList(FeaturePoint, "d:\\list1.txt");

//	DrawCross(pSrcBitsLeft, FeaturePoint, _widthLeft, pixelCountLeft);

//	SaveBand(widthLeft, heightLeft, pixelCountLeft, 8, pSrcBitsLeft, "d:\\left_.bmp");

//	return 0;

	//特征点计算完毕,存储于vector中

	//遍历vector, 在右片中搜寻相关系数最大的窗口

	vector<FEATUREPOINT>::iterator iter;
	
//	m_window3 = 5;

	int k = m_window3 / 2;
	
	int i(0), j(0), m(0), n(0);
	
	BYTE* pTemplate = new BYTE[m_window3*m_window3];	//new 5
	ZeroMemory(pTemplate, sizeof(BYTE)*m_window3*m_window3);

	BYTE* pTarget = new BYTE[m_window3*m_window3];		//new 6
	ZeroMemory(pTarget, sizeof(BYTE)*m_window3*m_window3);

	vector<MATCHEDPOINTS> MatchedPoints;

	float MaxR(0);
	float R(0);
	double A(0), B(0), C(0), D(0), E(0);	//计算相关系数的中间量

	int lMaxWidth;
	int lMaxHeight;
	
	for (iter = FeaturePoint.begin(); iter != FeaturePoint.end(); ++iter)
	{
		cout << endl << "ID: " << Count2++ << endl;
		//计算该点对应的特征点
		
		B = 0.0;
		D = 0.0;

		MaxR = 0.0;
		R = 0.0;

		if (iter->x < k || iter->y < k || iter->x > heightRight - k || iter->y > widthRight - k)
		{
			cout << "point abort: " << Count2 << endl;
			continue;
		}
		
		//逐个搜索

		//将左片小窗口内的数据拷贝
//		for (i = 0; i < m_window3; ++i)
//		{
//			for (j = 0; j < m_window3; ++j)
//			{
//				pTemplate[i*m_window3+j] = pSrcBitsLeft[(iter->x-k+j)*_widthLeft + (iter->y-k+i)];
//			}
//		}
		
		//可先求出B,D
		for (i = 0; i < m_window3; ++i)
		{
			for(j = 0; j < m_window3 ; ++j)
			{
				//B = 小窗口所有像素灰度值求和
				//D = ....................的平方再求和
//				B += pTemplate[i*m_window3 + j];
//				D += pTemplate[i*m_window3 + j] * pTemplate[i*m_window3 + j];

				B += pSrcBitsLeft[(i+iter->y)*_widthLeft + (j+iter->x)];
				D += pSrcBitsLeft[(i+iter->y)*_widthLeft + (j+iter->x)] * 
					pSrcBitsLeft[(i+iter->y)*_widthLeft + (j+iter->x)];
			}
		}
		
		//逐个小窗口计算R
		for(i = 0; i < heightRight - m_window3 + 1; ++i)
		{
			for(j = 0; j < widthRight - m_window3 + 1; ++j)	//i,j为右片某小窗口的一个顶点
			{
				A = 0.0;
				C = 0.0;
				E = 0.0;

				int centerX = j + k;
				int centerY = i + k;
				//这里的centerX,centerY就是右片某个小窗口的中心

/*
				//将右片小窗口的数据拷贝
				for (m = 0; m < m_window3; ++m)
				{
					for (n = 0; n < m_window3; ++n)
					{
						pTarget[i*m_window3+j] = pSrcBitsRight[(iter->x-k+i)*_widthLeft + (iter->y-k+j)];
					}
				}*/


				//求A,C,E
				for (m = 0; m < m_window3; ++m)
				{
					for(n = 0; n < m_window3 ; ++n)
					{
						//C = 左片小窗口所有像素灰度值求和
						//E = ........................平方的求和
						//A = 对应位置像素灰度直乘积之和

						C += pSrcBitsRight[(i+m)*_widthRight + (j+n)];
						E += pSrcBitsRight[(i+m)*_widthRight+(j+n)]*pSrcBitsRight[(i+m)*_widthRight+(j+n)];
//						A += pSrcBitsRight[(i+m)*_widthRight+(j+n)]*pTemplate[m*m_window3+n];

						A += pSrcBitsRight[(i+m)*_widthRight+(j+n)] *
							pSrcBitsLeft[(m+iter->y)*_widthLeft + (n+iter->x)];
//							pSrcBitsLeft[(i+iter->y)*_widthLeft + (j+iter->x)]
					}
				}

				double temp1 = D - B*B/m_window3/m_window3;
				double temp2 = E - C*C/m_window3/m_window3;

				if (temp1 != 0 && temp2 != 0)
				{
					R = (A - B*C/m_window3/m_window3) / sqrt(temp1*temp2);
				}
				else
					R = 0;

//				double sss;
//				sss = CalcCorrelation(pSrcBitsLeft, pSrcBitsRight, iter->x, iter->y, centerX, centerY,
//					m_window3, m_window3, widthLeft, widthRight, heightLeft, heightRight);

				if (R > MaxR)
				{
					MaxR = R;
					lMaxWidth = centerX;
					lMaxHeight = centerY;
					cout << R << endl;
				}


				//////////////////////////////////////////////////////////////////////////
/*				double dSigmaST = 0;
				double dSigmaS = 0;
				
				for(n=0;n<m_window3;n++)
				{
					for(m=0;m<m_window3;m++)
					{
						BYTE src = pSrcBitsRight[(i+n)*_widthRight+ (j+m)];
//						lpSrc=(char*)lpData+lRowBytes*(j+n)+(i+m);
						
						BYTE tem = pTemplate[m_window3*n + m];
//						lpTemplateSrc=(char*)lpTemplateData+lRowTemplataBytes*n+m;
						
//						pixel=(unsigned char)*lpSrc;
//						templatepixel=(unsigned char)*lpTemplateSrc;
						
						dSigmaS += (double)src*src;
						dSigmaST += (double)src*tem;
					}
				}
				
				R=dSigmaST/(sqrt(dSigmaS)*sqrt(dSigmaT));
				
				if(R > MaxR)
				{
					MaxR = R;
					lMaxWidth=j;
					lMaxHeight=i;

					cout << "MaxR: " << MaxR << endl;
				}*/
			}
		}

		if (MaxR >= m_CoRelated)
		{
			MATCHEDPOINTS mp;
			mp.coefficient = MaxR;
			mp.x1 = iter->x;
			mp.y1 = iter->y;
			mp.x2 = lMaxWidth;
			mp.y2 = lMaxHeight;
			
			MatchedPoints.push_back(mp);
		}
	}
	
	//保存结果位图
	DrawCross(pSrcBitsLeft, pSrcBitsRight, MatchedPoints,
		_widthLeft, _widthRight, pixelCountLeft, pixelCountRight);

	SaveBand(widthLeft, heightLeft, _widthLeft*heightLeft, 8, pSrcBitsLeft, dstFileLeft);
	SaveBand(widthRight, heightRight, _widthRight*heightRight, 8, pSrcBitsRight, dstFileRight);

	//保存特征点列表

	SaveList(MatchedPoints, txtFile);
	
	//clean up
	delete[] pSrcBitsLeft;
	delete[] pSrcBitsRight;
	delete[] pTemplate;

	pSrcBitsLeft = NULL;
	pSrcBitsRight = NULL;
	pTemplate = NULL;

	if (m_flag1 == 1)
	{
		ShellExecute(NULL, "open", txtFile, NULL, NULL, SW_SHOWNORMAL);
	}

	return nRetCode;
}