📄 edgecontour.cpp
字号:
// 返回
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* Fill2DIB()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 种子填充成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用于对图像进行种子填充运算。
*
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL WINAPI Fill2DIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
// 指向源图像的指针
LPSTR lpSrc;
//循环变量
long i;
//像素值
unsigned char pixel;
//左右边界像素位置
int xl,xr;
//是否已填充至边界
BOOL bFilll,bFillr;
//种子堆栈及指针
Seed Seeds[10];
int StackPoint;
//当前像素位置
int iCurrentPixelx,iCurrentPixely;
int iBufferPixelx,iBufferPixely;
//初始化种子
Seeds[1].Height = lHeight / 2;
Seeds[1].Width = lWidth / 2;
StackPoint = 1;
while( StackPoint != 0)
{
//取出种子
iCurrentPixelx = Seeds[StackPoint].Width;
iCurrentPixely = Seeds[StackPoint].Height;
StackPoint--;
// if(Seed2.Height== 75)
// {
// return true;
// i++;
// }
bFilll = true;
bFillr = true;
//填充种子所在的行
//保存种子像素的位置
iBufferPixelx = iCurrentPixelx;
iBufferPixely = iCurrentPixely;
//先向左填充
while(bFilll)
{
lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned char)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if(pixel != 255 && pixel != 0)
return FALSE;
//遇到边界
if(pixel == 0)
{
bFilll = false;
xl=iCurrentPixelx+1;
}
else
{
*lpSrc = (unsigned char)0;
iCurrentPixelx--;
//防止越界
if(iCurrentPixelx<0)
{
bFilll = false;
iCurrentPixelx = 0;
xl = 0;
}
}
}
//再向右填充
//取回种子像素的位置
iCurrentPixelx = iBufferPixelx+1;
if(iCurrentPixelx>lWidth)
{
bFillr = false;
iCurrentPixelx = lWidth;
xr = lWidth;
}
iCurrentPixely = iBufferPixely;
while(bFillr)
{
lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned char)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if(pixel != 255 && pixel != 0)
return FALSE;
//遇到边界
if(pixel == 0)
{
bFillr = false;
xr=iCurrentPixelx-1;
}
else
{
*lpSrc = (unsigned char)0;
iCurrentPixelx++;
//防止越界
if(iCurrentPixelx>lWidth)
{
bFillr = false;
iCurrentPixelx = lWidth;
xr = lWidth;
}
}
}
//上、下两条扫描线是否全为边界象素或已填充过
//先看上面的扫描线
iCurrentPixely--;
if(iCurrentPixely < 0)
{
iCurrentPixely = 0;
}
for (i = xr; i>= xl;i--)
{
lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned char)*lpSrc;
//有未填充的像素,将新的种子压入堆栈
if (pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely;
Seeds[StackPoint].Width = i;
break;
}
}
//再看下面的扫描线
iCurrentPixely+=2;
if(iCurrentPixely > lHeight)
{
iCurrentPixely = lHeight;
}
for (i = xr; i>= xl;i--)
{
lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned char)*lpSrc;
//有未填充的像素,将新的种子压入堆栈
if (pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely;
Seeds[StackPoint].Width = i;
break;
}
}
}
// 返回
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* FillDIB()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 种子填充成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用于对图像进行种子填充运算。
*
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL WINAPI FillDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
// 指向源图像的指针
LPSTR lpSrc;
//像素值
unsigned char pixel;
//种子堆栈及指针
Seed *Seeds;
int StackPoint;
//当前像素位置
int iCurrentPixelx,iCurrentPixely;
//初始化种子
Seeds = new Seed[lWidth*lHeight];
Seeds[1].Height = lHeight / 2;
Seeds[1].Width = lWidth / 2;
StackPoint = 1;
while( StackPoint != 0)
{
//取出种子
iCurrentPixelx = Seeds[StackPoint].Width;
iCurrentPixely = Seeds[StackPoint].Height;
StackPoint--;
lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned char)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if(pixel != 255 && pixel != 0)
return FALSE;
//将当前点涂黑
*lpSrc = (unsigned char)0;
//判断左面的点,如果为白,则压入堆栈
//注意防止越界
if(iCurrentPixelx > 0)
{
lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx - 1;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned char)*lpSrc;
if (pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely;
Seeds[StackPoint].Width = iCurrentPixelx - 1;
}
//目标图像中含有0和255外的其它灰度值
if(pixel != 255 && pixel != 0)
return FALSE;
}
//判断上面的点,如果为白,则压入堆栈
//注意防止越界
if(iCurrentPixely < lHeight - 1)
{
lpSrc = (char *)lpDIBBits + lWidth * (iCurrentPixely + 1) + iCurrentPixelx;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned char)*lpSrc;
if (pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely + 1;
Seeds[StackPoint].Width = iCurrentPixelx;
}
//目标图像中含有0和255外的其它灰度值
if(pixel != 255 && pixel != 0)
return FALSE;
}
//判断右面的点,如果为白,则压入堆栈
//注意防止越界
if(iCurrentPixelx < lWidth - 1)
{
lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx + 1;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned char)*lpSrc;
if (pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely;
Seeds[StackPoint].Width = iCurrentPixelx + 1;
}
//目标图像中含有0和255外的其它灰度值
if(pixel != 255 && pixel != 0)
return FALSE;
}
//判断下面的点,如果为白,则压入堆栈
//注意防止越界
if(iCurrentPixely > 0)
{
lpSrc = (char *)lpDIBBits + lWidth * (iCurrentPixely - 1) + iCurrentPixelx;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned char)*lpSrc;
if (pixel == 255)
{
StackPoint++;
Seeds[StackPoint].Height = iCurrentPixely - 1;
Seeds[StackPoint].Width = iCurrentPixelx;
}
//目标图像中含有0和255外的其它灰度值
if(pixel != 255 && pixel != 0)
return FALSE;
}
}
//释放堆栈
delete Seeds;
// 返回
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* ContourDIB()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用于对图像进行轮廓提取运算。
*
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL WINAPI ContourDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
// 指向源图像的指针
LPSTR lpSrc;
// 指向缓存图像的指针
LPSTR lpDst;
// 指向缓存DIB图像的指针
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;
//循环变量
long i;
long j;
unsigned char n,e,s,w,ne,se,nw,sw;
//像素值
unsigned char pixel;
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if (hNewDIBBits == NULL)
{
// 分配内存失败
return FALSE;
}
// 锁定内存
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (char *)lpNewDIBBits;
memset(lpDst, (BYTE)255, lWidth * lHeight);
for(j = 1; j <lHeight-1; j++)
{
for(i = 1;i <lWidth-1; i++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lWidth * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lWidth * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned char)*lpSrc;
//目标图像中含有0和255外的其它灰度值
// if(pixel != 255 && pixel != 0)
// return FALSE;
if(pixel == 0)
{
*lpDst = (unsigned char)0;
nw = (unsigned char)*(lpSrc + lWidth -1);
n = (unsigned char)*(lpSrc + lWidth );
ne = (unsigned char)*(lpSrc + lWidth +1);
w = (unsigned char)*(lpSrc -1);
e = (unsigned char)*(lpSrc +1);
sw = (unsigned char)*(lpSrc - lWidth -1);
s = (unsigned char)*(lpSrc - lWidth );
se = (unsigned char)*(lpSrc - lWidth +1);
//如果相邻的八个点都是黑点
if(nw+n+ne+w+e+sw+s+se==0)
{
*lpDst = (unsigned char)255;
}
}
}
}
// 复制腐蚀后的图像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* TraceDIB()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用于对图像进行轮廓跟踪运算。
*
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL WINAPI TraceDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
// 指向源图像的指针
LPSTR lpSrc;
// 指向缓存图像的指针
LPSTR lpDst;
// 指向缓存DIB图像的指针
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;
// 图像每行的字节数
LONG lLineBytes;
//循环变量
long i;
long j;
//像素值
unsigned char pixel;
//是否找到起始点及回到起始点
bool bFindStartPoint;
//是否扫描到一个边界点
bool bFindPoint;
//起始边界点与当前边界点
Point StartPoint,CurrentPoint;
//八个方向和起始扫描方向
int Direction[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
int BeginDirect;
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
if (hNewDIBBits == NULL)
{
// 分配内存失败
return FALSE;
}
// 锁定内存
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (char *)lpNewDIBBits;
memset(lpDst, (BYTE)255, lLineBytes * lHeight);
//先找到最左上方的边界点
bFindStartPoint = false;
for (j = 0;j < lHeight && !bFindStartPoint;j++)
{
for(i = 0;i < lWidth && !bFindStartPoint;i++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned char)*lpSrc;
if(pixel == 0)
{
bFindStartPoint = true;
StartPoint.Height = j;
StartPoint.Width = i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
*lpDst = (unsigned char)0;
}
}
}
//由于起始点是在左下方,故起始扫描沿左上方向
BeginDirect = 0;
//跟踪边界
bFindStartPoint = false;
//从初始点开始扫描
CurrentPoint.Height = StartPoint.Height;
CurrentPoint.Width = StartPoint.Width;
while(!bFindStartPoint)
{
bFindPoint = false;
while(!bFindPoint)
{
//沿扫描方向查看一个像素
lpSrc = (char *)lpDIBBits + lLineBytes * ( CurrentPoint.Height + Direction[BeginDirect][1])
+ (CurrentPoint.Width + Direction[BeginDirect][0]);
pixel = (unsigned char)*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 = (char *)lpNewDIBBits + lLineBytes * CurrentPoint.Height + CurrentPoint.Width;
*lpDst = (unsigned char)0;
//扫描的方向逆时针旋转两格
BeginDirect--;
if(BeginDirect == -1)
BeginDirect = 7;
BeginDirect--;
if(BeginDirect == -1)
BeginDirect = 7;
}
else
{
//扫描方向顺时针旋转一格
BeginDirect++;
if(BeginDirect == 8)
BeginDirect = 0;
}
}
}
// 复制腐蚀后的图像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -