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; }