• OpenCV12-图像卷积


    OpenCV12-图像卷积


    图像卷积

    OpenCV中提供了filt2D()函数用于实现图像和卷积模板之间的卷积运算

    void filter2D(
        InputArray src,  // 输入图像
        OutputArray dst, // 输出图像
        int ddepth,      // 输出图像数据类型(深度),当为-1时,根据输入图像类型自动选择。
        InputArray kernel, // 卷积核,CV_32FC1 
        Point anchor = Point(-1,-1), // 核的基准点,默认值代表内核基准点位于kernel的中心位置。
        double delta = 0,  // 偏移值,卷积结果加上偏移值 
        int borderType = BORDER_DEFAULT  // 像素边界外推标志
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    第6个参数是像素边界外推标志,在 图像几何变换 一文中讲解 wrapAffine() 仿射变换时第一次遇到,在这里我们体会到了什么是像素边界外推,就是对图像的边界,使用卷积核处理时,边界外面没有与卷积核对应的元素,这是如果要对边界元素卷积,则需要填充一些值,填充值的方法如下:

    /*
    BORDER_CONSTANT:用特定值填充,如用i填充:iiiiii|abcdefgh|iiiiiii
    BORDER_REPLICATE:两端复制填充,如两端用a和h填充:aaaaaa|abcdefgh|hhhhhhh
    BORDER_REFLECT:倒序填充
    BORDER_WRAP:正序填充
    BORDER_REFLECT_101:不包含边界值的倒序填充
    BORDER_TRANSPARENT:随即填充
    BORDER_REFLECT101、BORDER_DEFAULT:同BORDER_REFLECT_101
    BORDER_ISOLATED:不关心感兴趣区域之外的部分
    */
    enum BorderTypes {
        BORDER_CONSTANT    = 0, //!< `iiiiii|abcdefgh|iiiiiii`  with some specified `i`
        BORDER_REPLICATE   = 1, //!< `aaaaaa|abcdefgh|hhhhhhh`
        BORDER_REFLECT     = 2, //!< `fedcba|abcdefgh|hgfedcb`
        BORDER_WRAP        = 3, //!< `cdefgh|abcdefgh|abcdefg`
        BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba`
        BORDER_TRANSPARENT = 5, //!< `uvwxyz|abcdefgh|ijklmno`
    
        BORDER_REFLECT101  = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
        BORDER_DEFAULT     = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
        BORDER_ISOLATED    = 16 //!< do not look outside of ROI
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    由于边界外没有任何图像信息,因此可以使用 BORDER_CONSTANT 边界填充0。

    下面的例子中,卷积结果偏移了2。归一化后的矩阵中每个元素的数值都在一定范围内。再利用相同的卷积模板对彩色图像进行卷积,虽然卷积前后图像内容一致,但是图像整体变得模糊一些。

    #include 
    #include 
    
    using namespace cv;
    using namespace std;
    
    int main()
    {
    	cout << "OpenCV Version: " << CV_VERSION << endl;
    	utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);
    
    	//待卷积矩阵
    	uchar points[25] = {
    		1,2,3,4,5,
    		6,7,8,9,10,
    		11,12,13,14,15,
    		16,17,18,19,20,
    		21,22,23,24,25
    	};
    	Mat img(5, 5, CV_8UC1, points);
    	//卷积模板
    	Mat kernel = (Mat_<float>(3, 3) <<
    		1, 2, 1,
    		2, 0, 2,
    		1, 2, 1);
    	Mat kernel_norm = kernel / 12;  //卷积模板归一化
    	//未归一化卷积结果和归一化卷积结果
    	Mat result, result_norm;
    	filter2D(img, result, CV_32F, kernel, Point(-1, -1), 2, BORDER_CONSTANT);
    	filter2D(img, result_norm, CV_32F, kernel_norm, Point(-1, -1), 2, BORDER_CONSTANT);
    	cout << "result:" << endl << result << endl;
    	cout << "result_norm:" << endl << result_norm << endl;
    	//图像卷积
    	Mat lena = imread("lena.png");
    	if (lena.empty())
    	{
    		cout << "请确认图像文件名称是否正确" << endl;
    		return -1;
    	}
    	Mat lena_fillter;
    	filter2D(lena, lena_fillter, -1, kernel_norm, Point(-1, -1), 2, BORDER_CONSTANT);
    	imshow("lena_fillter", lena_fillter);
    	imshow("lena", lena);
    
    	int k = waitKey(0); // Wait for a keystroke in the window
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    输出:

    result:
    [25, 38, 46, 54, 39;
     54, 86, 98, 110, 78;
     94, 146, 158, 170, 118;
     134, 206, 218, 230, 158;
     95, 158, 166, 174, 109]
    result_norm:
    [3.9166665, 5, 5.666667, 6.3333335, 5.0833335;
     6.3333335, 9, 10.000001, 11.000001, 8.333333;
     9.666667, 14, 15, 16, 11.666668;
     13, 19, 20.000002, 21.000002, 15.000001;
     9.750001, 15, 15.666667, 16.333336, 10.916667]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    分布式机器学习:同步并行SGD算法的实现与复杂度分析
    定时任务动态管理-Scheduled
    基于springboot+vue的仓储物流系统
    学习Cesium.js的必须要了解的工具CesiumLab
    Chiitoitsu
    79 C++ STL pair(对组)
    异步复位同步释放在实际项目中的应用
    工程管理系统简介 工程管理系统源码 java工程管理系统 工程管理系统功能设计
    Acwing第 66 场周赛【完结】
    K8S 网络问题导致 ns 相关的服务不能互相访问
  • 原文地址:https://blog.csdn.net/ArthurHai521/article/details/133828491