📄 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 + -