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

📄 register.cpp

📁 将数字图像处理的一般算法都集中在一个MFC的框架中
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include "stdafx.h"
#include "Register.h"
#include "math.h"

/***********************************************************************
* 函数名称:
* Register()
*
*说明:无参数的构造函数,对成员变量进行初始化
***********************************************************************/
Register::Register()
{
	//输入图像1相关的成员变量赋初值
	m_nBitCount1=0;
	m_pImgData1=NULL;
	m_lpColorTable1=NULL;
	m_nColorTableLength1=0;
	m_imgWidth1=0;
	m_imgHeight1=0;
	
	//输入图像2相关的成员变量赋初值
	m_nBitCount2=0;
	m_pImgData2=NULL;
	m_lpColorTable2=NULL;
	m_nColorTableLength2=0;
	m_imgWidth2=0;
	m_imgHeight2=0;
	
	//输出图像相关的成员变量赋初值
	m_nBitCountOut=0;
	m_pImgDataOut=NULL;
	m_lpColorTableOut=NULL;
	m_nColorTableLengthOut=0;
	m_imgWidthOut=0;
	m_imgHeightOut=0;
	m_space=10;
}

/***********************************************************************
* 函数名称:
*   ~Register()
*
*说明:析构函数,释放资源
***********************************************************************/
Register::~Register()
{
	//释放图像1的缓冲区
	if(m_pImgData1!=NULL){
		delete []m_pImgData1;
		m_pImgData1=NULL;
	}
	if(m_lpColorTable1==NULL){
		delete []m_lpColorTable1;
		m_lpColorTable1=NULL;
	}
	
	//释放图像2的缓冲区
	if(m_pImgData2!=NULL){
		delete []m_pImgData2;
		m_pImgData2=NULL;
	}
	if(m_lpColorTable2==NULL){
		delete []m_lpColorTable2;
		m_lpColorTable2=NULL;
	}
	
	//释放输出图像的缓冲区
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
		m_pImgDataOut=NULL;
	}
	if(m_lpColorTableOut==NULL){
		delete []m_lpColorTableOut;
		m_lpColorTableOut=NULL;
	}
}

/***********************************************************************
* 函数名称:
* GetDimensions()
*
*函数参数:
*  无
*
*返回值:
*   图像的尺寸,用CSize类型表达
*
*说明:返回输出图像的宽和高
***********************************************************************/
CSize Register::GetDimensions()
{	
	if(m_pImgDataOut == NULL) return CSize(0, 0);
	return CSize(m_imgWidthOut, m_imgHeightOut);
}


/***********************************************************************
* 函数名称:
* InputImg1()
*
*函数参数:
*  CSize size -输入图像大小(宽、高)
*  int nBitCount  -每像素位数
*  LPRGBQUAD lpColorTable  -颜色表指针
*  unsigned char *pImgData  -位图数据指针
*
*返回值:
*   无
*
*说明:输入图像数据,作为参加配准的第一个图像,由数据成员m_pImgData1指向。
***********************************************************************/
void Register::InputImg1(CSize size, int nBitCount, LPRGBQUAD lpColorTable,
						 unsigned char *pImgData)
{
	//清除缓冲区
	if(m_pImgData1!=NULL){
		delete []m_pImgData1;
		m_pImgData1=NULL;
	}
	if(m_lpColorTable1==NULL){
		delete []m_lpColorTable1;
		m_lpColorTable1=NULL;
	}
	
	//为图像1相关的成员变量赋值
	m_nBitCount1=nBitCount;
	m_nColorTableLength1=ComputeColorTabalLength(nBitCount);
	
	//计算输入图像的大小,并为图像1分配合适大小的空间存储位图数据
	m_imgWidth1=size.cx;
	m_imgHeight1=size.cy;
	int lineByte=(m_imgWidth1*nBitCount/8+3)/4*4;
	int imgBufSize=m_imgHeight1*lineByte;
	m_pImgData1=new BYTE[imgBufSize];
	memcpy(m_pImgData1, pImgData, imgBufSize);
	
	//如果有颜色表,分配颜色表所需要的空间,并拷贝颜色表
	if(m_nColorTableLength1!=0){
		m_lpColorTable1= new RGBQUAD[m_nColorTableLength1];
		memcpy(m_lpColorTable1,lpColorTable,
			   sizeof(RGBQUAD) * m_nColorTableLength1);
	}
}


/***********************************************************************
* 函数名称:
* InputImg2()
*
*函数参数:
*  CSize size -输入图像大小(宽、高)
*  int nBitCount  -每像素位数
*  LPRGBQUAD lpColorTable  -颜色表指针
*  unsigned char *pImgData  -位图数据指针
*
*返回值:
*   无
*
*说明:输入图像数据,作为参加配准的第二个图像,由数据成员m_pImgData2指向。
***********************************************************************/
void Register::InputImg2(CSize size, int nBitCount, LPRGBQUAD lpColorTable, unsigned char *pImgData)
{
	//清除缓冲区
	if(m_pImgData2!=NULL){
		delete []m_pImgData2;
		m_pImgData2=NULL;
	}
	if(m_lpColorTable2==NULL){
		delete []m_lpColorTable2;
		m_lpColorTable2=NULL;
	}
	
	//为图像2相关的成员变量赋值
	m_nBitCount2=nBitCount;
	m_nColorTableLength2=ComputeColorTabalLength(nBitCount);
	
	//计算输入图像的大小,并为图像2分配合适大小的空间存储位图数据
	m_imgWidth2=size.cx;
	m_imgHeight2=size.cy;
	int lineByte=(m_imgWidth2*nBitCount/8+3)/4*4;
	int imgBufSize=m_imgHeight2*lineByte;
	m_pImgData2=new BYTE[imgBufSize];
	memcpy(m_pImgData2, pImgData, imgBufSize);
	
	//如果有颜色表,分配颜色表所需要的空间,并拷贝颜色表
	if(m_nColorTableLength2!=0){
		m_lpColorTable2= new RGBQUAD[m_nColorTableLength2];
		memcpy(m_lpColorTable2,lpColorTable,sizeof(RGBQUAD) * m_nColorTableLength2);
	}
}


/***********************************************************************
* 函数名称:
* RegisterBasedSpacial()
*
*函数参数:
*  unsigned char *imgBuf  -参考图(搜索图)位图数据
*  int width  -参考图宽,像素为单位
, int height  -参考图高,像素为单位
*  unsigned char * blockBuf  -基准图(模板)位图数据
*  int blockW  -基准图宽,像素为单位
*  int blockH  -基准图高,像素为单位
*
*返回值:
*   基准图左下角在参考图中的位置坐标,用CPoint类型表达
*
*说明:给定参考图和基准图数据,进行模板匹配,并返回基准图左下角在参考图中
*      的位置坐标,该函数只对灰度图像有效
***********************************************************************/
CPoint Register::RegisterBasedSpacial(unsigned char *imgBuf, int width, int height, 
								unsigned char * blockBuf, int blockW, int blockH)
{
	//图像每行像素的字节数
	int lineByte=(width+3)/4*4;
	
	//标准图像每行字节数
	int blockLineByte=(blockW+3)/4*4;
	
	//循环变量
	int i, j, i0, j0;
	
	//中间变量,每搜索一个位置记录该位置上的相关性测度,本函数用对应像素差的
	//绝对值并求和作为相关性测度,所以sum值最小的位置为最佳匹配位置
	int sum;
	
	//用min记录具有最小sum的值, 及具有最小sum的位置
	int min, minX, minY;
	
	//中间变量
	int t1, t2;
	
    //为了节省时间,此处行方向和纵方向搜索步长为3,读者可根据需要自己调整步长
	for(i=0;i<height-blockH;i+=3){
		for(j=0;j<width-blockW; j+=3){
			sum=0;
			
			//搜索匹配窗口内的像素,(i0,j0)的步长也可以视情况和需要来定
			for(i0=0;i0<blockH;i0++){
				for(j0=0;j0<blockW;j0++){
					//对应像素相减,并计算差的绝对值之和
					t1=*(imgBuf+(i+i0)*lineByte+j+j0);
					t2=*(blockBuf+i0*blockLineByte+j0);
					sum += abs(t1-t2);				
				}
			}
			
			//第一个搜索区域,此时也是最小sum值的位置
			if(i==0&&j==0){
				min=sum;
				minX=0;
				minY=0;
			}
			else{//已经不是第一个搜索位置了
				if(min>sum){//出现一个新的最小位置,记录此时的最小值及其位置坐标
					min=sum;
					minX=j;
					minY=i;
				}
			}
			
		}
	}
	
	//返回匹配位置
	CPoint pos(minX,minY);
	return pos;
}


/***********************************************************************
* 函数名称:
* relativityRegistering()
*
*函数参数:
*  无
*
*返回值:
*   1为成功,0为失败
*
*说明:把m_pImgData1所指向数据作为参考图,m_pImgData2所指向数据作为基准图,
*      进行模板匹配,为m_pImgDataOut分配空间,将结果输出至m_pImgDataOut中。
***********************************************************************/
BOOL Register::relativityRegistering()
{
	//基准图与参考图格式不统一
	if(m_nBitCount1!=m_nBitCount2){	
		return FALSE;//返回
	}

	//匹配位置变量,调用模板匹配函数,获得基准图左下角在参考图中的位置
	CPoint macthPos(0,0);
	macthPos=RegisterBasedSpacial(m_pImgData1, m_imgWidth1, m_imgHeight1, 
		m_pImgData2, m_imgWidth2, m_imgHeight2);
	
	//将匹配结果在输出图像中显示
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
		m_pImgDataOut=NULL;
	}
	
	//输出图像与输入图像为同一类型,此处为灰度类型
	m_nBitCountOut=m_nBitCount1;
	m_nColorTableLengthOut=ComputeColorTabalLength(m_nBitCountOut);
	if(m_nColorTableLengthOut!=0){
		m_lpColorTableOut=new RGBQUAD[m_nColorTableLengthOut];
		memcpy(m_lpColorTableOut,m_lpColorTable1,
			sizeof(RGBQUAD)*m_nColorTableLengthOut);
	}
	
	//输出图像的宽、高及每行像素字节数,与参考图大小相同
	m_imgWidthOut=m_imgWidth1;
	m_imgHeightOut=m_imgHeight1;
	int lineByte=(m_imgWidth1*m_nBitCount1/8+3)/4*4;

	//为输出图像分配空间,并将参考图拷贝至m_pImgDataOut
	m_pImgDataOut=new unsigned char[lineByte*m_imgHeightOut];
	memcpy( m_pImgDataOut,m_pImgData1, lineByte*m_imgHeightOut);
	
	//将基准图的位置用黑色框标记出来,以显示匹配结果的正确性
	for(int i=0;i<m_imgWidth2;i++){
		*(m_pImgDataOut+(macthPos.y+0)*lineByte+macthPos.x+i)=0;
		*(m_pImgDataOut+(macthPos.y+m_imgHeight2-1)*lineByte+macthPos.x+i)=0;
	}
	for(i=0;i<m_imgHeight2;i++){
		*(m_pImgDataOut+(macthPos.y+i)*lineByte+macthPos.x+0)=0;
		*(m_pImgDataOut+(macthPos.y+i)*lineByte+macthPos.x+m_imgWidth2)=0;
	}
	return TRUE;
}


/***********************************************************************
* 函数名称:
* conv2()
*
*函数参数:
*  float *Src  -要处理的数据
*  int width  -参考图宽,像素为单位
, int height  -参考图高,像素为单位
*  float *mark  -(模板)数据
*  int markWidth  -模板宽,像素为单位
*  int markHeight  -模板高,像素为单位
*返回值:
*   无
*
*说明:用mark模板对数组Src进行卷积操作,结果存在Src中
***********************************************************************/
void Register::conv2(float *Src, int width, int height, float *mark,
					 int markWidth , int markHeight )
{
	int i,j,m,n;
	//temp为临时数组,避免在原图上直接操作
	float *temp = new float [width*height];
	memset( temp, 0 , sizeof(float)*width*height);
	float sum;
	int lineByte=(width+3)/4*4;
	
	/////卷积,边缘处不操作
	for (i = (int) markWidth/2 ; i < width - markWidth/2 ;i++)
		for (j = (int) markHeight/2 ; j < height - markHeight/2 ; j++)
		{
			sum=0;
			for (m = -markWidth/2 ; m <= markWidth/2 ; m++)
				for (n = -markHeight/2 ; n <= markHeight/2 ; n++)
				{
					sum += Src[(j+n) * lineByte+ i+m] 
						 * mark[(n+markHeight/2) * markWidth + m+markWidth/2];
				}
				temp[j * lineByte + i]=sum;
		}
		memcpy( Src, temp , sizeof(float)*lineByte*height);
		delete[] temp;
}
/***********************************************************************
* 函数名称:
* ArraydotMultiArray()
*
*函数参数:
*  float * src1 , 源矩阵1
*  float * src2    源矩阵2
, 
* float * dest  结果矩阵
* int width   矩阵的宽
* int height  矩阵的高
*返回值:
*   无
*
*说明:矩阵点乘函数即,dest[i]=src1[i]*src2[i]
***********************************************************************/
void Register::ArraydotMultiArray( float * dest , float * src1 , 
								  float * src2 , int width , int height)
{
	int lineByte=(width+3)/4*4;
	
	for (int i = 0 ; i < width ; i++ )
		for ( int j = 0 ; j < height ; j++) 
			dest[j * lineByte + i] = src1[j * lineByte + i] * src2[j* lineByte + i];
}

/***********************************************************************
* 函数名称:
* LocalMaximum()
*
*函数参数:
*  float * src  ,存放特征值的矩阵
* int width   矩阵的宽
* int height  矩阵的高
* int posx , 要判断的点的列坐标
* int posy , 要判断的点的行坐标
* int neiboursize , 邻域的大小
*返回值:
*  bool型,若是局部最大,返回真,否则返回假
*
*说明:判断点(posx,posy)的特征值,是否为局部极大值
***********************************************************************/
bool Register::LocalMaximum(float * src , int width , int height ,
							int posx , int posy , int neiboursize)
{
	int i,j;
	int lineByte=(width+3)/4*4;
	//判断是否为局部最大
	for ( i = -neiboursize/2 ; i <= neiboursize/2 ; i++)
		for ( j = -neiboursize/2 ; j <= neiboursize/2 ; j++)
		{
			if ( src[(posy + j) * lineByte + posx+i] > src[posy * lineByte + posx])
				return 0;
		}
		return 1;
}

/***********************************************************************
* 函数名称:
* SpaceSuppress()
*
*函数参数:
* ptArray * pCornerpos ,存放特征点的矩阵
*返回值:
*  无
*
*说明:将pCornerpos中相距小于距离阈值的点对剔除
***********************************************************************/
void Register::SpaceSuppress(ptArray * pCornerpos)
{
	int i,j;
	int length;
	//length特征点的个数
	length = pCornerpos->GetSize();
	CPoint pt1,pt2;
	//distancetable 存放两两特征点距离的数组
	double * distacetable = new double [length * length];
	//表识点对时小于距离阈值
	bool * marktable = new bool [length * length];
	memset( distacetable , 0 , sizeof(double) * length * length);
	memset( marktable , 0 , sizeof(bool) * length * length);
	
	for ( i = 0 ; i < length-1 ; i++) 
	{
		pt1 = pCornerpos->GetAt(i);
		for ( j = i+1 ; j < length ; j++)
		{
			pt2 = pCornerpos->GetAt(j);
			//求取距离
			distacetable[j * length + i] = sqrt(pow(pt1.x - pt2.x , 2)
				+ pow(pt1.y - pt2.y , 2));
			if ( distacetable[j* length + i] < m_space)
			{
				//表识距离小于阈值
				marktable[j * length + i] = 1;
			}
		}
	}
	//remove_num表示去除的点数
	int temp, remove_num=0;
	for ( i= 0 ; i < length-1 ; i++)
	{
		temp = 0;
		//判断是否由与其距离小于阈值的点
		for ( j = 0 ; j < length-1 ; j++)
		{
			temp += marktable[i * length + j];
		}
		if ( temp != 0)
		{ 
			//从特征点数组中剔除该点
			pCornerpos->RemoveAt( i - remove_num );
			remove_num++;
		}			
	}
	
	delete []distacetable;
	delete []marktable;
}
/***********************************************************************
* 函数名称:
* HarisConnerDetect()
*
*函数参数:
* unsigned char *imgBufIn, 待提取角点的图像数组
* int width, 图像的宽
* int height, 图像的高
* ptArray * pCornerpos ,存放特征点的矩阵
*返回值:
*  无
*
*说明:提取图像imgBfuIn的角点,存放于矩阵pCornerpos中
***********************************************************************/
void Register::HarisConnerDetect(unsigned char *imgBufIn, int width, 
								 int height, ptArray * pCornerpos)
{
	int imWidth = width;
	int imHeight = height;
	//图像模糊卷积模版
	float blur[7] = {1, 6 , 15 , 20 , 15 , 6 , 1}; 
	//滤波模版
	float prefilt[3] = { 0.223755 , 0.552490 , 0.223755 };
	//对图像求导模版
	float derivfilt[3] = { -0.453014 , 0 , 0.453014 };
	int lineByte=(imWidth*m_nBitCount1/8+3)/4*4;
	
	int i,j;
	////模板归一化(取均值)
	float sum=0;
	for ( i = 0 ; i < 7 ; i++ )
		sum += blur[i];
	for ( i = 0 ; i < 7 ; i++ )
		blur[i] /= sum;
    
	//fx 图像的一阶x方向导数 , fy 图像的一阶y方向导数
	float * fx = new float [lineByte * imHeight];
	float * fy = new float [lineByte * imHeight];
	//fx2每个像素值为fx对应像素值的平方
	float * fx2 = new float [lineByte * imHeight];
	//fy2每个像素值为fy对应像素值的平方
	float * fy2 = new float [lineByte * imHeight];
	//fxy=fx*fy
	float * fxy = new float [lineByte * imHeight];
	
    ///initiale
	for ( i =0 ; i < imWidth ; i++){
		for ( j = 0 ; j < imHeight ; j++){	
			fx[j * lineByte + i] = (float) imgBufIn[j * lineByte + i];
			fy[j * lineByte + i] = (float) imgBufIn[j * lineByte + i];
		}

⌨️ 快捷键说明

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