OpenCV-C++ 自定义线性滤波

这一节主要介绍卷积的概念,以及常见的算子,在最后简单介绍自定义卷积核,并利用filter2D这个API执行图像模糊

卷积概念

  • 卷积是图像处理中一个操作,是kernel在图像的每个像素上的操作;
  • kernel本质上一个固定大小的矩阵数组,其中心点称为锚点;

\[H(x,y) = \sum_{i=0}^{M_i-1}\sum_{j=0}^{M_j-1}I(x+i-a_i, y+j-a_j)K(i, j) \]

卷积核也被称为算子;

下面的算子可以获取图像的边缘信息;不同的算子边缘方向信息不同;

自定义卷积模糊

实际上就是自定义卷积核;

完整程序如下:

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(){
    // 读取图像
    Mat src = imread("/home/chen/dataset/lena.jpg");
    if (src.empty()){
        cout << "could not load image." << endl;
        return -1;
    }
    namedWindow("src", WINDOW_AUTOSIZE);
    imshow("src", src); 

    // Robert算子
    Mat kernelRobert_x = (Mat_<int>(2, 2) << 1, 0, 0, -1);
    Mat dstRobert_x;
    filter2D(src, dstRobert_x, -1, kernelRobert_x, Point(-1, -1), 0.0);
    namedWindow("dstRobert_x", WINDOW_AUTOSIZE);
    imshow("dstRobert_x", dstRobert_x);

    Mat kernelRobert_y = (Mat_<int>(2, 2) << 0, 1, -1, 0);
    Mat dstRobert_y;
    filter2D(src, dstRobert_y, -1, kernelRobert_y, Point(-1, -1), 0.0);
    namedWindow("dstRobert_y", WINDOW_AUTOSIZE);
    imshow("dstRobert_y", dstRobert_y);

    // Sobel算子
    Mat kernelSobel_x = (Mat_<int>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
    Mat dstSobel_x;
    filter2D(src, dstSobel_x, -1, kernelSobel_x, Point(-1, -1), 0.0);
    namedWindow("dstSobel_x", WINDOW_AUTOSIZE);
    imshow("dstSobel_x", dstSobel_x);

    Mat kernelSobel_y = (Mat_<int>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
    Mat dstSobel_y;
    filter2D(src, dstSobel_y, -1, kernelSobel_y, Point(-1, -1), 0.0);
    namedWindow("dstSobel_y", WINDOW_AUTOSIZE);
    imshow("dstSobel_y", dstSobel_y);

    // 拉普拉斯算子
    Mat kernelLa = (Mat_<int>(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0);
    Mat dstLa;
    filter2D(src, dstLa, -1, kernelLa, Point(-1, -1), 0.0);
    namedWindow("dstLa", WINDOW_AUTOSIZE);
    imshow("dstLa", dstLa);
    
    // 自定义卷积核
    int c = 0;
    int ksize = 0;
    int index = 0;
    Mat dst;
    namedWindow("dst", WINDOW_AUTOSIZE);
    while(true){
        c = waitKey(500);
        if ((char)c == 27){
            break;
        }
        ksize = 4 + (index % 5)*2 + 1;
        Mat kernel = Mat::ones(Size(ksize, ksize), CV_32F) / (float)(ksize*ksize);
        filter2D(src, dst, -1, kernel, Point(-1, -1), 0.0);
        imshow("dst", dst);

        index++;

    }
    waitKey(0);

    return 0;
}


posted @ 2021-04-13 22:15  chenzhen0530  阅读(240)  评论(0编辑  收藏  举报