⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 image.cpp

📁 一个基于MFC的SIFT图像配准算法代码。好用
💻 CPP
字号:
// Image.cpp: implementation of the CImg class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "disparity 200712.h"
#include "Img.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////



CImg::CImg()
{
	kp = new CKeypoint[N_KP];
	n_kp = 0;
}

CImg::~CImg()
{

}

void CImg::CreateImg(char *filename)
{
	printf("读取图像...");
	image_c = cvLoadImage( filename, 1);	//读彩色图像
	image = cvLoadImage( filename, 0);		//强制转换为单色

	width = image->width;					//保存图像的尺寸
	height = image->height;

	image32f = cvCreateImage ( cvSize(width,height), IPL_DEPTH_32F, 1);		

	cvConvert( image, image32f);			//转换为32位浮点图像


	//构造高斯图像组Gau[*]
	printf("ok\n");
	for (int i=0; i<LEVEL; i++)
	{
		printf("构造高斯图像组...%d%%\r",(int)(i*100.0/LEVEL));
		Gau[i] = cvCreateImage ( cvSize(width,height), IPL_DEPTH_32F, 1);
		cvSmooth( image32f, Gau[i], CV_GAUSSIAN, 0, 0, pow(RATE,i));
	}

	//计算高斯图像的差分Dog[*]
	printf("构造高斯图像组...ok    \n");
	printf("构造高斯图像的差分...");
	for (i=0; i<LEVEL-1; i++)
	{
		Dog[i] = cvCreateImage ( cvSize(width,height), IPL_DEPTH_32F, 1);
		cvSub( Gau[i+1], Gau[i], Dog[i] );
	}
	printf("ok\n");

}

void CImg::FindKeypoint(void)
{
	int margin;	//图像边缘留出的空白宽度
	double TH;

	for(int i=1; i<LEVEL-2; i++)//高斯模糊等级
	{		
		
		//显示提示
		printf("查找特征点...%d%%\r",(int)(i*100.0/(LEVEL-1)) );

		margin = int(6*pow(RATE,i));		//搜索特征点时要在图像边缘留出一定宽度,以防止出界

		TH = 0;		//域值,但似乎作用不大,所以设为0

		for (int x=margin; x<width-margin; x++)
		{
			for (int y=margin; y<height-margin; y++)
			{
				//查找在 3x3x3 临域中的极值
				if (   (ELEM(Dog[i],x,y) - ELEM(Dog[i],x+1,y) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x-1,y) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x+1,y+1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x-1,y-1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x+1,y-1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x-1,y+1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x,y+1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x,y-1) > TH
					
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x+1,y) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x-1,y) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x+1,y+1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x-1,y-1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x+1,y-1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x-1,y+1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x,y+1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x,y-1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x,y) > TH
					
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x+1,y) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x-1,y) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x+1,y+1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x-1,y-1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x+1,y-1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x-1,y+1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x,y+1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x,y-1) > TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x,y)> TH ) 
					
					|| (ELEM(Dog[i],x,y) - ELEM(Dog[i],x+1,y) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x-1,y) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x+1,y+1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x-1,y-1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x+1,y-1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x-1,y+1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x,y+1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i],x,y-1) < -TH
					
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x+1,y) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x-1,y) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x+1,y+1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x-1,y-1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x+1,y-1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x-1,y+1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x,y+1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x,y-1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i+1],x,y) < -TH
					
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x+1,y) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x-1,y) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x+1,y+1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x-1,y-1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x+1,y-1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x-1,y+1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x,y+1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x,y-1) < -TH
					&&	ELEM(Dog[i],x,y) - ELEM(Dog[i-1],x,y)< -TH )  )

				//下面这一段是把图像的像素当作正六边形(蜂巢形)来处理,但效果不理想
				/*if(
					(ELEM_IN(Dog[i],x,y)>ELEM_IN(Dog[i],x+1,y) &&
					ELEM_IN(Dog[i],x,y)>ELEM_IN(Dog[i],x-1,y) &&
					ELEM_IN(Dog[i],x,y)>ELEM_IN(Dog[i],x+0.5,y+0.5*sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)>ELEM_IN(Dog[i],x+0.5,y-0.5*sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)>ELEM_IN(Dog[i],x-0.5,y+0.5*sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)>ELEM_IN(Dog[i],x-0.5,y-0.5*sqrt(3)) &&

					ELEM_IN(Dog[i],x,y)>ELEM_IN(Dog[i+1],x,y+1/sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)>ELEM_IN(Dog[i+1],x+0.5,y-0.5/sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)>ELEM_IN(Dog[i+1],x+0.5,y-0.5/sqrt(3)) &&

					ELEM_IN(Dog[i],x,y)>ELEM_IN(Dog[i-1],x,y+1/sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)>ELEM_IN(Dog[i-1],x+0.5,y-0.5/sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)>ELEM_IN(Dog[i-1],x+0.5,y-0.5/sqrt(3)) ) ||

					(ELEM_IN(Dog[i],x,y)<ELEM_IN(Dog[i],x+1,y) &&
					ELEM_IN(Dog[i],x,y)<ELEM_IN(Dog[i],x-1,y) &&
					ELEM_IN(Dog[i],x,y)<ELEM_IN(Dog[i],x+0.5,y+0.5*sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)<ELEM_IN(Dog[i],x+0.5,y-0.5*sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)<ELEM_IN(Dog[i],x-0.5,y+0.5*sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)<ELEM_IN(Dog[i],x-0.5,y-0.5*sqrt(3)) &&

					ELEM_IN(Dog[i],x,y)<ELEM_IN(Dog[i+1],x,y+1/sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)<ELEM_IN(Dog[i+1],x+0.5,y-0.5/sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)<ELEM_IN(Dog[i+1],x+0.5,y-0.5/sqrt(3)) &&

					ELEM_IN(Dog[i],x,y)<ELEM_IN(Dog[i-1],x,y+1/sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)<ELEM_IN(Dog[i-1],x+0.5,y-0.5/sqrt(3)) &&
					ELEM_IN(Dog[i],x,y)<ELEM_IN(Dog[i-1],x+0.5,y-0.5/sqrt(3)) ) )*/

				{
					if ( fabs(ELEM(Dog[i],x,y)) > 3 )//这一行用来排除特征不明显的点
					{
						//以下用来排除曲率太小的点(边缘点)
						double Dxx,Dyy,Dxy,Tr,Det,r,threshold;
						double rate = pow(RATE,i);

						Dxx = (ELEM_IN(Dog[i],x+rate,y) + ELEM_IN(Dog[i],x-rate,y) -2*ELEM_IN(Dog[i],x,y));
						Dyy = (ELEM_IN(Dog[i],x,y+rate) + ELEM_IN(Dog[i],x,y-rate) -2*ELEM_IN(Dog[i],x,y));
						Dxy = (( ELEM_IN(Dog[i],x+rate,y+rate) + ELEM_IN(Dog[i],x-rate,y-rate) - ELEM_IN(Dog[i],x-rate,y+rate) - ELEM_IN(Dog[i],x+rate,y-rate)))/4;
						
						Tr = Dxx + Dyy;
						Det = Dxx*Dyy - Dxy*Dxy;

						r=5;
						
						threshold = (r+1)*(r+1)/r;

						if ( fabs(Tr*Tr/Det) < threshold )//(Tr*Tr/Det)表示的是特征点的曲率,其绝对值大于一定值才保留该点
						{
							//最后剩下的特征点,保存下来
							kp[n_kp].level = i;		//保存高斯模糊的等级
							kp[n_kp].x = x;
							kp[n_kp].y = y;			//保存特征点的坐标
							
							if(n_kp<N_KP-1)
							{
								n_kp++;				//特征点个数加一(防止出界N_KP)
							}
						}
					}
				}
			}
		}
	}

	//显示提示
	printf("特征点查找...ok     \n共找到%d个特征点\n", n_kp);
}

void CImg::DrawKeypoint(void)
{
	for (int n=0; n<n_kp; n++)
	{
		int x=kp[n].x;
		int y=kp[n].y;

		float length = (float)pow(RATE,kp[n].level);		//方向矢量的长度

		//if(kp[n].level==1)
		{
		//在彩色图像上用白色“+”表示出特征点的位置
		cvLine( image_c, cvPoint(x-1,y), cvPoint(x+1,y), cvScalar(255,255,255) );
		cvLine( image_c, cvPoint(x,y-1), cvPoint(x,y+1), cvScalar(255,255,255) );
		//画出特征点的方向矢量
		cvLine( image_c, cvPoint(x,y), cvPoint( x+(int)(cos(kp[n].direction*PI/18)*length), y+(int)(sin(kp[n].direction*PI/18)*length)), cvScalar(255,255,255) );
	
		}
	}
}

void CImg::ShowImg(char *title)
{
	cvNamedWindow(title, 1 );
    cvShowImage( title, image_c );		//显示彩色图像
}

//计算特征点的主方向和副方向
void CImg::Direction4Kp(void)
{
	float x,y;
	int level;
	float rate;
	float temp;			//临时变量
	float m,q;			//m表示模,q表示角度
	int n_kp_t = n_kp;	//由Dog的极值所得到的特征点的数量(因为有可能增加)

	printf("计算特征点的方向...");

	for (int n=0; n<n_kp_t; n++)
	{
		level = kp[n].level;
		rate = 2*(float)pow(RATE,level);

		//构造方向直方图
		for (x=-2; x<=2; x+=.5)
		{
			for (y=-2; y<=2; y+=.5)
			{
				if( x*x+y*y < 4)
				{
					m = (float)sqrt(pow(ELEM_IN(Gau[level],kp[n].x+(x+1)*rate,kp[n].y+y*rate)-ELEM_IN(Gau[level],kp[n].x+(x-1)*rate,kp[n].y+y*rate),2)+pow(ELEM_IN(Gau[level],kp[n].x+x*rate,kp[n].y+(y+1)*rate)-ELEM_IN(Gau[level],kp[n].x+x*rate,kp[n].y+(y-1)*rate),2));
					q = (float)atan2(ELEM_IN(Gau[level],kp[n].x+x*rate,kp[n].y+(y+1)*rate)-ELEM_IN(Gau[level],kp[n].x+x*rate,kp[n].y+(y-1)*rate), ELEM_IN(Gau[level],kp[n].x+(x+1)*rate,kp[n].y+y*rate)-ELEM_IN(Gau[level],kp[n].x+(x-1)*rate,kp[n].y+y*rate));

					kp[n].orient[(int)floor((q+2*PI)/(PI/18))%36] += m*(float)exp(-(x*x+y*y)/2);
				}
			}
		}

		//选出最大方向
		temp = kp[n].orient[0];
		for (int d=1; d<36; d++)
		{
			if (kp[n].orient[d]>temp)
			{
				temp = kp[n].orient[d];
				kp[n].direction = d;
			}
		}

		//*/选出副方向
		for (d=0; d<36; d++)
		{
			if ( d!=kp[n].direction && kp[n].orient[d]>0.9*kp[n].orient[kp[n].direction])
			{
				kp[n_kp].level = kp[n].level;
				kp[n_kp].x = kp[n].x;
				kp[n_kp].y = kp[n].y;
				kp[n_kp].direction = d;

				if(n_kp<N_KP-1)
				{
					n_kp++;
				}
			}
		}//*///end of 选出副方向

	}//end of for

	printf("ok\n");
	printf("特征点的数量增加到%d个\n",n_kp);

}

void CImg::ConstructDescripter(void)
{
	double	region_kp[12][12];	//特征点的 12x12 的临域
	double	direction;			//主方向(0-2*PI)
	double	x,y;				//临域中每一点在原图中的对应坐标
	double	rate;

	printf("提取特征...");

	for (int n=0; n<n_kp; n++)
	{
		direction = kp[n].direction*PI/18;  //主方向(0-2*PI)
		rate = 1.5*pow(RATE,kp[n].level);		//特征点所在的等级的比例
		
		//为特征点构造一个12x12的临域
		for (int i=0; i<12; i++)
		{
			for (int j=0; j<12; j++)
			{
				//一些几何变换
				x = (i-5.5*rate)*cos(direction)+(j-5.5*rate)*sin(direction) + kp[n].x;
				y = -(i-5.5*rate)*sin(direction)+(j-5.5*rate)*cos(direction) + kp[n].y;

				if ( x<=0 || x>=width-1 || y<=0 || y>=height-1)
				{	
					//如果落在图像边界之外则给一个平均值128
					region_kp[i][j] = 128;
				}
				else
				{
					//如果在图像边界之内则采用插值
					region_kp[i][j] = ELEM_IN(Gau[kp[n].level], x, y);
				}
			}
		}//end of 构造临域

		//计算特征点的128维特征
		for (int x=0; x<4; x++)
		{
			for (int y=0; y<4; y++)
			{
				int i = x*3+1;
				int j = y*3+1;

			//注释掉的一段:文献上的方法,其实效果差不多
			/*	kp[n].feature[0+(y*4+x)*8] = region_kp[i][j] - region_kp[i+1][j];
				kp[n].feature[1+(y*4+x)*8] = region_kp[i][j] - region_kp[i][j+1];
				kp[n].feature[2+(y*4+x)*8] = region_kp[i][j] - region_kp[i-1][j];
				kp[n].feature[3+(y*4+x)*8] = region_kp[i][j] - region_kp[i][j-1];
				kp[n].feature[4+(y*4+x)*8] = region_kp[i][j] - region_kp[i+1][j+1];
				kp[n].feature[5+(y*4+x)*8] = region_kp[i][j] - region_kp[i+1][j-1];
				kp[n].feature[6+(y*4+x)*8] = region_kp[i][j] - region_kp[i-1][j+1];
				kp[n].feature[7+(y*4+x)*8] = region_kp[i][j] - region_kp[i-1][j-1];
			}
		}*///end of 计算特征
				kp[n].feature[0+(y*4+x)*4] = region_kp[i][j] - region_kp[i+1][j];
				kp[n].feature[1+(y*4+x)*4] = region_kp[i][j] - region_kp[i][j+1];
				kp[n].feature[2+(y*4+x)*4] = region_kp[i][j] - region_kp[i-1][j];
				kp[n].feature[3+(y*4+x)*4] = region_kp[i][j] - region_kp[i][j-1];
			}
		}
		{
			kp[n].feature[64] = region_kp[0][6] - region_kp[11][6];
			kp[n].feature[65] = region_kp[6][0] - region_kp[6][11];

			kp[n].feature[66] = region_kp[0][3] - region_kp[6][3];
			kp[n].feature[67] = region_kp[3][0] - region_kp[3][6];

			kp[n].feature[68] = region_kp[0][9] - region_kp[6][9];
			kp[n].feature[69] = region_kp[9][0] - region_kp[9][6];

			kp[n].feature[70] = region_kp[3][6] - region_kp[3][11];
			kp[n].feature[71] = region_kp[6][3] - region_kp[11][3];

			kp[n].feature[72] = region_kp[9][6] - region_kp[9][11];
			kp[n].feature[73] = region_kp[6][9] - region_kp[11][9];

		}

	}//end of for

//	printf("ok\n");

}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -