📄 imganalyse.cpp
字号:
//计算标定系数
*X_Scale = realSize/(x2-x1);
*Y_Scale = realSize/(y2-y1);
*XY_Scale = (float)sqrt((*X_Scale)*(*X_Scale) + (*Y_Scale)*(*Y_Scale));
}
////////////////////////////////////////////////////////////////////////
//函数:GetEdgePointNum()
//功能:获取边界点数
//返回:返回边界点数
////////////////////////////////////////////////////////////////////////
int CImgAnalyse::GetEdgePointNum()
{
return (TraceArray.GetSize());
}
////////////////////////////////////////////////////////////////////////
//函数:AreaByChain()
//功能:由边界链码计算区域面积
//返回:BOOL 计算正确则返回TRUE
////////////////////////////////////////////////////////////////////////
BOOL CImgAnalyse::AreaByChain(float *fArea)
{
//循环变量
int i;
//边界点结构体变量
EdgePoint m_EdgePoint;
//边界点数,即TraceArray的大小
int nNumNode;
//分别用于存储条件公式中X的增量和2α
//注意:由于边界跟踪的作用,各方向在数组中的顺序依次为
//左上方、上方、右上方、右方、右下方、下方、左下方、左方
//另外:TraceArray中存储的坐标与常用坐标相同,其原点在左下角,Y朝上
int DetaX[8] = {-1,0,1,1,1,0,-1,-1};
int Alfa[8] = {1,0,-1,0,1,0,-1,0};
float sum = 0.0f;
nNumNode = TraceArray.GetSize();
if(nNumNode<1)
{
AfxMessageBox("是否没有进行轮廓跟踪?\n请进行正确的轮廓跟踪!");
return FALSE;
}
for(i=0;i<nNumNode;i++)
{
//获取第i个结点的数据
m_EdgePoint = TraceArray.GetAt(i);
sum += m_EdgePoint.CurPoint.y*DetaX[m_EdgePoint.nCurVerct]+0.5f*Alfa[m_EdgePoint.nCurVerct];
}
//返回由边界链码计算的面积
*fArea = sum;
return (TRUE);
}
////////////////////////////////////////////////////////////
//函数:BOOL AreaByGreen(m_fXScale,m_fYScale,float *fArea)
//功能:利用格林公式求封闭轮廓内的面积,要利用边界点坐标
//参数:m_fXScale,m_fYScale分别为X和Y方向的标定系数
///////////////////////////////////////////////////////////
BOOL CImgAnalyse::AreaByGreen(float m_fXScale, float m_fYScale, float *fArea)
{
//循环变量
int i;
//边界点结构体变量
EdgePoint m_EdgePoint;
//边界点数,即TraceArray的大小
int nNumNode;
//当前点和下一点的坐标, 第一点的坐标
int nCurX,nCurY,nNextX,nNextY,nFirstX,nFirstY;
float sum = 0.0f;
nNumNode = TraceArray.GetSize();
if(nNumNode<1)
{
AfxMessageBox("是否没有进行轮廓跟踪?\n请进行正确的轮廓跟踪!");
return FALSE;
}
//获取第0个结点的数据
m_EdgePoint = TraceArray.GetAt(0);
nCurX = m_EdgePoint.CurPoint.x;
nCurY = m_EdgePoint.CurPoint.y;
nFirstX = nCurX;
nFirstY = nCurY;
for(i=1;i<nNumNode;i++)
{
//获取第i个结点的数据
m_EdgePoint = TraceArray.GetAt(i);
nNextX = m_EdgePoint.CurPoint.x;
nNextY = m_EdgePoint.CurPoint.y;
//对当前点与下一点的X和Y坐标的乘积和累加
sum += (nCurY*nNextX - nCurX*nNextY);
nCurX = nNextX;
nCurY = nNextY;
}
//加上最后一点与第0点的X和Y的乘积和
sum += (nNextY*nFirstX - nNextX*nFirstY);
//返回由边界坐标计算的面积
*fArea = (float)(0.5*m_fXScale*m_fYScale*sum);
return (TRUE);
}
////////////////////////////////////////////////////////////
//函数:BOOL PeriByChainCode()
//功能:由边界链码计算封闭区域的周长
//参数:分别为水平、垂直和斜方向的标定系数
////////////////////////////////////////////////////////////
BOOL CImgAnalyse::PeriByChainCode(float m_fXScale, float m_fYScale, float m_fXYScale, float *fP)
{
//水平、垂直、斜向链码数
int nHorNum = 0,nVerNum = 0,nDiaNum = 0;
//循环变量
int i;
//边界点结构体变量
EdgePoint m_EdgePoint;
//当前矢量方向,即链码方向
BYTE CurVerct;
//边界点数,即TraceArray的大小
int nNumNode;
nNumNode = TraceArray.GetSize();
if(nNumNode<1)
{
AfxMessageBox("是否没有进行轮廓跟踪?\n请进行正确的轮廓跟踪!");
return FALSE;
}
for(i=0;i<nNumNode;i++)
{
//获取第i个结点的数据
m_EdgePoint = TraceArray.GetAt(i);
CurVerct = m_EdgePoint.nCurVerct;
//水平方向链码数
if(CurVerct==0 || CurVerct==4)
nHorNum++;
//垂直方向链码数
else if(CurVerct==2 || CurVerct==6)
nVerNum++;
//斜向链码数
else
nDiaNum++;
}
//返回由边界链码计算的周长
*fP = (nHorNum*m_fXScale+nVerNum*m_fYScale+nDiaNum*m_fXYScale);
return (TRUE);
}
//////////////////////////////////////////////////////////////////
//函数:FourierFactor(int *nDimSize)
//功能:求傅立叶变换子
//参数:nDimSize int型指针,用于传递数组大小
//返回:double型 变换后的频域数据
double * CImgAnalyse::FourierFactor(int *nDimSize)
{
int j;
EdgePoint m_EdgePoint;
int nNumNode;
nNumNode = TraceArray.GetSize();
if(nNumNode<1)
{
AfxMessageBox("是否没有进行轮廓跟踪?\n请进行正确的轮廓跟踪!");
return NULL;
}
//用于传递数组大小
*nDimSize = nNumNode;
//初始化为一维矩阵
mFourier = zeros(1,nNumNode);
//转换为复数矩阵
mFourier = mcomplex(mFourier);
for(j=0;j<nNumNode;j++)
{
m_EdgePoint = TraceArray.GetAt(j);
//把X坐标赋予实部
mFourier.r(j+1) = m_EdgePoint.CurPoint.x;
//把Y坐标赋予虚部
mFourier.i(j+1) = m_EdgePoint.CurPoint.y;
}
//调用Matlab下的一维傅立叶变换函数
mFourier = fft(mFourier);
//求复数的模
mFourier = msqrt(dot_mul(real(mFourier),real(mFourier))+dot_mul(imag(mFourier),imag(mFourier)));
double * mdata;
mdata = new double[nNumNode];
memcpy(mdata, mFourier.addr(),nNumNode*sizeof(double));
return mdata;
}
//////////////////////////////////////////////////////////////
//函数:LabelArea(CDibObject *pDibObject)
//功能:对不同的连通成分作不同的标记,同时计算出区域面积和中心坐标
//说明:只对8位二值灰度图像(0和255两种值)有效,需经灰值化。
//参数:若pDibObject为空,则使用当前的图像对象。
//////////////////////////////////////////////////////////////
BOOL CImgAnalyse::LabelArea(CDibObject *pDibObject)
{
if(pDibObject!=NULL) m_pDibObject=pDibObject;
if(m_pDibObject==NULL) return(FALSE);
int nWidth,nHeight;
nWidth=m_pDibObject->GetWidth();
nHeight=m_pDibObject->GetHeight();
//当前像素的邻域方向数组
int direct[8][2]={{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};
int lx,ly;//当前点的邻点坐标
unsigned char *pOldBuffer;
unsigned char *pNewBuffer,*pNewBits,*pNewTemp;
int nWidthBytes, nNumColors, x, y, i, j, k;
HGLOBAL hNewDib;
pOldBuffer = (unsigned char *) m_pDibObject->GetDIBPointer( &nWidthBytes,m_pDibObject->GetNumBits());
if(pOldBuffer == NULL) return(FALSE);
nNumColors = m_pDibObject->GetNumColors();
//位图数据偏移量
DWORD offset=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumColors*sizeof(RGBQUAD);
//位图缓冲区大小
DWORD dwNewSize=offset+nHeight*nWidthBytes;
hNewDib=::GlobalAlloc(GHND,dwNewSize);
if(hNewDib==NULL){AfxMessageBox("Alloc memory error!");return FALSE;}
pNewBuffer=(unsigned char *)::GlobalLock(hNewDib);
if(pNewBuffer==NULL)
{
::GlobalFree(hNewDib);
AfxMessageBox("Lock memory error!");
return FALSE;
}
pNewBits=(unsigned char *)&pNewBuffer[offset];
memcpy(pNewBuffer,pOldBuffer,dwNewSize);
LabelArray.RemoveAll();
int label=100;//起始标记号
LabelResult m_LabelResult;//存放标记结果的结构体
int NumPixels;//区域面积
int xStart,yStart;//区域起始点
long cx,cy;//区域中心坐标
switch(m_pDibObject->GetNumBits())
{
case 8:
for(y=0;y<nHeight;y++)
{
pNewTemp=pNewBits;
pNewTemp+=y*nWidthBytes;
for(x=0;x<nWidth; x++)
{
if(pNewTemp[x]==255)
{
if(label>255){AfxMessageBox("标记太多!");return (FALSE);}
pNewTemp[x]=label;//赋予当前元素以标记号
int cnt=1;
xStart=x;/////////////
yStart=nHeight-1-y;/////////////
cx=xStart,cy=yStart;
NumPixels=1;
while(cnt)
{
cnt=0;//循环标记
for(j=0;j<nHeight;j++)
{
pNewTemp=pNewBits;
for(k=0;k<nWidth;k++)
{
if(pNewTemp[k+j*nWidthBytes]==label)//如果找到一个相同的记号
{
for(i=0;i<8;i++)
{
lx=k+direct[i][0];
ly=j+direct[i][1];
//判断是否超出图像边界
if(lx>=0 && lx<nWidth && ly>=0 && ly<nHeight)
//循环标记八邻域
if(*(pNewTemp+lx+ly*nWidthBytes)==255){
*(pNewTemp+lx+ly*nWidthBytes)=label;
NumPixels++;
cx+=lx;
cy+=nHeight-1-ly;
cnt++;}
}
}
}
}
}
if(NumPixels==0){cx=0;cy=0;}
else
{
cx=cx/NumPixels;cy=cy/NumPixels;
}
m_LabelResult.nLabelNo=label;
m_LabelResult.StartPoint.x=xStart;
m_LabelResult.StartPoint.y=yStart;
m_LabelResult.CenterPoint.x=cx;
m_LabelResult.CenterPoint.y=cy;
m_LabelResult.LabelArea=NumPixels;
LabelArray.Add(m_LabelResult);
label=label+1;
}
}
}
break;
}
if(label-100==0){::GlobalUnlock(hNewDib);::GlobalFree(hNewDib);return (FALSE);}
//将内存解锁和将不再使用的内存释放
::GlobalUnlock( m_pDibObject->GetDib());
::GlobalFree(m_pDibObject->GetDib());
::GlobalUnlock(hNewDib);
m_pDibObject->SetDib(hNewDib);
return( TRUE );
}
////////////////////////////////////////////////////////
//函数名称:GetCentroid()
//功 能:返回区域标记LabelArea()中计算的质心坐标
//参 数:无
//返 回:POINT
////////////////////////////////////////////////////////
POINT CImgAnalyse::GetCentroid()
{
//定义一个LabelResult类型的变量
LabelResult m_LabelResult;
POINT m_Center;
if(LabelArray.GetSize() > 0)
{
//把模板数组LabelArray的第一个元素的数据赋予变量m_LabelResult
m_LabelResult = LabelArray.GetAt(0);
m_Center = m_LabelResult.CenterPoint;
}
return (m_Center);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -