博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
opencv学习笔记14(自定义线性滤波)
阅读量:3958 次
发布时间:2019-05-24

本文共 2865 字,大约阅读时间需要 9 分钟。

自定义线性滤波

卷积概念

  • 卷积是图像处理中一个操作,是kernel在图像的每个像素上的操作。
  • Kernel本质上一个固定大小的矩阵数组,其中心点称为锚点(anchor point)
    在这里插入图片描述

卷积操作

  • 把kernel放到像素数组之上,求锚点周围覆盖的像素乘积之和(包括锚点),用来替换锚点覆盖下像素点值称为卷积处理。数学表达如下:
    在这里插入图片描述
    在这里插入图片描述
    Sum = 8x1+6x1+6x1+2x1+8x1+6x1+2x1+2x1+8x1
    New pixel = sum / (m*n)
    在这里插入图片描述

filter2D()函数

参考链接:https://blog.csdn.net/keith_bb/article/details/53103026

此函数利用内核实现对图像的卷积运算

CV_EXPORTS_W void filter2D( InputArray src, OutputArray dst, int ddepth,                            InputArray kernel, Point anchor=Point(-1,-1),                            double delta=0, int borderType=BORDER_DEFAULT );

参数解释:

  • InputArray src: 输入图像
  • OutputArray dst: 输出图像,和输入图像具有相同的尺寸和通道数量
  • int ddepth: 目标图像深度,如果没写将生成与原图像深度相同的图像。当depth输入值为-1时,目标图像和原图像深度保持一致。
  • InputArray kernel: 卷积核(或者是相关核),一个单通道浮点型矩阵。如果想在图像不同的通道使用不同的kernel,可以先使用split()函数将图像通道事先分开。
  • Point anchor: 内核的基准点(anchor),其默认值为(-1,-1)说明位于kernel的中心位置。基准点即kernel中与进行处理的像素点重合的点。
  • double delta: 在储存目标图像前可选的添加到像素的值,默认值为0
  • int borderType: 像素向外逼近的方法,默认值是BORDER_DEFAULT,即对全部边界进行计算。

常见算子

  • Robert算子(左侧x方向,右侧y方向)
    在这里插入图片描述
  • Sobel算子(左侧x方向,右侧y方向)
    在这里插入图片描述
  • 拉普拉斯算子(当中间值为5时是锐化算子)
    在这里插入图片描述

自定义卷积模糊

  • filter2D方法filter2D(
    Mat src, //输入图像
    Mat dst, // 模糊图像
    int depth, // 图像深度32/8
    Mat kernel, // 卷积核/模板
    Point anchor, // 锚点位置
    double delta // 计算出来的像素+delta
    )
    其中 kernel是可以自定义的卷积核
    在这里插入图片描述

结果演示

Robert 算子结果

在这里插入图片描述
在这里插入图片描述
sobel 算子结果
在这里插入图片描述
在这里插入图片描述
拉普拉斯算子结果
在这里插入图片描述
自定义模糊结果(卷积核大小为5*5时)
在这里插入图片描述

代码实现

#include
#include
using namespace cv;using namespace std;int main(){
Mat src = imread("G:/OpenCV/opencv笔记所用图片/1.jpg"); if (src.empty()) {
cout << "could not load image..." << endl; getchar(); return -1; } Mat dst; // robert X 方向 Mat kernel_x = (Mat_
(2, 2) << 1, 0, 0, -1); //定义robert的x方向的算子为卷积核 filter2D(src, dst, -1, kernel_x, Point(-1, -1), 0.0); //使用filter2D来对图像进行卷积操作(使用的卷积核已定义) imshow("robert X",dst); // robert y 方向 Mat kernel_y = (Mat_
(2, 2) << 0, 1, -1, 0); //定义robert的y方向的算子为卷积核 filter2D(src, dst, -1, kernel_y, Point(-1, -1), 0.0); imshow("robert y", dst); //sobel的算子比Robert要差异大一些 // Sobel X 方向 Mat Skernel_x = (Mat_
(3, 3) << -1, 0, 1, -2,0,2,-1,0,1); //定义sobel的x方向的算子为卷积核 filter2D(src, dst, -1, Skernel_x, Point(-1, -1), 0.0); imshow("Sobel x", dst); // Sobel Y 方向 Mat yimg; Mat Skernel_y = (Mat_
(3, 3) << -1, -2, -1, 0,0,0, 1,2,1); //定义sobel的y方向的算子为卷积核 filter2D(src, yimg, -1, Skernel_y, Point(-1, -1), 0.0); imshow("Sobel y", yimg); // 拉普拉斯算子(边缘检测算子,得到的是主要的轮廓,当中间的值是5时是锐化算子) Mat Lkernel = (Mat_
(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0); filter2D(src, dst, -1, Lkernel, Point(-1, -1), 0.0); imshow("拉普拉斯", dst); //自定义卷积模糊 int c = 0; int index = 0; int ksize = 0; //使用循环是其模糊程度自动加深 while (true) { c = waitKey(600); if ((char)c == 27) { // ESC break; } ksize = 5 + (index % 8) * 2; Mat kernel = Mat::ones(Size(ksize, ksize), CV_32F) / (float)(ksize * ksize); //定义一个大小变化的卷积核 filter2D(src, dst, -1, kernel, Point(-1, -1)); index++; //进行模糊自增 imshow("卷积模糊", dst); } waitKey(0); return 0;}
你可能感兴趣的文章
杭电ACM——2073,无限的路(思维)
查看>>
杭电ACM——2069,Coin Change(DP)
查看>>
杭电ACM——2074,叠筐
查看>>
北大ACM——3616,Milking Time(DP)
查看>>
杭电ACM——2076,夹角有多大
查看>>
牛客练习赛43——B Tachibana Kanade Loves Probability(暴力,思维)
查看>>
牛客第十七届上海大学程序设计春季联赛——E CSL 的魔法(贪心)
查看>>
杭电ACM——1028,Ignatius and the Princess III(母函数)
查看>>
杭电ACM——1171,Big Event in HDU(母函数)
查看>>
杭电ACM——6491,时间间隔(思维)
查看>>
杭电AC——1085,Holding Bin-Laden Captive!(母函数)
查看>>
杭电ACM——2110,Crisis of HDU(母函数)
查看>>
杭电AM——2152,Fruit(母函数)
查看>>
杭电ACM——2566,统计硬币(DP)
查看>>
堆栈(数据结构)
查看>>
队列(数据结构)
查看>>
杭电ACM——1251,统计难题(Trie树)
查看>>
牛客网哈尔滨工程大学第十四届程序设计竞赛(同步赛)—— 小蚂蚁过马路(思维)
查看>>
牛客网哈尔滨工程大学第十四届程序设计竞赛(同步赛)—— 苹果手链(水题)
查看>>
杭电ACM——6518,Clumsy Keke(暴力+思维)
查看>>