找回密码
 立即注册
查看: 176|回复: 0

图像处理 —— 膨胀(形态学)

[复制链接]
发表于 2022-5-28 11:00 | 显示全部楼层 |阅读模式
膨胀:对二值化物体边界点进行扩充,将与物体接触的所有背景点合并到该物体中,使边界向外部扩张。如果两个物体间隔较近,会将两物体连通在一起。对填补图像分割后物体的空洞有用。









膨胀效果图

<hr/>图像的膨胀,可分三种:水平膨胀、垂直膨胀、全方向膨胀。
水平膨胀:遍历目标图像中的目标区域,只考虑目标像素及其相邻的左右两个像素的灰度值,确认其与膨胀的结构元素是否有交点,即存在至少一处对应的灰度值相等。如果有交点,则处理该像素点。否则将该像素点删除。



水平膨胀所用的结构元素

源码如下:
void LevelInflation()
{
        BYTE* Temp;
        BYTE* p_data;
        p_data = this->GetData();
        int nWidth,nHeight;
        nWidth = this->GetWidth();
        nHeight = this->GetHeight();

        if (m_pBitmapInfoHeader->biBitCount < 9)
        {
                Temp = new BYTE[nWidth*nHeight];
                memset(Temp, (BYTE)255, nHeight*nWidth);  // 目标图像中的当前点先赋成白色
                for (int j = 0; j < nHeight; j++)
                {
                        for (int i = 1; i < nWidth - 1; i++)    // 由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边的两列像素
                        {
                                // 如果源图像中(-1,0)、(0,0)、(1,0)三个点之一有黑点,
                                // 则将目标图像中的(0,0)点赋成黑色
                                for(int m = 0; m < 3; m++)
                                {
                                        if (*(p_data+j*nWidth+i-1+m) < 128)
                                        {
                                                *(Temp+j*nWidth+i) = 0;
                                                break;
                                        }
                                }
                        }
                }
        }

        memcpy(p_data, Temp, nWidth*nHeight);
        delete Temp;
}实现效果:


https://www.zhihu.com/video/1443960175544053760
垂直膨胀:遍历目标图像中的目标区域,只考虑目标像素及其相邻的上下两个像素的灰度值,确认其与膨胀的结构元素是否有交点,即存在至少一处对应的灰度值相等。如果有交点,则处理该像素点。否则将该像素点删除。



垂直膨胀所用的结构元素

代码如下:
void VerticalInflation()
{
        BYTE* Temp;
        BYTE* p_data;
        p_data = this->GetData();
        int nWidth,nHeight;
        nWidth = this->GetWidth();
        nHeight = this->GetHeight();
        if (m_pBitmapInfoHeader->biBitCount < 9)
        {
                Temp = new BYTE[nWidth*nHeight];
                memset(Temp, (BYTE)255, nHeight*nWidth);  // 目标图像中的当前点先赋成白色
                for (int j = 1; j < nHeight-1; j++) // 由于使用1×3的结构元素,为防止越界,所以不处理最上边和最下边的两列像素
                {
                        for (int i = 0; i < nWidth; i++)   
                        {
                                // 如果源图像中上中下三个点之一有黑点,
                                // 则将目标图像中的(0,0)点赋成黑色
                                for(int m = 0; m < 3; m++)
                                {
                                        if (*(p_data+(j-1+m)*nWidth+i) < 128)
                                        {
                                                *(Temp+j*nWidth+i) = 0;
                                                break;
                                        }
                                }
                        }
                }
        }

        memcpy(p_data, Temp, nWidth*nHeight);
        delete Temp;
}实现效果:


https://www.zhihu.com/video/1443959858265923584
全方位膨胀:遍历目标图像中的目标区域,只考虑目标像素及其相邻的上下左右四个像素的灰度值,确认其与膨胀的结构元素是否有交点,即存在至少一处对应的灰度值相等。如果有交点,则处理该像素点。否则将该像素点删除。



全方向膨胀所有的结构元素

源码如下:
void DoubleInflation()
{
        BYTE* Temp;
        BYTE* p_data;
        p_data = this->GetData();
        int nWidth,nHeight;
        nWidth = this->GetWidth();
        nHeight = this->GetHeight();
        if (m_pBitmapInfoHeader->biBitCount < 9)
        {
                Temp = new BYTE[nWidth*nHeight];
                memset(Temp, (BYTE)255, nHeight*nWidth);  // 目标图像中的当前点先赋成白色
                for (int j = 1; j < nHeight-1; j++) // 为防止越界,所以不处理最上边,最左边,最右边和最下边的两列像素
                {
                        for (int i = 1; i < nWidth-1; i++)   
                        {
                                // 如果源图像中上,下,左,右四个点之一有黑点,
                                // 则将目标图像中的(0,0)点赋成黑色
                                //结构元素如下
                                // B[9]={0, 1, 0,
                                //       1, 0, 1,
                                //       0, 1, 0};
                                if (*(p_data+(j-1)*nWidth+i) < 128)
                                {
                                        *(Temp+j*nWidth+i) = 0;
                                        continue;
                                }
                                if (*(p_data+j*nWidth+i+1) < 128)
                                {
                                        *(Temp+j*nWidth+i) = 0;
                                        continue;
                                }
                                if (*(p_data+j*nWidth+i-1) < 128)
                                {
                                        *(Temp+j*nWidth+i) = 0;
                                        continue;
                                }
                                if (*(p_data+(j+1)*nWidth+i) < 128)
                                {
                                        *(Temp+j*nWidth+i) = 0;
                                        continue;
                                }
                        }
                }
        }

        memcpy(p_data, Temp, nWidth*nHeight);
        delete Temp;
}实现效果:


https://www.zhihu.com/video/1443960438211526656

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-10 12:47 , Processed in 0.092345 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表