?? segapi.cpp
字號:
nWeight[1][1][2] = 0 ;
nWeight[1][2][0] = -1 ;
nWeight[1][2][1] = -1 ;
nWeight[1][2][2] = -1 ;
//這個變量用來表示Laplacian算子象素值
int nTmp[3][3];
// 臨時變量
double dGrad ;
double dGradOne;
double dGradTwo;
// 模板循環(huán)控制變量
int yy ;
int xx ;
// 下面開始利用Prewitt算子進行計算,為了保證計算所需要的
// 的數(shù)據(jù)位于圖像數(shù)據(jù)的內(nèi)部,下面的兩重循環(huán)的條件是
// y<nHeight-1 而不是y<nHeight,相應的x方向也是x<nWidth-1
// 而不是x<nWidth
for(y=1; y<nHeight-1 ; y++ )
for(x=1 ; x<nWidth-1 ; x++ )
{
dGrad = 0 ;
dGradOne = 0 ;
dGradTwo = 0 ;
// Laplacian算子需要的各點象素值
// 模板第一行
nTmp[0][0] = lpImage[(y-1)*nSaveWidth + x - 1 ] ;
nTmp[0][1] = lpImage[(y-1)*nSaveWidth + x ] ;
nTmp[0][2] = lpImage[(y-1)*nSaveWidth + x + 1 ] ;
// 模板第二行
nTmp[1][0] = lpImage[y*nSaveWidth + x - 1 ] ;
nTmp[1][1] = lpImage[y*nSaveWidth + x ] ;
nTmp[1][2] = lpImage[y*nSaveWidth + x + 1 ] ;
// 模板第三行
nTmp[2][0] = lpImage[(y+1)*nSaveWidth + x - 1 ] ;
nTmp[2][1] = lpImage[(y+1)*nSaveWidth + x ] ;
nTmp[2][2] = lpImage[(y+1)*nSaveWidth + x + 1 ] ;
// 計算梯度
for(yy=0; yy<3; yy++)
for(xx=0; xx<3; xx++)
{
dGradOne += nTmp[yy][xx] * nWeight[0][yy][xx] ;
dGradTwo += nTmp[yy][xx] * nWeight[1][yy][xx] ;
}
dGrad = dGradOne*dGradOne + dGradTwo*dGradTwo ;
dGrad = sqrt(dGrad) ;
// 梯度值寫入內(nèi)存
*(pdGrad+y*nWidth+x)=dGrad;
}
}
/*************************************************************************
*
* \函數(shù)名稱:
* EdgeTrack()
*
* \輸入?yún)?shù):
* CDib * pDib - 指向CDib類的指針,含有原始圖象信息
* unsigned char * pUnEdgeTrack - 指向邊界跟蹤結(jié)果的指針
*
* \返回值:
* 無
*
* \說明:
* pUnEdgeTrack指針指向的數(shù)據(jù)區(qū)存儲了邊界跟蹤的結(jié)果,其中1(邏輯)表示
* 對應象素為邊界點,0表示為非邊界點
*
* 串行邊界分割
*
*************************************************************************
*/
void EdgeTrack(CDib * pDib, unsigned char * pUnEdgeTrack)
{
static int nDx[8]={-1,-1,-1, 0, 0, 1, 1, 1};
static int nDy[8]={-1, 0, 1,-1, 1,-1, 0, 1};
// 遍歷圖象的縱坐標
int y;
// 遍歷圖象的橫坐標
int x;
// 圖象的長寬大小
CSize sizeImage = pDib->GetDimensions();
int nWidth = sizeImage.cx ;
int nHeight = sizeImage.cy ;
// 指向梯度數(shù)據(jù)的指針
double * pdGrad;
// 按照圖像的大小開辟內(nèi)存空間,存儲梯度計算的結(jié)果
pdGrad=new double[nHeight*nWidth];
// 調(diào)用Roberts算子求梯度
RobertsOperator(pDib, pdGrad);
// 定義當前象素梯度值
double dCurrGrad = 0;
// 定義最大梯度值
double dMaxGrad;
// 設(shè)置初值
dMaxGrad = 0;
// 最大梯度值對應的象素點坐標
int nPx;
int nPy;
nPx = 0;
nPy = 0;
// 求梯度最大值所在的象素點坐標
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++)
{
dCurrGrad = pdGrad[y*nWidth + x] ;
if( dMaxGrad< dCurrGrad )
{
dMaxGrad = dCurrGrad;
nPx = x ;
nPy = y ;
}
}
}
// 初始化
memset(pUnEdgeTrack,0,sizeof(unsigned char)*nWidth*nHeight);
dCurrGrad = pdGrad[nPy*nWidth + nPx] ;
// 從(nPx,nPy)點開始進行邊界跟蹤
pUnEdgeTrack[nPy*nWidth + nPx] = 255 ;
// 循環(huán)變量,遍歷當前象素的8鄰域
int i ;
int yy;
int xx;
int nDetX;
int nDetY;
while(dCurrGrad>10)
{
// 設(shè)置當前點為邊界點
pUnEdgeTrack[nPy*nWidth + nPx] = 255 ;
dMaxGrad = 0 ;
for(i=0; i<8; i++)
{
nDetX=nDx[i];
nDetY=nDy[i];
y = nPy + nDetY;
x = nPx + nDetX;
// 判斷是否在圖像內(nèi)部
if(x>=0 && x<nWidth && y>=0 && y<nHeight)
{
if( ( pdGrad[y*nWidth + x] > dMaxGrad) && ( pUnEdgeTrack[y*nWidth + x] == 0) )
{
dMaxGrad = pdGrad[y*nWidth + x] ;
yy = y;
xx = x;
}
}
}
// 下一個邊界點的梯度,橫縱坐標
dCurrGrad = dMaxGrad ;
nPy = yy;
nPx = xx;
}
//釋放內(nèi)存
delete pdGrad;
pdGrad = NULL;
}
/*************************************************************************
*
* \函數(shù)名稱:
* MakeGauss()
*
* \輸入?yún)?shù):
* double sigma - 高斯函數(shù)的標準差
* double **pdKernel - 指向高斯數(shù)據(jù)數(shù)組的指針
* int *pnWindowSize - 數(shù)據(jù)的長度
*
* \返回值:
* 無
*
* \說明:
* 這個函數(shù)可以生成一個一維的高斯函數(shù)的數(shù)字數(shù)據(jù),理論上高斯數(shù)據(jù)的長度應
* 該是無限長的,但是為了計算的簡單和速度,實際的高斯數(shù)據(jù)只能是有限長的
* pnWindowSize就是數(shù)據(jù)長度
*
*************************************************************************
*/
void MakeGauss(double sigma, double **pdKernel, int *pnWindowSize)
{
// 循環(huán)控制變量
int i ;
// 數(shù)組的中心點
int nCenter;
// 數(shù)組的某一點到中心點的距離
double dDis ;
double PI = 3.14159;
// 中間變量
double dValue;
double dSum ;
dSum = 0 ;
// 數(shù)組長度,根據(jù)概率論的知識,選取[-3*sigma, 3*sigma]以內(nèi)的數(shù)據(jù)。
// 這些數(shù)據(jù)會覆蓋絕大部分的濾波系數(shù)
*pnWindowSize = 1 + 2 * ceil(3 * sigma);
// 中心
nCenter = (*pnWindowSize) / 2;
// 分配內(nèi)存
*pdKernel = new double[*pnWindowSize] ;
for(i=0; i< (*pnWindowSize); i++)
{
dDis = (double)(i - nCenter);
dValue = exp(-(1/2)*dDis*dDis/(sigma*sigma)) / (sqrt(2 * PI) * sigma );
(*pdKernel)[i] = dValue ;
dSum += dValue;
}
// 歸一化
for(i=0; i<(*pnWindowSize) ; i++)
{
(*pdKernel)[i] /= dSum;
}
}
/*************************************************************************
*
* \函數(shù)名稱:
* GaussianSmooth()
*
* \輸入?yún)?shù):
* unsigned char * pUnchImg - 指向圖象數(shù)據(jù)的指針
* int nWidth - 圖象數(shù)據(jù)寬度
* int nHeight - 圖象數(shù)據(jù)高度
* double dSigma - 高斯函數(shù)的標準差
* unsigned char * pUnchSmthdImg - 指向經(jīng)過平滑之后的圖象數(shù)據(jù)
*
* \返回值:
* 無
*
* \說明:
* 為了抑止噪聲,采用高斯濾波對圖象進行濾波,濾波先對x方向進行,然后對
* y方向進行。
*
*************************************************************************
*/
void GaussianSmooth(unsigned char *pUnchImg, int nWidth, int nHeight,
double sigma, unsigned char * pUnchSmthdImg)
{
// 循環(huán)控制變量
int y;
int x;
int i;
// 高斯濾波器的數(shù)組長度
int nWindowSize;
// 窗口長度的1/2
int nHalfLen;
// 一維高斯數(shù)據(jù)濾波器
double *pdKernel ;
// 高斯系數(shù)與圖象數(shù)據(jù)的點乘
double dDotMul ;
// 高斯濾波系數(shù)的總和
double dWeightSum ;
// 中間變量
double * pdTmp ;
// 分配內(nèi)存
pdTmp = new double[nWidth*nHeight];
// 產(chǎn)生一維高斯數(shù)據(jù)濾波器
// MakeGauss(sigma, &dKernel, &nWindowSize);
MakeGauss(sigma, &pdKernel, &nWindowSize) ;
// MakeGauss返回窗口的長度,利用此變量計算窗口的半長
nHalfLen = nWindowSize / 2;
// x方向進行濾波
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++)
{
dDotMul = 0;
dWeightSum = 0;
for(i=(-nHalfLen); i<=nHalfLen; i++)
{
// 判斷是否在圖象內(nèi)部
if( (i+x) >= 0 && (i+x) < nWidth )
{
dDotMul += (double)pUnchImg[y*nWidth + (i+x)] * pdKernel[nHalfLen+i];
dWeightSum += pdKernel[nHalfLen+i];
}
}
pdTmp[y*nWidth + x] = dDotMul/dWeightSum ;
}
}
// y方向進行濾波
for(x=0; x<nWidth; x++)
{
for(y=0; y<nHeight; y++)
{
dDotMul = 0;
dWeightSum = 0;
for(i=(-nHalfLen); i<=nHalfLen; i++)
{
// 判斷是否在圖象內(nèi)部
if( (i+y) >= 0 && (i+y) < nHeight )
{
dDotMul += (double)pdTmp[(y+i)*nWidth + x] * pdKernel[nHalfLen+i];
dWeightSum += pdKernel[nHalfLen+i];
}
}
pUnchSmthdImg[y*nWidth + x] = (unsigned char)(int)dDotMul/dWeightSum ;
}
}
// 釋放內(nèi)存
delete []pdKernel;
pdKernel = NULL ;
delete []pdTmp;
pdTmp = NULL;
}
/*************************************************************************
*
* \函數(shù)名稱:
* DirGrad()
*
* \輸入?yún)?shù):
* unsigned char *pUnchSmthdImg - 經(jīng)過高斯濾波后的圖象
* int nWidht - 圖象寬度
* int nHeight - 圖象高度
* int *pnGradX - x方向的方向?qū)?shù)
* int *pnGradY - y方向的方向?qū)?shù)
* \返回值:
* 無
*
* \說明:
* 這個函數(shù)計算方向倒數(shù),采用的微分算子是(-1 0 1) 和 (-1 0 1)'(轉(zhuǎn)置)
* 計算的時候?qū)吔缦笏夭捎昧颂厥馓幚? *
*
*************************************************************************
*/
void DirGrad(unsigned char *pUnchSmthdImg, int nWidth, int nHeight,
int *pnGradX , int *pnGradY)
{
// 循環(huán)控制變量
int y ;
int x ;
// 計算x方向的方向?qū)?shù),在邊界出進行了處理,防止要訪問的象素出界
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++)
{
pnGradX[y*nWidth+x] = (int) ( pUnchSmthdImg[y*nWidth+min(nWidth-1,x+1)]
- pUnchSmthdImg[y*nWidth+max(0,x-1)] );
}
}
// 計算y方向的方向?qū)?shù),在邊界出進行了處理,防止要訪問的象素出界
for(x=0; x<nWidth; x++)
{
for(y=0; y<nHeight; y++)
{
pnGradY[y*nWidth+x] = (int) ( pUnchSmthdImg[min(nHeight-1,y+1)*nWidth + x]
- pUnchSmthdImg[max(0,y-1)*nWidth+ x ] );
}
}
}
/*************************************************************************
*
* \函數(shù)名稱:
* GradMagnitude()
*
* \輸入?yún)?shù):
* int *pnGradX - x方向的方向?qū)?shù)
* int *pnGradY - y方向的方向?qū)?shù)
* int nWidht - 圖象寬度
* int nHeight - 圖象高度
* int *pnMag - 梯度幅度
*
* \返回值:
* 無
*
* \說明:
* 這個函數(shù)利用方向倒數(shù)計算梯度幅度,方向倒數(shù)是DirGrad函數(shù)計算的結(jié)果
*
*************************************************************************
*/
void GradMagnitude(int *pnGradX, int *pnGradY, int nWidth, int nHeight, int *pnMag)
{
// 循環(huán)控制變量
int y ;
int x ;
// 中間變量
double dSqtOne;
double dSqtTwo;
for(y=0; y<nHeight; y++)
{
for(x=0; x<nWidth; x++)
{
dSqtOne = pnGradX[y*nWidth + x] * pnGradX[y*nWidth + x];
dSqtTwo = pnGradY[y*nWidth + x] * pnGradY[y*nWidth + x];
pnMag[y*nWidth + x] = (int)(sqrt(dSqtOne + dSqtTwo) + 0.5);
}
}
}
/*************************************************************************
*
* \函數(shù)名稱:
* NonmaxSuppress()
*
* \輸入?yún)?shù):
* int *pnMag - 梯度圖
* int *pnGradX - x方向的方向?qū)?shù)
* int *pnGradY - y方向的方向?qū)?shù)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -