?? segapi.cpp
字號:
#include "GlobalApi.h"
#include "stdafx.h"
#include "cdib.h"
#include "math.h"
#include <direct.h>
#include <complex>
using namespace std;
/*************************************************************************
*
* \函數(shù)名稱:
* RegionSegFixThreshold()
*
* \輸入?yún)?shù):
* CDib * pDib - 指向CDib類的指針,含有原始圖象信息
* int nThreshold - 區(qū)域分割的閾值
*
* \返回值:
* 無
*
* \說明:
* 1(邏輯)表示對應象素為前景區(qū)域,0表示背景
* 閾值分割的關鍵問題在于閾值的選取。閾值的選取一般應該視實際的應用而
* 靈活設定。
*
*************************************************************************
*/
void RegionSegFixThreshold(CDib * pDib, int nThreshold)
{
//遍歷圖象的縱坐標
int y;
//遍歷圖象的橫坐標
int x;
//圖象的長寬大小
CSize sizeImage = pDib->GetDimensions();
int nWidth = sizeImage.cx ;
int nHeight = sizeImage.cy ;
//圖像在計算機在存儲中的實際大小
CSize sizeImageSave = pDib->GetDibSaveDim();
//圖像在內(nèi)存中每一行象素占用的實際空間
int nSaveWidth = sizeImageSave.cx;
//圖像數(shù)據(jù)的指針
LPBYTE pImageData = pDib->m_lpImage;
for(y=0; y<nHeight ; y++ )
for(x=0; x<nWidth ; x++ )
{
if( *(pImageData+y*nSaveWidth+x) < nThreshold)
*(pImageData+y*nSaveWidth+x) = 0;
}
}
/*************************************************************************
*
* \函數(shù)名稱:
* RegionSegAdaptive()
*
* \輸入?yún)?shù):
* CDib * pDib - 指向CDib類的指針,含有原始圖象信息
*
* \返回值:
* 無
*
* \說明:
* 1(邏輯)表示對應象素為前景區(qū)域,0表示背景
* 閾值分割的關鍵問題在于閾值的選取。閾值的選取一般應該視實際的應用而
* 靈活設定。本函數(shù)中,閾值不是固定的,而是根據(jù)圖象象素的實際性質(zhì)而設定的。
* 這個函數(shù)把圖像分成四個子圖象,然后計算每個子圖象的均值,根據(jù)均值設置閾值
* 閾值只是應用在對應的子圖象
*
*************************************************************************
*/
void RegionSegAdaptive(CDib * pDib)
{
//遍歷圖象的縱坐標
int y;
//遍歷圖象的橫坐標
int x;
//圖象的長寬大小
CSize sizeImage = pDib->GetDimensions();
int nWidth = sizeImage.cx ;
int nHeight = sizeImage.cy ;
//圖像在計算機在存儲中的實際大小
CSize sizeImageSave = pDib->GetDibSaveDim();
//圖像在內(nèi)存中每一行象素占用的實際空間
int nSaveWidth = sizeImageSave.cx;
//圖像數(shù)據(jù)的指針
LPBYTE lpImage = pDib->m_lpImage;
// 局部閾值
int nThd[2][2] ;
// 子圖象的平均值
int nLocAvg ;
// 對左上圖像逐點掃描:
nLocAvg = 0 ;
// y方向
for(y=0; y<nHeight/2 ; y++ )
{
// x方向
for(x=0; x<nWidth/2 ; x++ )
{
nLocAvg += lpImage[y*nSaveWidth + x];
}
}
// 計算均值
nLocAvg /= ( (nHeight/2) * (nWidth/2) ) ;
// 設置閾值為子圖象的平均值
nThd[0][0] = nLocAvg ;
// 對左上圖像逐點掃描進行分割:
// y方向
for(y=0; y<nHeight/2 ; y++ )
{
// x方向
for(x=0; x<nWidth/2 ; x++ )
{
if(lpImage[y*nSaveWidth + x]<nThd[0][0])
lpImage[y*nSaveWidth + x] = 255 ;
else
{
lpImage[y*nSaveWidth + x] = 0 ;
}
}
}
// =============================================
// 對左下圖像逐點掃描:
nLocAvg = 0 ;
// y方向
for(y=nHeight/2; y<nHeight ; y++ )
{
// x方向
for(x=0; x<nWidth/2 ; x++ )
{
nLocAvg += lpImage[y*nSaveWidth + x];
}
}
// 計算均值
nLocAvg /= ( (nHeight - nHeight/2) * (nWidth/2) ) ;
// 設置閾值為子圖象的平均值
nThd[1][0] = nLocAvg ;
// 對左下圖像逐點掃描進行分割:
// y方向
for(y=nHeight/2; y<nHeight ; y++ )
{
// x方向
for(x=0; x<nWidth/2 ; x++ )
{
if(lpImage[y*nSaveWidth + x]<nThd[1][0])
lpImage[y*nSaveWidth + x] = 255 ;
else
{
lpImage[y*nSaveWidth + x] = 0 ;
}
}
}
// =============================================
// 對右上圖像逐點掃描:
nLocAvg = 0 ;
// y方向
for(y=0; y<nHeight/2 ; y++ )
{
// x方向
for(x=nWidth/2; x<nWidth ; x++ )
{
nLocAvg += lpImage[y*nSaveWidth + x];
}
}
// 計算均值
nLocAvg /= ( (nHeight/2) * (nWidth - nWidth/2) ) ;
// 設置閾值為子圖象的平均值
nThd[0][1] = nLocAvg ;
// 對右上圖像逐點掃描進行分割:
// y方向
for(y=0; y<nHeight/2 ; y++ )
{
// x方向
for(x=nWidth/2; x<nWidth ; x++ )
{
if(lpImage[y*nSaveWidth + x]<nThd[0][1])
lpImage[y*nSaveWidth + x] = 255 ;
else
{
lpImage[y*nSaveWidth + x] = 0 ;
}
}
}
// =============================================
// 對右下圖像逐點掃描:
nLocAvg = 0 ;
// y方向
for(y=nHeight/2; y<nHeight ; y++ )
{
// x方向
for(x=nWidth/2; x<nWidth ; x++ )
{
nLocAvg += lpImage[y*nSaveWidth + x];
}
}
// 計算均值
nLocAvg /= ( (nHeight - nHeight/2) * (nWidth - nWidth/2) ) ;
// 設置閾值為子圖象的平均值
nThd[1][1] = nLocAvg ;
// 對右下圖像逐點掃描進行分割:
// y方向
for(y=nHeight/2; y<nHeight ; y++ )
{
// x方向
for(x=nWidth/2; x<nWidth ; x++ )
{
if(lpImage[y*nSaveWidth + x]<nThd[1][1])
lpImage[y*nSaveWidth + x] = 255 ;
else
{
lpImage[y*nSaveWidth + x] = 0 ;
}
}
}
// 為了顯示方便顯示,邏輯1用黑色顯示,邏輯0用白色顯示
for(y=0; y<nHeight ; y++ )
{
// x方向
for(x=0; x<nWidth ; x++ )
{
lpImage[y*nSaveWidth + x] = 255 - lpImage[y*nSaveWidth + x] ;
}
}
}
/*************************************************************************
*
* \函數(shù)名稱:
* RobertsOperator()
*
* \輸入?yún)?shù):
* CDib * pDib - 指向CDib類的指針,含有原始圖象信息
* double * pdGrad - 指向梯度數(shù)據(jù)的指針,含有圖像的梯度信息
*
* \返回值:
* 無
*
* \說明:
* Roberts算子
*
*************************************************************************
*/
void RobertsOperator(CDib * pDib, double * pdGrad)
{
// 遍歷圖象的縱坐標
int y;
// 遍歷圖象的橫坐標
int x;
// 圖象的長寬大小
CSize sizeImage = pDib->GetDimensions();
int nWidth = sizeImage.cx ;
int nHeight = sizeImage.cy ;
// 圖像在計算機在存儲中的實際大小
CSize sizeImageSave = pDib->GetDibSaveDim();
// 圖像在內(nèi)存中每一行象素占用的實際空間
int nSaveWidth = sizeImageSave.cx;
// 圖像數(shù)據(jù)的指針
LPBYTE pImageData = pDib->m_lpImage;
// 初始化
for(y=0; y<nHeight ; y++ )
for(x=0 ; x<nWidth ; x++ )
{
*(pdGrad+y*nWidth+x)=0;
}
// 下面開始利用Roberts算子進行計算,為了保證計算所需要的
// 的數(shù)據(jù)位于圖像數(shù)據(jù)的內(nèi)部,下面的兩重循環(huán)的條件是
// y<nHeight-1 而不是y<nHeight,相應的x方向也是x<nWidth-1
// 而不是x<nWidth
//這兩個變量用來表示Roberts算子第一個模板的兩個象素值
int nUpLeft;
int nDownRight;
// 這兩個變量用來表示Roberts算子第二個模板的兩個象素值
int nUpRight;
int nDownLeft;
// 這兩個變量用來表示Roberts算子計算的結果
int nValueOne;
int nValueTwo;
// 臨時變量
double dGrad;
for(y=0; y<nHeight-1 ; y++ )
for(x=0 ; x<nWidth-1 ; x++ )
{
// Roberts算子第一個模板需要的象素值
nUpLeft =*(pImageData+y*nSaveWidth+x) ;
nDownRight =*( pImageData+(y+1)*nSaveWidth+x+1 );
nDownRight *=-1;
//Roberts算子的第一個模板計算結果
nValueOne =nUpLeft+nDownRight ;
// Roberts算子第二個模板需要的象素值
nUpRight =*( pImageData+y*nSaveWidth+x+1 ) ;
nDownLeft =*( pImageData+(y+1)*nSaveWidth+x );
nDownLeft *=-1;
// Roberts算子的第二個模板計算結果
nValueTwo =nUpRight+nDownLeft;
// 計算兩個偏導數(shù)的平方和
dGrad=nValueOne*nValueOne + nValueTwo*nValueTwo;
// 開方
dGrad=pow(dGrad,0.5);
// 范數(shù)采用歐式距離
*(pdGrad+y*nWidth+x)=dGrad;
}
}
/*************************************************************************
*
* \函數(shù)名稱:
* LaplacianOperator()
*
* \輸入?yún)?shù):
* CDib * pDib - 指向CDib類的指針,含有原始圖象信息
* double * pdGrad - 指向梯度數(shù)據(jù)的指針,含有圖像的梯度信息
*
* \返回值:
* 無
*
* \說明:
* LaplacianOperator算子,是二階算子,不想Roberts算子那樣需要兩個模板計算
* 梯度,LaplacianOperator算子只要一個算子就可以計算梯度。但是因為利用了
* 二階信息,對噪聲比較敏感
*
*************************************************************************
*/
void LaplacianOperator(CDib * pDib, double * pdGrad)
{
// 遍歷圖象的縱坐標
int y;
// 遍歷圖象的橫坐標
int x;
// 圖象的長寬大小
CSize sizeImage = pDib->GetDimensions();
int nWidth = sizeImage.cx ;
int nHeight = sizeImage.cy ;
// 圖像在計算機在存儲中的實際大小
CSize sizeImageSave = pDib->GetDibSaveDim();
// 圖像在內(nèi)存中每一行象素占用的實際空間
int nSaveWidth = sizeImageSave.cx;
// 圖像數(shù)據(jù)的指針
LPBYTE lpImage = pDib->m_lpImage;
// 初始化
for(y=0; y<nHeight ; y++ )
for(x=0 ; x<nWidth ; x++ )
{
*(pdGrad+y*nWidth+x)=0;
}
// 設置模板系數(shù)
static int nWeight[3][3] ;
nWeight[0][0] = -1 ;
nWeight[0][1] = -1 ;
nWeight[0][2] = -1 ;
nWeight[1][0] = -1 ;
nWeight[1][1] = 8 ;
nWeight[1][2] = -1 ;
nWeight[2][0] = -1 ;
nWeight[2][1] = -1 ;
nWeight[2][2] = -1 ;
//這個變量用來表示Laplacian算子象素值
int nTmp[3][3];
// 臨時變量
double dGrad;
// 模板循環(huán)控制變量
int yy ;
int xx ;
// 下面開始利用Laplacian算子進行計算,為了保證計算所需要的
// 的數(shù)據(jù)位于圖像數(shù)據(jù)的內(nèi)部,下面的兩重循環(huán)的條件是
// y<nHeight-2 而不是y<nHeight,相應的x方向也是x<nWidth-2
// 而不是x<nWidth
for(y=1; y<nHeight-2 ; y++ )
for(x=1 ; x<nWidth-2 ; x++ )
{
dGrad = 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++)
{
dGrad += nTmp[yy][xx] * nWeight[yy][xx] ;
}
// 梯度值寫入內(nèi)存
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -