OpenCV学习 day9 自定义线性滤波 图像边缘处理 边缘算子

自定义滤波器

代码演示:

//Sboel算子
Mat kernel_x = (Mat_<int>(3, 3) << -1, 0, 1, -2, 0, 2, -1 ,0, 1);  //X方向
Mat kernel_y = (Mat_<int>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);  //Y方向
    
filter2D(src, dst, -1, kernel_x, Point(-1, -1), 0.0);

 

自定义高斯滤波

// 5*5大小的高斯核
Mat kernel = Mat::ones(Size(5, 5), CV_32F) / (float)(5* 5);
filter2D(src, dst, -1, kernel, Point(-1, -1));

 

 

边缘处理

在卷积开始之前增加边缘像素,填充的像素值为0或者RGB黑色,比如3x3在四周各填充1个像素的边缘,这样就确保图像的边缘被处理,在卷积处理之后再去掉这些边缘。

openCV中默认的处理方法是: BORDER_DEFAULT,

此外常用的还有如下几种:
- BORDER_CONSTANT – 填充边缘用指定像素值
- BORDER_REPLICATE – 填充边缘像素用已知的边缘像素值。
- BORDER_WRAP – 用另外一边的像素来补偿填充

 

API:

copyMakeBorder(
 - Mat src, // 输入图像
 - Mat dst, // 添加边缘图像
 - int top, // 边缘填充长度,一般上下左右都取相同值,
 - int bottom,
 - int left,
 - int right, 
 - int borderType // 边缘类型
 - Scalar value 
)

几种填充类型:

enum BorderTypes {
    BORDER_CONSTANT    = 0, //常值填充
    BORDER_REPLICATE   = 1, //原图边缘复制
    BORDER_REFLECT     = 2, //
    BORDER_WRAP        = 3, //原图的另一边复制到这边
    BORDER_REFLECT_101 = 4, //
    BORDER_TRANSPARENT = 5, //

    BORDER_REFLECT101  = BORDER_REFLECT_101, //
    BORDER_DEFAULT     = BORDER_REFLECT_101, //
    BORDER_ISOLATED    = 16 //
};

 

边缘算子

如下图所示,相邻像素之间发生较大改变时,它它们方向上的导数值也会很大

OpenCV学习 day9 自定义线性滤波 图像边缘处理 边缘算子

 

 

Sobel算子

是离散微分算子(discrete differentiation operator),用来计算图像灰度的近似梯度

Soble算子功能集合高斯平滑和微分求导

又被称为一阶微分算子,求导算子,在水平和垂直两个方向上求导,得到图像X方向与Y方向梯度图像

OpenCV学习 day9 自定义线性滤波 图像边缘处理 边缘算子

 

opencv中使用改进版Scharr的算子如下:

OpenCV学习 day9 自定义线性滤波 图像边缘处理 边缘算子

 

 API:

cv::Sobel (
InputArray Src // 输入图像
OutputArray dst// 输出图像,大小与输入图像一致
int depth // 输出图像深度. 通常深度比输入图像要高 防止像素值被截断
int dx.  // X方向,几阶导数
int dy // Y方向,几阶导数. 
int ksize // SOBEL算子kernel大小,必须是1、3、5、7、
double scale  = 1
double delta = 0
int borderType = BORDER_DEFAULT
)

OpenCV学习 day9 自定义线性滤波 图像边缘处理 边缘算子

 

 Scharr:

cv::Scharr (
InputArray Src // 输入图像
OutputArray dst// 输出图像,大小与输入图像一致
int depth // 输出图像深度. 
int dx.  // X方向,几阶导数
int dy // Y方向,几阶导数. 
double scale  = 1
double delta = 0
int borderType = BORDER_DEFAULT
)

代码演示:

思路:

高斯平滑

转灰度

求X、Y方向梯度

梯度图融合

int sobel_boder(Mat src) {
    Mat blur_src, gray_src, dst;
    Mat xgrad, ygrad;
    GaussianBlur(src, blur_src, Size(3, 3), 0, 0);  //高斯模糊
    cvtColor(blur_src, gray_src, COLOR_BGR2GRAY);  //转灰度
    
    Sobel(gray_src, xgrad, CV_16S, 1, 0, 3); //X方向求梯度
    Sobel(gray_src, ygrad, CV_16S, 0, 1, 3); //Y方向求梯度
    //Scharr(gray_src, xgrad, CV_16S, 1, 0, 3); //Y方向求梯度
    //Scharr(gray_src, ygrad, CV_16S, 0, 1, 3); //Y方向求梯度

    convertScaleAbs(xgrad, xgrad);  //计算图像的像素绝对值,输出到图像B
    convertScaleAbs(ygrad, ygrad);
    
    imshow("x grad", xgrad);
    imshow("y grad", ygrad);

    addWeighted(xgrad, 0.5, ygrad, 0.5,0,dst);  // X Y方向梯度融合
    imshow("x y add result", dst);
    
    //标准的Sobel最后梯度计算
    Mat xygrad = Mat(xgrad.size(), xgrad.type());
    printf("type: %d\n", xgrad.type());
    for (int row = 0; row < xgrad.rows; row++) {
        for (int col = 0; col < xgrad.cols; col++) {
            int xg = xgrad.at<uchar>(row, col);
            int yg = ygrad.at<uchar>(row, col);
            int xyg = xg + yg;
            xygrad.at<uchar>(row, col) = saturate_cast<uchar>(xyg);
        }
    }
    imshow("final image", xygrad);

    waitKey(0);
    return 0;
}

 

上一篇:Python学习day9面向对象编程2-方法的可变个数的参数和方法的参数传递


下一篇:Java学习笔记Day9