📄 morph.cpp
字号:
// ************************************************************************
// 文件名:Morph.cpp
//
// 数学形态学函数库:
//
// VErosion() - 对图象进行垂直腐蚀
// HErosion() - 对图象进行水平腐蚀
// VDilation() - 对图象进行垂直膨胀
// HDilation() - 对图象进行水平膨胀
// VHErosion() - 对图象进行全方向腐蚀
// VHDilation() - 对图象进行全方向膨胀
// OpenOperate() - 对图象进行开运算处理
// CloseOperate() - 对图象进行闭运算处理
// Thin() - 对图象进行细化处理
// Thick() - 对图象进行粗化处理
// MAT() - 对图象进行中轴变换
//
// ************************************************************************
#include "stdafx.h"
#include "dip_system.h"
#include "Morph.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMorph
CMorph::CMorph()
{
}
CMorph::~CMorph()
{
}
BEGIN_MESSAGE_MAP(CMorph, CWnd)
//{{AFX_MSG_MAP(CMorph)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMorph message handlers
/*************************************************************************
*
* 函数名称:
* VErosion()
*
* 参数:
* HDIB hDIB - 待处理的DIB
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数对图象进行垂直方向上的腐蚀
*
************************************************************************/
void CMorph::VErosion(HDIB hDIB)
{
//循环变量
LONG i;
LONG j;
LONG n;
// 指向DIB的指针
LPBYTE lpDIB;
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 指向源图像的指针
LPBYTE lpSrc;
// 指向缓存图像的指针
LPBYTE lpDst;
// 指向缓存DIB图像的指针
LPBYTE lpNewDIBBits;
HLOCAL hNewDIBBits;
// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB图像象素起始位置
lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
// 判断是否是24-bpp位图
if (m_clsDIB.DIBBitCount(lpDIB) != 24)
{
// 提示用户
MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回
return;
}
// 更改光标形状
BeginWaitCursor();
// DIB的宽度
LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
if (hNewDIBBits == NULL)
{
// 分配内存失败
return;
}
// 锁定内存
lpNewDIBBits = (LPBYTE)LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (LPBYTE)lpNewDIBBits;
memset(lpDst, (BYTE)255, lLineBytes * lHeight);
//使用垂直方向的结构元素进行腐蚀
for(i = 1; i < lHeight - 1; i++)
{
for(j = 0; j < lLineBytes; j += 3)
{
//由于使用3×1的结构元素,为防止越界,所以不处理最上边和最下边的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)(lpDIBBits + lLineBytes * i + j);
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (unsigned char *)(lpNewDIBBits + lLineBytes * i + j);
//目标图像中的当前点先赋成黑色
*lpDst = 0;
*(lpDst + 1) = 0;
*(lpDst + 2) = 0;
// 如果源图像中(0,-1)、(0,0)、(0,1)三个点之一有白点,
// 则将目标图像中的(0,0)点赋成白色
for (n = 0; n < 3; n++)
{
if (*(lpSrc + (n - 1) * lLineBytes) > 128)
{
*lpDst = 255;
*(lpDst + 1) = 255;
*(lpDst + 2) = 255;
break;
}
}
}
}
// 复制腐蚀后的图像
memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 恢复光标
EndWaitCursor();
}
/*************************************************************************
*
* 函数名称:
* HErosion()
*
* 参数:
* HDIB hDIB - 待处理的DIB
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数对图象进行水平方向上的腐蚀
*
************************************************************************/
void CMorph::HErosion(HDIB hDIB)
{
//循环变量
LONG i;
LONG j;
LONG n;
// 指向DIB的指针
LPBYTE lpDIB;
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 指向源图像的指针
LPBYTE lpSrc;
// 指向缓存图像的指针
LPBYTE lpDst;
// 指向缓存DIB图像的指针
LPBYTE lpNewDIBBits;
HLOCAL hNewDIBBits;
// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB图像象素起始位置
lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
// 判断是否是24-bpp位图
if (m_clsDIB.DIBBitCount(lpDIB) != 24)
{
// 提示用户
MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回
return;
}
// 更改光标形状
BeginWaitCursor();
// DIB的宽度
LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
if (hNewDIBBits == NULL)
{
// 分配内存失败
return;
}
// 锁定内存
lpNewDIBBits = (LPBYTE)LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (LPBYTE)lpNewDIBBits;
memset(lpDst, (BYTE)255, lLineBytes * lHeight);
// 使用水平方向的结构元素进行腐蚀
for (i = 0; i < lHeight; i++)
{
for (j = 3; j < lLineBytes - 3; j += 3)
{
// 由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)(lpDIBBits + lLineBytes * i + j);
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (unsigned char *)(lpNewDIBBits + lLineBytes * i + j);
// 目标图像中的当前点先赋成黑色
*lpDst = 0;
*(lpDst + 1) = 0;
*(lpDst + 2) = 0;
// 如果源图像中(-1,0)、(0,0)、(1,0)三个点之一有白点,
// 则将目标图像中的(0,0)点赋成白色
for (n = 0; n < 3; n++)
{
if (*(lpSrc + (n - 1) * 3) > 128)
{
*lpDst = 255;
*(lpDst + 1) = 255;
*(lpDst + 2) = 255;
break;
}
}
}
}
// 复制腐蚀后的图像
memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 恢复光标
EndWaitCursor();
}
/*************************************************************************
*
* 函数名称:
* VDilation()
*
* 参数:
* HDIB hDIB - 待处理的DIB
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数对图象进行垂直方向上的膨胀
*
************************************************************************/
void CMorph::VDilation(HDIB hDIB)
{
//循环变量
LONG i;
LONG j;
LONG n;
// 指向DIB的指针
LPBYTE lpDIB;
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 指向源图像的指针
LPBYTE lpSrc;
// 指向缓存图像的指针
LPBYTE lpDst;
// 指向缓存DIB图像的指针
LPBYTE lpNewDIBBits;
HLOCAL hNewDIBBits;
// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB图像象素起始位置
lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
// 判断是否是24-bpp位图
if (m_clsDIB.DIBBitCount(lpDIB) != 24)
{
// 提示用户
MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回
return;
}
// 更改光标形状
BeginWaitCursor();
// DIB的宽度
LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
if (hNewDIBBits == NULL)
{
// 分配内存失败
return;
}
// 锁定内存
lpNewDIBBits = (LPBYTE)LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (LPBYTE)lpNewDIBBits;
memset(lpDst, (BYTE)255, lLineBytes * lHeight);
//使用垂直方向的结构元素进行膨胀
for(i = 1; i < lHeight - 1; i++)
{
for(j = 0; j < lLineBytes; j += 3)
{
//由于使用3×1的结构元素,为防止越界,所以不处理最上边和最下边的两列像素
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)(lpDIBBits + lLineBytes * i + j);
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (unsigned char *)(lpNewDIBBits + lLineBytes * i + j);
//目标图像中的当前点先赋成白色
*lpDst = 255;
*(lpDst + 1) = 255;
*(lpDst + 2) = 255;
// 如果源图像中(0,-1)、(0,0)、(0,1)三个点之一有黑点,
// 则将目标图像中的(0,0)点赋成黑色
for (n = 0; n < 3; n++)
{
if (*(lpSrc + (n - 1) * lLineBytes) < 128)
{
*lpDst = 0;
*(lpDst + 1) = 0;
*(lpDst + 2) = 0;
break;
}
}
}
}
// 复制腐蚀后的图像
memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 恢复光标
EndWaitCursor();
}
/*************************************************************************
*
* 函数名称:
* HDilation()
*
* 参数:
* HDIB hDIB - 待处理的DIB
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数对图象进行水平方向上的膨胀
*
************************************************************************/
void CMorph::HDilation(HDIB hDIB)
{
//循环变量
LONG i;
LONG j;
LONG n;
// 指向DIB的指针
LPBYTE lpDIB;
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 指向源图像的指针
LPBYTE lpSrc;
// 指向缓存图像的指针
LPBYTE lpDst;
// 指向缓存DIB图像的指针
LPBYTE lpNewDIBBits;
HLOCAL hNewDIBBits;
// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB图像象素起始位置
lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
// 判断是否是24-bpp位图
if (m_clsDIB.DIBBitCount(lpDIB) != 24)
{
// 提示用户
MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回
return;
}
// 更改光标形状
BeginWaitCursor();
// DIB的宽度
LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
if (hNewDIBBits == NULL)
{
// 分配内存失败
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -