RISC-V MCU中文社区

【分享】 形态学操作—膨胀与腐蚀(Dilation and Erosion)

发表于 全国大学生集成电路创新创业大赛 2021-07-23 23:16:56
0
2140
0

    大家好,我们是大黄蜂队,编号是 CICC1948。上一篇分享贴(使用Otsu阈值算法将灰度图像二值化)讲解了将一个灰度图像作二值化的方法,那我们为什么要进行二值化这个操作呢?其一部分原因,就是我们要进行接下来的膨胀(Dilation)与腐蚀(Erosion)操作。

    膨胀是将与物体接触的全部背景点合并到该物体中,使边界向外部扩张的过程,能够用来填补物体中的空洞。物体膨胀前后的效果,就相当于物体在边界上向外扩张了一圈,因此膨胀操作也可以用于外扩物体的轮廓,以起到一些特殊的作用。而腐蚀则可以当作是膨胀的逆过程,相当于物体在边界上向内收缩了一圈。下图展示了对一个图像进行膨胀和腐蚀操作后的效果,中间的图像是操作之前的样子:


    除了对图象中物体产生的影响外,膨胀和腐蚀的操作也会对图像背景产生影响:当图像背景中存在白色噪点时,如果对图像进行腐蚀操作,则这些白色噪点就会被周围的黑色所“吞噬”掉,同时图片前景的物体轮廓也会被腐蚀一圈。如果这个时候再对图像作膨胀操作,此时由于白色的噪点已经不复存在了,所以只会表现为前景物体的轮廓扩大回了原来的尺寸。这样的操作我们称为“开操作”(Opening),这是一种消除图像背景白色噪点的有效方式。下图演示了对一副背景中存在白色噪点的图像进行开操作的效果,可以看到操作之后前景(白色字母)的轮廓并没有发生变化,但是图像背景中的白色噪点已经全部被消除了。



    当然,除了“开操作”之外,自然也存在“闭操作”(Closing)。闭操作是开操作的逆过程,他会先对图像进行膨胀操作,然后再进行腐蚀。当图像的前景中存在白色噪点时,闭操作是一种有效的去噪方式。下图演示了对一幅前景中存在黑色噪点的图像进行闭操作的效果:


    
    根据上面所演示的例子,其实我们对于形态学膨胀和腐蚀就可以有一个更加概括的理解:膨胀就是用图像中的白色来“侵蚀”黑色,腐蚀就是用图像中的黑色来“侵蚀”白色。当他们交替使用时,就可以在保证大块像素区域不变的前提下,消除图象中小的像素噪点。除此之外,如果只是单纯想要扩大或者收缩前景图像的边界,膨胀和腐蚀也可以成为一种有效的手段。

    最后,这里贴出一段用 C 语言实现膨胀的代码,供大家参考:


/**
 * @desc   图像指定区域取最大值(不判断是否超出边界)
 * @param  ppImg 输入图像(灰阶),
 * @param  x 当前像素坐标,
 * @param  y 当前像素坐标,
 * @param  pKernal 内核模版
 * @param  halfKernalW 内核模版宽度一半
 * @return 返回模版内最大值
 * **/
unsigned char getMaxPixelCenter(unsigned char **ppImg,int x,int y,
              int *pKernal,int kernalW,int halfKernalW){
    int i=0,j=0,x0=x,y0=y,x1,y1;
    unsigned char maxValue = 0x00;
    int *p = pKernal;

    x0 -= halfKernalW;
    y0 -= halfKernalW;

    for (i=0;i>1);

    int y,x;
    unsigned char *pImgOut = (unsigned char *)malloc(w*h);   //输出图像
    //方便处理,转成二维矩阵
    unsigned char** ppImgIn = create2DImg(pImgIn,w,h);
    unsigned char** ppImgOut = create2DImg(pImgOut,w,h);

    //Mode 2 先中间,后四个边处理
    for(y=halfKernalW;y ppImg[y1][x1])
                    minValue = ppImg[y1][x1];
            }
        }
    }

    return minValue;
}



void imgDilate(unsigned char *pImgIn,int w,int h){
    //内核大小为3
    int kernal[9] = {0,1,0,1,1,1,0,1,0};
    int kernalW = 3,halfKernalW = (3>>1);

    int y,x;
    unsigned char *pImgOut = (unsigned char *)malloc(w*h);   //输出图像
    //方便处理,转成二维矩阵
    unsigned char** ppImgIn = create2DImg(pImgIn,w,h);
    unsigned char** ppImgOut = create2DImg(pImgOut,w,h);
    for(y=0;y        for(x=0;x            ppImgOut[y][x] = getMaxPixelWhole(ppImgIn,x,y,w,h,kernal,kernalW,halfKernalW);
        } } }


喜欢0
用户评论
wxz

wxz 实名认证

懒的都不写签名

积分
问答
粉丝
关注
  • RV-STAR 开发板
  • RISC-V处理器设计系列课程
  • 培养RISC-V大学土壤 共建RISC-V教育生态
RV-STAR 开发板