📄 register.cpp
字号:
#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 + -