?? bingxingbianjiedib.cpp
字號(hào):
#include "stdafx.h"
#include "windowsx.h"
#include "math.h"
#include "BingXingBianJieDib.h"
#include "MainFrm.h"
#include "DynSplitView2.h"
BingXingBianJieDib::BingXingBianJieDib()
{
}
BingXingBianJieDib::~BingXingBianJieDib()
{
}
///***************************************************************/
/*函數(shù)名稱:Lunkuotiqu()
/*函數(shù)類型:void
/*功能:對(duì)圖像進(jìn)行輪廓提取。
/***************************************************************/
void BingXingBianJieDib::Lunkuotiqu()
{
LPBYTE p_data ; //原圖數(shù)據(jù)區(qū)指針
int wide,height; //原圖長、寬
// 指向源圖像的指針
LPBYTE lpSrc;
// 指向緩存圖像的指針
LPBYTE lpDst;
// 指向緩存DIB圖像的指針
LPBYTE temp;
//循環(huán)變量
long i;
long j;
unsigned char n1,n2,n3,n4,n5,n6,n7,n8;
//像素值
unsigned char pixel;
// 暫時(shí)分配內(nèi)存,以保存新圖像
p_data=GetData();
wide=GetWidth();
height=GetHeight();
temp = new BYTE[wide * height];
for (j=0;j<height;j++)
{
for(i=0;i<wide;i++)
{
lpSrc = (LPBYTE)p_data + wide * j + i;
if(*lpSrc>127)
*lpSrc=255;
else
*lpSrc=0;
}
}
// 初始化新分配的內(nèi)存,設(shè)定初始值為255
memset(temp, 255, wide * height);
for(j = 1; j <height-1; j++)
{
for(i = 1;i <wide-1; i++)
{
// 指向源圖像倒數(shù)第j行,第i個(gè)象素的指針
lpSrc = (LPBYTE)p_data + wide * j + i;
// 指向目標(biāo)圖像倒數(shù)第j行,第i個(gè)象素的指針
lpDst = (LPBYTE)temp + wide * j + i;
//取得當(dāng)前指針處的像素值,注意要轉(zhuǎn)換為unsigned char型
pixel = (unsigned char)*lpSrc;
if(pixel == 0)
{
*lpDst = (unsigned char)0;
n1 = (unsigned char)*(lpSrc + wide -1);
n2 = (unsigned char)*(lpSrc + wide );
n3 = (unsigned char)*(lpSrc + wide +1);
n4 = (unsigned char)*(lpSrc -1);
n5= (unsigned char)*(lpSrc +1);
n6 = (unsigned char)*(lpSrc - wide -1);
n7 = (unsigned char)*(lpSrc - wide );
n8 = (unsigned char)*(lpSrc - wide +1);
//如果相鄰的八個(gè)點(diǎn)都是黑點(diǎn)
if(n1+n2+n3+n4+n5+n6+n7+n8==0)
{
*lpDst = (unsigned char)255;
}
}
}
}
// 復(fù)制腐蝕后的圖像
memcpy(p_data,temp, wide * height);
// 釋放內(nèi)存
delete temp;
}
///***************************************************************/
/*函數(shù)名稱:Diedaifazhi(int *tongji)
/*函數(shù)類型:void
/*參數(shù)說明:tonji ---直方圖灰度值統(tǒng)計(jì)
/*功能:對(duì)圖像進(jìn)行迭代閥值選取。
/***************************************************************/
void BingXingBianJieDib::Diedaifazhi(int *tongji)
{
// 循環(huán)變量
LONG i;
LONG j;
// 指向DIB象素指針
LPBYTE p_data;
// 找到DIB圖像象素起始位置
p_data = GetData();
// DIB的寬度
LONG wide = this->GetDibWidthBytes();
// DIB的高度
LONG height = this->GetHeight();
// 迭代閥值
int T1, T2;
T1 = 127;
T2 = 0;
// 臨時(shí)變量
int Temp0, Temp1, Temp2, Temp3;
Temp0 = Temp1 = Temp2 = Temp3 = 0;
while (true)
{
// 計(jì)算下一個(gè)迭代閥值
for (i = 0; i < T1 + 1; i++)
{
Temp0 += tongji[i] * i;
Temp1 += tongji[i];
}
for (i = T1 + 1; i < 256; i++)
{
Temp2 += tongji[i] * i;
Temp3 += tongji[i];
}
T2 = (Temp0 / Temp1 + Temp2 / Temp3) / 2;
// 看迭代結(jié)果是否已收斂
if (T1 == T2)
break;
else
T1 = T2;
}
// 對(duì)各像素進(jìn)行灰度轉(zhuǎn)換
for (j = 0; j < height; j ++)
{
for (i = 0; i < wide; i ++)
{
// 讀取像素
unsigned char temp = *((unsigned char *)p_data + wide * j + i);
// 判斷像素灰度值是否超出范圍
if (temp < T1)
temp = 0;
else
temp = 255;
// 回寫處理完的像素
*((unsigned char *)p_data + wide * j + i) = temp;
}
}
}
///***************************************************************/
/*函數(shù)名稱:Fenbutongji(int *tongji)
/*函數(shù)類型:void
/*參數(shù)說明:tonji ---直方圖灰度值統(tǒng)計(jì)
/*功能:對(duì)圖像進(jìn)行灰度值統(tǒng)計(jì)。
/***************************************************************/
void BingXingBianJieDib::Fenbutongji(int *tongji)
{
// 循環(huán)變量
LONG i;
LONG j;
//變量初始化
memset(tongji,0,sizeof(int) * 256);
// 指向DIB象素指針
LPBYTE p_data;
// 找到DIB圖像象素起始位置
p_data = this->GetData();
// DIB的寬度
LONG wide = GetDibWidthBytes();
// DIB的高度
LONG height = GetHeight();
// 對(duì)各像素進(jìn)行灰度轉(zhuǎn)換
for (j = 0; j < height; j ++)
{
for (i = 0; i <wide; i++)
{
// 對(duì)各像素進(jìn)行灰度統(tǒng)計(jì)
unsigned char temp = *((unsigned char *)p_data + wide * j + i);
tongji[temp]++;
}
}
}
///***************************************************************/
/*函數(shù)名稱:Lunkuogenzong()
/*函數(shù)類型:void
/*功能:對(duì)圖像進(jìn)行邊界跟蹤。
/***************************************************************/
void BingXingBianJieDib::Lunkuogenzong()
{
// 指向源圖像的指針
LPBYTE lpSrc;
LPBYTE p_data ;
// 指向緩存圖像的指針
LPBYTE lpDst;
// 指向緩存DIB圖像的指針
LPBYTE temp;
long wide;
long height;
//循環(huán)變量
long i;
long j;
//像素值
long pixel;
//是否找到起始點(diǎn)及回到起始點(diǎn)
bool bFindStartPoint;
//是否掃描到一個(gè)邊界點(diǎn)
bool bFindPoint;
//起始邊界點(diǎn)與當(dāng)前邊界點(diǎn)
Point StartPoint,CurrentPoint;
//八個(gè)方向和起始掃描方向
int Direction[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
int BeginDirect;
p_data=GetData();
if(m_pBitmapInfoHeader->biBitCount<9) //灰度圖像
{
wide=GetWidth();
height=GetHeight();
for (j=0;j<height;j++)
{
for(i=0;i<wide;i++)
{
lpSrc = (LPBYTE)p_data + wide * j + i;
if(*lpSrc>127)
*lpSrc=255;
else
*lpSrc=0;
}
}
// 暫時(shí)分配內(nèi)存,以保存新圖像
temp = new BYTE[wide*height];
// 初始化新分配的內(nèi)存,設(shè)定初始值為255
lpDst = temp;
memset(lpDst, (BYTE)255, wide * height);
//先找到最左上方的邊界點(diǎn)
bFindStartPoint = false;
for (j = 0;j < height && !bFindStartPoint;j++)
{
for(i = 0;i < wide && !bFindStartPoint;i++)
{
// 指向源圖像倒數(shù)第j行,第i個(gè)象素的指針
lpSrc = (LPBYTE)(p_data + wide * j + i);
//取得當(dāng)前指針處的像素值,注意要轉(zhuǎn)換為unsigned char型
pixel = *lpSrc;
if(pixel ==0)
{
bFindStartPoint = true;
StartPoint.Height = j;
StartPoint.Width = i;
// 指向目標(biāo)圖像倒數(shù)第j行,第i個(gè)象素的指針
lpDst = (LPBYTE)(temp + wide * j + i);
*lpDst = 0;
}
}
}
//由于起始點(diǎn)是在左下方,故起始掃描沿左上方向
BeginDirect = 0;
//跟蹤邊界
bFindStartPoint = false;
//從初始點(diǎn)開始掃描
CurrentPoint.Height = StartPoint.Height;
CurrentPoint.Width = StartPoint.Width;
while(!bFindStartPoint)
{
bFindPoint = false;
while(!bFindPoint)
{
//沿掃描方向查看一個(gè)像素
lpSrc = (LPBYTE)(p_data + wide * ( CurrentPoint.Height + Direction[BeginDirect][1])
+ (CurrentPoint.Width + Direction[BeginDirect][0]));
pixel = *lpSrc;
if(pixel== 0)
{
bFindPoint = true;
CurrentPoint.Height = CurrentPoint.Height + Direction[BeginDirect][1];
CurrentPoint.Width = CurrentPoint.Width + Direction[BeginDirect][0];
if(CurrentPoint.Height == StartPoint.Height && CurrentPoint.Width == StartPoint.Width)
{
bFindStartPoint = true;
}
lpDst = (LPBYTE)(temp + wide * CurrentPoint.Height + CurrentPoint.Width);
*lpDst = 0;
//掃描的方向逆時(shí)針旋轉(zhuǎn)兩格
BeginDirect--;
if(BeginDirect == -1)
BeginDirect = 7;
BeginDirect--;
if(BeginDirect == -1)
BeginDirect = 7;
}
else
{
//掃描方向順時(shí)針旋轉(zhuǎn)一格
BeginDirect++;
if(BeginDirect == 8)
BeginDirect = 0;
}
}
}
// 復(fù)制圖像
memcpy(p_data, temp, wide * height);
// 釋放內(nèi)存
delete temp;
}
}
///***************************************************************/
/*函數(shù)名稱:Zhongzitianchong(CPoint SeedPoint)
/*函數(shù)類型:void
/*參數(shù)說明:SeedPoint ---選區(qū)種子點(diǎn)
/*功能:對(duì)圖像進(jìn)行種子填充。
/***************************************************************/
void BingXingBianJieDib::Zhongzitianchong(CPoint SeedPoint)
{
// 指向源圖像的指針
LPBYTE lpSrc;
//圖像的高和寬
int height,wide ;
//像素值
long pixel;
//種子堆棧及指針
Seed *Seeds;
int StackPoint;
LPBYTE temp;
//當(dāng)前像素位置
int iCurrentPixelx,iCurrentPixely;
temp =this->GetData();
lpSrc=temp;
if(m_pBitmapInfoHeader->biBitCount<9) //灰度圖像
{
height=this->GetHeight();
wide=this->GetWidth();
for(int j=0;j<height;j++)
{
for(int i=0;i<wide;i++)
{
if(*lpSrc>110)
*lpSrc=255;
else
*lpSrc=0;
lpSrc++;
}
}
//初始化種子
Seeds = new Seed[wide*height];
Seeds[1].Height = SeedPoint.y;
Seeds[1].Width = SeedPoint.x;
StackPoint = 1;
while( StackPoint != 0)
{
//取出種子
iCurrentPixelx = Seeds[StackPoint].Width;
iCurrentPixely = Seeds[StackPoint].Height;
StackPoint--;
lpSrc = (LPBYTE)temp + wide * iCurrentPixely + iCurrentPixelx;
//取得當(dāng)前指針處的像素值,注意要轉(zhuǎn)換為unsigned char型
pixel = *lpSrc;
//將當(dāng)前點(diǎn)涂黑
*lpSrc =0;
//判斷左面的點(diǎn),如果為白,則壓入堆棧
//注意防止越界
if(iCurrentPixelx > 0)
{
lpSrc = (LPBYTE)temp + wide * iCurrentPixely + iCurrentPixelx - 1;
//取得當(dāng)前指針處的像素值,注意要轉(zhuǎn)換為unsigned char型
pixel = *lpSrc;
if (pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely;
Seeds[StackPoint].Width = iCurrentPixelx - 1;
}
}
//判斷上面的點(diǎn),如果為白,則壓入堆棧
//注意防止越界
if(iCurrentPixely < height - 1)
{
lpSrc = (LPBYTE)temp + wide * (iCurrentPixely + 1) + iCurrentPixelx;
//取得當(dāng)前指針處的像素值,注意要轉(zhuǎn)換為unsigned char型
pixel = *lpSrc;
if (pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely + 1;
Seeds[StackPoint].Width = iCurrentPixelx;
}
}
//判斷右面的點(diǎn),如果為白,則壓入堆棧
//注意防止越界
if(iCurrentPixelx < wide - 1)
{
lpSrc = (LPBYTE)temp + wide * iCurrentPixely + iCurrentPixelx + 1;
//取得當(dāng)前指針處的像素值,注意要轉(zhuǎn)換為unsigned char型
pixel = *lpSrc;
if (pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely;
Seeds[StackPoint].Width = iCurrentPixelx + 1;
}
}
//判斷下面的點(diǎn),如果為白,則壓入堆棧
//注意防止越界
if(iCurrentPixely > 0)
{
lpSrc = (LPBYTE)temp + wide * (iCurrentPixely - 1) + iCurrentPixelx;
//取得當(dāng)前指針處的像素值,注意要轉(zhuǎn)換為unsigned char型
pixel = *lpSrc;
if (pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely - 1;
Seeds[StackPoint].Width = iCurrentPixelx;
}
}
}
//釋放堆棧
delete Seeds;
}
else //24位彩色
{
height=this->GetHeight();
wide=this->GetDibWidthBytes();
//初始化種子
Seeds = new Seed[wide*height];
Seeds[1].Height = SeedPoint.y;
Seeds[1].Width = SeedPoint.x*3;
StackPoint = 1;
while( StackPoint != 0)
{
//取出種子
iCurrentPixelx = Seeds[StackPoint].Width;
iCurrentPixely = Seeds[StackPoint].Height;
StackPoint--;
lpSrc = (LPBYTE)temp + wide * iCurrentPixely + iCurrentPixelx;
//取得當(dāng)前指針處的像素值,注意要轉(zhuǎn)換為unsigned char型
pixel = *lpSrc;
//將當(dāng)前點(diǎn)涂黑
*lpSrc =0;
//判斷左面的點(diǎn),如果為白,則壓入堆棧
//注意防止越界
if(iCurrentPixelx > 0)
{
lpSrc = (LPBYTE)temp + wide * iCurrentPixely + iCurrentPixelx - 1;
//取得當(dāng)前指針處的像素值,注意要轉(zhuǎn)換為unsigned char型
pixel = *lpSrc;
if (pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely;
Seeds[StackPoint].Width = iCurrentPixelx - 1;
}
}
//判斷上面的點(diǎn),如果為白,則壓入堆棧
//注意防止越界
if(iCurrentPixely < height - 1)
{
lpSrc = (LPBYTE)temp + wide * (iCurrentPixely + 1) + iCurrentPixelx;
//取得當(dāng)前指針處的像素值,注意要轉(zhuǎn)換為unsigned char型
pixel = *lpSrc;
if (pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely + 1;
Seeds[StackPoint].Width = iCurrentPixelx;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -