OpenCvSharp 学习笔记16 --处理边缘(BorderTypes)

一,卷积的边缘问题

先看一幅图:
在这里插入图片描述
定义了一个 ( 3 ∗ 3 ) (3 * 3) 33的卷积核在 源数据上进行卷积操作,源 上面的黄色部分为卷积核的开始位置,输出 上面的黄色部分为卷积核的结束部分,但是卷积核的中心点(锚点)覆盖不了源数据的四边的边缘值(如上图的锚点盲区,输出的红色部分)。
总结:
图像卷积的时候边界像素,不能被卷积操作,原因在于边界像素没有跟 kernel 完全重复或者没有被kernel 的锚点覆盖,所以当 ( 3 ∗ 3 ) (3 * 3) (33)滤波时,边缘有 1个像素没有被卷积处理, ( 5 ∗ 5 ) (5 * 5) (55)时就会有2个边缘像素没有被处理掉, ( 7 ∗ 7 ) (7 * 7) (77)就会有3个 … …

二,OpenCv的解决方法

在卷积开始之前增加边缘像素,填充的像素值为0 或者 RGB黑色,比如在 ( 3 ∗ 3 ) (3 * 3) (33)的四周各填充一个像素的边缘,这样就缺包图像的边缘被处理,在卷积之后再去掉这些边缘。opencv中默认的处理方法是:BorderTypes.Default ,除此之外常用的还有:

  1. BorderTypes.Constant;填充边缘用指定的像素值。
  2. BorderTypes.Replicate;填充边缘像素用已知的边缘像素值。
  3. BorderTypes.Wrap;用另一边的像素来补偿填充。

API :Cv2.CopyMakeBorder() ,在图像周围形成边框

参数说明
InputArray srcThe source image
OutputArray dst输出图像;将具有与src相同的类型和大小size (src.cols+left+right,src.rows+top+bottom)
int topSpecify how much pixels in each direction from the source image rectangle one needs to extrapolate (指定从源图像矩形每个方向需要推断多少像素)边缘长度,一般上下左右都取相同的值
int bottom同上
int left同上
int right同上
BorderTypes borderType边缘处理类型 (枚举类型)
Scalar? value = null颜色,默认是 null

三,代码

 #region 边缘处理
        /// <summary>
        /// 图像边缘处理类型
        /// </summary>
        private static void ImageEdgeProcessing(string path)
        {
            Mat src_Mat = new Mat(path, ImreadModes.AnyColor | ImreadModes.AnyDepth);
            Mat dst_Mat = new Mat();

            #region 边缘处理四个类型
            //定义四个方向像素,边缘宽度相对于源图像的 0.05
            int top = (int)(0.05 * src_Mat.Rows);
            int botton = (int)(0.05 * src_Mat.Rows);
            int left = (int)(0.05 * src_Mat.Cols);
            int right = (int)(0.05 * src_Mat.Cols);

            //定义随机数
            RNG r = new RNG(12345);
            //int borderType =(int) BorderTypes.Default;
            BorderTypes borderType = new BorderTypes();
            borderType = BorderTypes.Default;
            //Cv2.ImShow("src", src);
            int ch = 0;
            while (true)
            {
                ch = Cv2.WaitKey(500);
                if ((char)ch == 27)// ESC建退出
                {
                    break;
                }
                else if ((char)ch == 'r')
                {
                    borderType = BorderTypes.Replicate;//填充边缘像素用已知的边缘像素值
                }
                else if ((char)ch == 'w')
                {
                    borderType = BorderTypes.Wrap;//用另外一边的像素来补偿填充
                }
                else if ((char)ch == 'c')
                {
                    borderType = BorderTypes.Constant;//填充边缘用指定像素值
                }

                else if ((char)ch == 'd')
                {
                    borderType = BorderTypes.Default;//默认边缘处理
                }

                Scalar color = new Scalar(r.Uniform(0, 255), r.Uniform(0, 255), r.Uniform(0, 255));

                Cv2.CopyMakeBorder(src_Mat, dst_Mat, top, botton, left, right, borderType, color);
                Window w = new Window("dst", WindowMode.Normal);
                Cv2.ImShow("dst", dst_Mat);
            }
                #endregion
                //Cv2.GaussianBlur(src, dst, new Size(5, 5), 5, 5, BorderTypes.Wrap);

                //using (new Window("dst", WindowMode.Normal, dst_Mat))
                //{
                //    Cv2.WaitKey(0);
                //}
            
        }
        #endregion

BorderTypes.Default效果
在这里插入图片描述
BorderTypes.Replicate效果
在这里插入图片描述
BorderTypes.Wrap效果
在这里插入图片描述
BorderTypes.Constant效果
在这里插入图片描述

在进行模糊处理时也可以指定边缘处理类型

最后一个参数指定边缘处理类型

Cv2.GaussianBlur(src_Mat, dst_Mat, new Size(5, 5), 5, 5, BorderTypes.Wrap);

在这里插入图片描述
上面的边缘处理没有指定边缘宽度,只是1个像素的变化我们看不出来而已。

  • 2
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值