一、导读
不知道大家在学习滤波的时候,有没有自己尝试去实现过一些简单的滤波;而在实现的过程中,有没有发现图像的边缘不知道该怎么处理,就像下面这样:
图像为灰度图。左为原图,右边为以大小为7的滤波核处理过的中值滤波图像,可以看到图像周围较之原图是多了一圈黑边的(因为我的输出Mat初值设为0)。
当滤波核的大小增大时,这种现象会更加明显。
原因是:
在处理过程中,处在边缘的像素点之外,没有足够的像素点构成一个滤波核的大小,所以只能够对其放弃处理,否则会报内存错误。
或许你会想,可以对于处于边界的元素的特殊情况进行特殊处理,但要针对四个边界的元素去写分支语句的话,是一件很麻烦的事。
所以,在这里我向大家推荐一个好的边缘处理办法,那就是 将边缘向外延伸。
二、边缘延伸方法
OpenCV中有已经写好的边缘延伸函数:
copyMakeBorder(Mat inputMat, Mat outputMat,
int width, int width, int width, int width,
BorderTypes BORDER_REPLICATE);
参数解析:
- inputMat:Mat类型,输入的图像矩阵,是需要被处理的图像
- outputMat:Mat类型,输出的图像矩阵,用于存储延伸边缘后的图像
- width:int类型,四个依次是上、下、左、右四个边缘应该被扩充的宽度(以像素为单位)
- BORDER_REPLICATE:BorderTypes(enum)型,除BORDER_REPLICATE外,还有BORDER_DEFAULT、BORDER_CONSTANT、BORDER_WRAP
四种类型具体效果如下:
左为原图,右为BORDER_REPLICATE延伸方式,可以看出,效果为原先最外围的像素平移向外扩展
左为原图,右为BORDER_DEFAULT延伸方式,效果为镜像填充
左为原图,右为BORDER_CONSTANT延伸方式,效果为纯色填充
左为原图,右为BORDER_WRAP延伸方式,效果为平铺填充。
如果想要效果更明显,各位可以自行尝试,将width增大。
三、滤波效果
以上添加边缘后,可以开始对图像进行滤波处理,滤波处理后,直接将原图部分选为感兴趣区域保留,增加的边缘去除掉,即完成滤波处理。
以下只给出BORDER_REPLICATE延伸方式后的均值滤波处理(因为个人对比后此方式效果最佳)
可以看出,较之原来没有了边缘的困扰~
四、结语
当然,在其他滤波方式下,可以根据情况选用合适的边缘延伸方式,比如均值滤波,使用BORDER_CONSTANT方式较好,因为黑色边缘对于原图边缘的均值滤波处理没有影响。