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

一,卷积的边缘问题

先看一幅图:
OpenCvSharp 学习笔记16 --处理边缘(BorderTypes)_第1张图片
定义了一个 ( 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 src The source image
OutputArray dst 输出图像;将具有与src相同的类型和大小size (src.cols+left+right,src.rows+top+bottom)
int top Specify 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 边缘处理
        /// 
        /// 图像边缘处理类型
        /// 
        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效果
OpenCvSharp 学习笔记16 --处理边缘(BorderTypes)_第2张图片
BorderTypes.Replicate效果
OpenCvSharp 学习笔记16 --处理边缘(BorderTypes)_第3张图片
BorderTypes.Wrap效果
OpenCvSharp 学习笔记16 --处理边缘(BorderTypes)_第4张图片
BorderTypes.Constant效果
OpenCvSharp 学习笔记16 --处理边缘(BorderTypes)_第5张图片

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

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

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

OpenCvSharp 学习笔记16 --处理边缘(BorderTypes)_第6张图片
上面的边缘处理没有指定边缘宽度,只是1个像素的变化我们看不出来而已。

你可能感兴趣的:(学习笔记)