www.gusucode.com > VC++图像分水岭分割算法控件及示例源代码-源码程序 > VC++图像分水岭分割算法控件及示例源代码-源码程序/code/MyMath.cpp

    //Download by http://www.NewXing.com
// MyMath.cpp: implementation of the MyMath class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "WaterShed.h"
#include "MyMath.h"
#include <MATH.H>

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

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

MyMath::MyMath()
{
	srand( (unsigned)time( NULL ) );
}

MyMath::~MyMath()
{

}

DOUBLE MyMath::LineDistance(My3DPoint inPoint1, My3DPoint inPoint2)
{
	DOUBLE tempoffx = inPoint1.x - inPoint2.x;
	DOUBLE tempoffy = inPoint1.y - inPoint2.y;
	DOUBLE tempoffh = inPoint1.h - inPoint2.h;

	return sqrt(tempoffx*tempoffx + tempoffy*tempoffy + 
		tempoffh*tempoffh);
}

DOUBLE MyMath::TriangleArea(My3DPoint inPoint1, 
	My3DPoint inPoint2, My3DPoint inPoint3)
{
	//计算边长;
	DOUBLE a = LineDistance(inPoint1, inPoint2);
	DOUBLE b = LineDistance(inPoint2, inPoint3);
	DOUBLE c = LineDistance(inPoint3, inPoint1);

	//计算周长的1/2;
	DOUBLE s = (a+b+c) / 2;

	//计算面积;
	return sqrt( s * (s-a) * (s-b) * (s-c) );
}

DOUBLE MyMath::TetrahedronVol(My3DPoint inPoint1,
		My3DPoint inPoint2, My3DPoint inPoint3,
		My3DPoint inPoint4)
{		
	//四面体体积;
	DOUBLE xa,ya,ha,xb,yb,hb,xc,yc,hc,xd,yd,hd;//四个点的三维坐标;
	xa = inPoint1.x;
	ya = inPoint1.y;
	ha = inPoint1.h;
	xb = inPoint2.x;
	yb = inPoint2.y;
	hb = inPoint2.h;
	xc = inPoint3.x;
	yc = inPoint3.y;
	hc = inPoint3.h;
	xd = inPoint4.x;
	yd = inPoint4.y;
	hd = inPoint4.h;

	//求消减后的矩阵;
	DOUBLE m11 = xb - xa;
	DOUBLE m12 = yb - ya;
	DOUBLE m13 = hb - ha;
	DOUBLE m21 = xc - xa;
	DOUBLE m22 = yc - ya;
	DOUBLE m23 = hc - ha;
	DOUBLE m31 = xd - xa;
	DOUBLE m32 = yd - ya;
	DOUBLE m33 = hd - ha;

	//求行列式;
	DOUBLE determinant = fabs ( m11 * (m22*m33 - m32*m23) -
		m21 * (m12*m33 - m32*m13) +
		m31 * (m12*m23 - m22*m13) );

	//返回体积;
    return determinant / 6;	
}

DOUBLE MyMath::PointLineDistance(My3DPoint point, My3DPoint linePt1, My3DPoint linePt2)
//点线距离;
{
	DOUBLE area = TriangleArea(point, linePt1, linePt2);
	DOUBLE edgelength = LineDistance(linePt1, linePt2);
	return area/edgelength * 2;
}

DOUBLE MyMath::PrismVol(My3DPoint upPoint1, My3DPoint upPoint2, 
		My3DPoint upPoint3,	My3DPoint downPoint1, 
		My3DPoint downPoint2, My3DPoint downPoint3)
//三棱柱体积;
{
	DOUBLE tetra1, tetra2, tetra3;//分割后的三个四面体体积;
	tetra1 = TetrahedronVol(downPoint1, downPoint2, 
		                    downPoint3, upPoint1);
	tetra2 = TetrahedronVol(upPoint1, upPoint2, 
		                    upPoint3, downPoint2);
	tetra3 = TetrahedronVol(upPoint1, upPoint3, 
		                    downPoint2, downPoint3);
	return tetra1 + tetra2 + tetra3;
}

BOOL  MyMath::GetBinAt(LONG inLong, INT inPos)
//输入一个整数,返回该数在inPos处的二进制值,inPos位置从右算起;
//由于此函数是为了用于证据理论的组合公式,故其性能不宜被普通的转换二进
//制函数调用,如需进行该种转换需要另写转换函数;
{
	LONG backin1 = inLong;
	LONG backin2 = backin1;

	for (int i=0; i<=inPos; i++)
	{
		backin1 = backin2;
		backin2 = backin1 / 2;	
	}

	if ( backin2*2 != backin1 )
	{
		return 1;
	}else
	{
		return 0;
	}
}

DOUBLE MyMath::Gaussian(DOUBLE inputx, DOUBLE mean, DOUBLE diff)
//计算高斯函数值;
{
	return exp( -1.0 * (inputx - mean) * (inputx - mean) / 
		( 2 * diff * diff) );
}

DOUBLE MyMath::GetARandom()
//得到一个介于0-1之间的双精度随机数;
{
	return  ( (DOUBLE)rand() / (DOUBLE)RAND_MAX );
}

void MyMath::RevertCopyMatrix(BYTE* inMatrix, INT width, BYTE* outMatrix, INT sita, INT mode)
//sita 0-4对应0,45,90和135,mode 0对应上-下,左-右
//mode 1对应下-上,右-左;输入必须为奇数阶方阵;
{
	INT pos = -1;
	INT replacepos = -1;
	if (sita==0)
	{
		if (mode==0)
		{
			//0度上-下
			INT tempi = INT ( width/2 );
			for (INT y=0; y<width; y++)
			{
				for (INT x=0; x<width; x++)
				{
					pos = y*width + x;
					if (y>tempi)
					{						
						replacepos = (width-y)*width + x;
						outMatrix[pos] = inMatrix[replacepos];
					}else
					{
						outMatrix[pos] = inMatrix[pos];
					}
				}
			}
		}else
		{
			//0度下-上
			INT tempi = INT ( width/2 );
			for (INT y=0; y<width; y++)
			{
				for (INT x=0; x<width; x++)
				{
					pos = y*width + x;
					if (y<tempi)
					{						
						replacepos = (width-y)*width + x;
						outMatrix[pos] = inMatrix[replacepos];
					}else
					{
						outMatrix[pos] = inMatrix[pos];
					}
				}
			}
		}
	}

	if (sita==1)
	{
		//45度
		if (mode==0)
		{
			//45度左-右
			for (INT y=0; y<width; y++)
			{
				for (INT x=0; x<width; x++)
				{
					pos = y*width + x;
					INT tempoff = abs( y - (width-x) );
					if (y>(width-x))
					{						
						replacepos = (y-tempoff)*width + (x-tempoff);
						outMatrix[pos] = inMatrix[replacepos];
					}else
					{
						outMatrix[pos] = inMatrix[pos];
					}
				}
			}
		}else
		{
			//45度右-左
			for (INT y=0; y<width; y++)
			{
				for (INT x=0; x<width; x++)
				{
					pos = y*width + x;
					INT tempoff = abs( y - (width-x) );
					if (y<(width-x))
					{						
						replacepos = (y+tempoff)*width + (x+tempoff);
						outMatrix[pos] = inMatrix[replacepos];
					}else
					{
						outMatrix[pos] = inMatrix[pos];
					}
				}
			}
		}
	}

	if (sita==2)
	{
		//90度
		if (mode==0)
		{
			//90度左-右
			INT tempi = INT ( width/2 );
			for (INT y=0; y<width; y++)
			{
				for (INT x=0; x<width; x++)
				{
					pos = y*width + x;
					if (x>tempi)
					{						
						replacepos = y*width + (width-x);
						outMatrix[pos] = inMatrix[replacepos];
					}else
					{
						outMatrix[pos] = inMatrix[pos];
					}
				}
			}
		}else
		{
			//90度右-左
			INT tempi = INT ( width/2 );
			for (INT y=0; y<width; y++)
			{
				for (INT x=0; x<width; x++)
				{
					pos = y*width + x;
					if (x<tempi)
					{						
						replacepos = y*width + (width-x);
						outMatrix[pos] = inMatrix[replacepos];
					}else
					{
						outMatrix[pos] = inMatrix[pos];
					}
				}
			}
		}
	}

	if (sita==3)
	{
		//135度
		if (mode==0)
		{
			//135度左-右
			for (INT y=0; y<width; y++)
			{
				for (INT x=0; x<width; x++)
				{
					pos = y*width + x;
					if (y>x)
					{
						//XY翻转;
						replacepos = x*width + y;
						outMatrix[pos] = inMatrix[replacepos];
					}else
					{
						outMatrix[pos] = inMatrix[pos];
					}
				}
			}
		}else
		{
			//135度右-左
			for (INT y=0; y<width; y++)
			{
				for (INT x=0; x<width; x++)
				{
					pos = y*width + x;
					if (y<x)
					{
						//XY翻转;
						replacepos = x*width + y;
						outMatrix[pos] = inMatrix[replacepos];
					}else
					{
						outMatrix[pos] = inMatrix[pos];
					}
				}
			}
		}
	}
}

FLOAT MyMath::CalcuMatrixMean(FLOAT* inMatrix, INT width, INT height)
//计算输入矩阵的平均值;
{
	INT count = width * height;
	FLOAT added = 0;

	for (INT pos=0; pos<count; pos++)
	{
		added += inMatrix[pos];
	}

	return added / (FLOAT)count;
}

INT MyMath::FindMaxInThree(DOUBLE inval1, DOUBLE inval2, DOUBLE inval3)
//找三个数中最大者,返回为最大者的序号,从0开始编号;
{
	if (inval1>inval2)
	{
		if (inval1>inval3)
		{
			return 0;
		}else
		{
			return 2;
		}
	}else
	{
		if (inval2>inval3)
		{
			return 1;
		}else
		{
			return 2;
		}
	}
}

DOUBLE MyMath::ReturnMinInThree(DOUBLE inval1, DOUBLE inval2, DOUBLE inval3)
//找三个数中最小者,并将其返回;
{
	if (inval1<inval2)
	{
		if (inval1<inval3)
		{
			return inval1;
		}else
		{
			return inval3;
		}
	}else
	{
		if (inval2<inval3)
		{
			return inval2;
		}else
		{
			return inval3;
		}
	}
}

DOUBLE MyMath::ReturnMaxInThree(DOUBLE inval1, DOUBLE inval2, DOUBLE inval3)
//找三个数中最大者,并将其返回;
{
	if (inval1>inval2)
	{
		if (inval1>inval3)
		{
			return inval1;
		}else
		{
			return inval3;
		}
	}else
	{
		if (inval2>inval3)
		{
			return inval2;
		}else
		{
			return inval3;
		}
	}
}

void MyMath::ClacuMean(DOUBLE* inData, LONG inNumber, FLOAT& outMean, FLOAT& outSerr)
//计算输入数组的均值与方差;
{
	DOUBLE total = 0;
	//计算均值;
	for (INT i=0; i<inNumber; i++)
	{
		total += inData[i];
	}
	outMean = (FLOAT) ( total / (FLOAT)inNumber );

	//计算方差;
	total = 0;
	for (i=0; i<inNumber; i++)
	{
		total += (inData[i] - outMean) * (inData[i] - outMean);
	}
	total = total / (DOUBLE)inNumber;//误差平方和的期望;
	outSerr = (FLOAT) ( sqrt(total) );//标准差;
}

void MyMath::ClacuMeanPositive(FLOAT* inData, LONG inNumber, FLOAT& outMean, FLOAT& outSerr)
//计算输入数组的均值与方差,只计算正值元素;
{
	FLOAT total = 0;
	FLOAT count = 0;
	//计算均值;
	for (INT i=0; i<inNumber; i++)
	{
		if (inData[i]>0)
		{
			total += inData[i];
			count++;
		}
		
	}

	outMean = (FLOAT) ( total / (FLOAT)count );

	//计算方差;
	total = 0;
	for (i=0; i<inNumber; i++)
	{
		if (inData[i]>0)
		{
			total += (inData[i] - outMean) 
				* (inData[i] - outMean);
		}		
	}

	total = (FLOAT) ( total / (FLOAT)count );//误差平方和的期望;
	outSerr = (FLOAT) ( sqrt(total) );//标准差;
}

BOOL MyMath::isOdd(INT inInt)
//是否奇数;
{
	INT tempi = (INT) (inInt/2);
	if (tempi*2 == inInt)
	{
		//偶数;
		return FALSE;
	}

	//奇数;
	return TRUE;
}

/*******************************************************************************
* 函数名称:GetMaxValue()
*
* 参数:    BYTE* pWinValue    -- 指向数组的指针
*           int nWinLength     -- 数组的长度
*
* 返回值:  BYTE               -- 数组的最大值
*
* 说明:    该函数用于得到一个数组的最大值,由函数 LocalThresholding() 调用。
********************************************************************************/

BYTE MyMath::GetMaxValue(BYTE* pWinValue,int nWinLength)
{
	int i;    // 循环变量
	BYTE Tmp = 0; // 临时变量
    for(i=0;i<nWinLength;i++)
	{
		if(pWinValue[i] > Tmp)
		{
			Tmp = pWinValue[i];
		}
	}
	return Tmp;
}

/*******************************************************************************
* 函数名称:GetMinValue()
*
* 参数:    BYTE* pWinValue    -- 指向数组的指针
*           int nWinLength     -- 数组的长度
*
* 返回值:  BYTE               -- 数组的最小值
*
* 说明:    该函数用于得到一个数组的最小值,由函数 LocalThresholding() 调用。
********************************************************************************/

BYTE MyMath::GetMinValue(BYTE* pWinValue,int nWinLength)
{
	int i;    // 循环变量
	BYTE Tmp = 255; // 临时变量
    for(i=0;i<nWinLength;i++)
	{
		if(pWinValue[i] < Tmp)
		{
			Tmp = pWinValue[i];
		}
	}

	return Tmp;
}

/*******************************************************************************
* 函数名称:GetAveValue()
*
* 参数:    BYTE* pWinValue    -- 指向数组的指针
*           int nWinLength     -- 数组的长度
*
* 返回值:  BYTE               -- 数组的均值
*
* 说明:    该函数用于得到一个数组内非0数的均值,由函数 LocalThresholding() 调用。
********************************************************************************/

BYTE MyMath::GetAveValue(BYTE* pWinValue,int nWinLength)
{
	int i;    // 循环变量
	int nNonZeroNum = 0;  // 非0的数目
	int nTotal = 0;       // 临时变量,数值之和
	BYTE Average;
	double dAverage;
    for(i=0;i<nWinLength;i++)
	{
		if(pWinValue[i] != 0)
		{
			nTotal += pWinValue[i];
			nNonZeroNum++;
		}
	}
	dAverage = (double)nTotal/nNonZeroNum;
	if(dAverage - (int)dAverage != 0.0)
	{
		Average = (int)dAverage + 1;
	}
	else
	{
		Average = (int)dAverage;
	}

	return Average;
}

void MyMath::QickSort(FLOAT* inArr, LONG inNum)
//快速排序;
{
	qsort( inArr, inNum, sizeof(FLOAT), CompareFloat );
}

void MyMath::QickSort(MyImageGraPt* inArr, LONG inNum)
//按梯度值及空间顺序对各点排序;
{
    qsort( inArr, inNum, sizeof(MyImageGraPt), CompareGraPt );
}

void MyMath::QickSortInver(MyImageGraPt* inArr, LONG inNum)
//按梯度值及空间逆序对各点排序;
{
    qsort( inArr, inNum, sizeof(MyImageGraPt), CompareGraPtInver );
}

int CompareFloat( const void* in1, const void* in2 )
//比较;
{
	FLOAT tempf = *((FLOAT*)in1) - *((FLOAT*)in2);

	if (tempf==0)
	{
		return 0;
	}	
	return (INT) (tempf/fabs(tempf));
}

int CompareGraPt( const void* in1, const void* in2 )
//比较梯度;
{
	MyImageGraPt pt1, pt2;
	pt1 = *((MyImageGraPt*)in1);
	pt2 = *((MyImageGraPt*)in2);
	FLOAT tempf = (FLOAT) ( pt1.gradient - pt2.gradient );
	FLOAT tempx = (FLOAT) ( pt1.x - pt2.x );
	FLOAT tempy = (FLOAT) ( pt1.y - pt2.y );

	//如果梯度值一样,则按照空间位置排序;
	if (tempf==0)
	{
		if (tempy==0)
		{
			if (tempx==0)
			{
				return 0;
			}else
			{
				tempf = tempx;
			}
		}else
		{
			tempf = tempy;
		}
	}
	
	INT tempi = (INT) (tempf/fabs(tempf));
	return tempi;
}

int CompareGraPtInver( const void* in1, const void* in2 )
//比较梯度;
{
	MyImageGraPt pt1, pt2;
	pt1 = *((MyImageGraPt*)in1);
	pt2 = *((MyImageGraPt*)in2);
	FLOAT tempf = (FLOAT) ( pt1.gradient - pt2.gradient );
	FLOAT tempx = (FLOAT) ( pt1.x - pt2.x );
	FLOAT tempy = (FLOAT) ( pt1.y - pt2.y );

	//如果梯度值一样,则按照空间位置反向排序;
	if (tempf==0)
	{
		if (tempx==0)
		{
			if (tempy==0)
			{
				return 0;
			}else
			{
				tempf = -tempy;//空间位置反向排序;
			}
		}else
		{
			tempf = -tempx;//空间位置反向排序;
		}
	}

	INT tempi = (INT) (tempf/fabs(tempf));
	return tempi;
}

void MyMath::GetNeiInt(INT posx, INT posy, INT currentpos, INT width, INT height
		, INT& left, INT& right, INT& up, INT& down)
//在矩阵中找pos的四个邻域;
{
	//INT curpos = posy*width + posx;
	if ( posx-1 >= 0 )
	{
		left = currentpos - 1;
	}else
	{
		left = -1;
	}

	if ( posx+1 < width)
	{
		right = currentpos + 1;
	}else
	{
		right = -1;
	}

	if ( posy-1 >= 0 )
	{
		up = currentpos - width;
	}else
	{
		up = -1;
	}

	if ( posy+1 < height )
	{
		down = currentpos + width;
	}else
	{
		down = -1;
	}
}