阅读(4130) (12)

OpenCV制作自己的线性滤镜

2017-09-06 11:06:34 更新

目标

在本教程中,您将学习如何:

理论

注意
下面的解释属于Bradski和Kaehler 的“ 学习OpenCV ”一书。

关联

在非常一般的意义上,相关性是图像的每个部分和运算符(内核)之间的操作。

什么是内核?

内核本质上是固定大小的数字系列数组,以及该阵列中的一个锚点,通常位于中心。

OpenCV制作自己的线性滤镜

与内核的关联如何工作?

假设您想知道图像中特定位置的结果值。相关值的计算方式如下:

  1. 将内核锚放置在确定的像素的顶部,其余核心覆盖图像中的相应局部像素。
  2. 将内核系数乘以相应的图像像素值并对结果求和。
  3. 将结果放置在输入图像中锚点的位置。
  4. 通过在整个图像上扫描内核来重复所有像素的过程。

以方程式的形式表达上述程序,我们将具有:

OpenCV制作自己的线性滤镜

幸运的是,OpenCV为您提供了函数cv :: filter2D,因此您不必对所有这些操作进行编码。

Code

  1. 这个程序是做什么的?
  • 加载图像
  • 执行标准化的盒式过滤器。例如,对于的内核,内核将是:size=3,

OpenCV制作自己的线性滤镜

   该程序将使用大小为3,5,7,9和11的内核执行过滤操作。
  • 过滤器输出(每个内核)将在500毫秒内显示

   2. 教程代码如下所示。您也可以从这里下载

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
int main ( int argc, char** argv )
{
  Mat src, dst;
  Mat kernel;
  Point anchor;
  double delta;
  int ddepth;
  int kernel_size;
  const char* window_name = "filter2D Demo";
  String imageName("../data/lena.jpg"); // by default
  if (argc > 1)
  {
    imageName = argv[1];
  }
  src = imread( imageName, IMREAD_COLOR ); // Load an image
  if( src.empty() )
    { return -1; }
  anchor = Point( -1, -1 );
  delta = 0;
  ddepth = -1;
  int ind = 0;
  for(;;)
       {
         char c = (char)waitKey(500);
         if( c == 27 )
           { break; }
         kernel_size = 3 + 2*( ind%5 );
         kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size);
         filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT );
         imshow( window_name, dst );
         ind++;
       }
  return 0;
}
Explanation

说明

  • 加载图像
  String imageName("../data/lena.jpg"); // by default
  if (argc > 1)
  {
    imageName = argv[1];
  }
  src = imread( imageName, IMREAD_COLOR ); // Load an image
  if( src.empty() )
    { return -1; }

  • 初始化线性滤波器的参数

  anchor = Point(-1,-1);
  delta = 0;
  ddepth = -1;
  • 执行无限循环更新内核大小,并将我们的线性滤波器应用于输入图像。我们来详细分析一下:
  • 首先我们定义我们的过滤器将要使用的内核。这里是:
         kernel_size = 3 + 2*( ind%5 );
         kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size);

第一行是将kernel_size更新为在范围内的奇数值:[3,11]。第二行实际上通过将其值设置为1′s 填充矩阵并通过将其除以元素数量进行规范化来构建内核。

  • 设置内核后,我们可以使用函数cv :: filter2D来生成过滤器:

参数表示:
  1. src:源图像
  2. dst:目的地图像
  3. ddepth:深度dst。负值(如−1)表示深度与源相同。
  4. 内核:要通过图像扫描的内核
  5. anchor:锚点相对于其内核的位置。位置点(-1,-1)表示默认的中心。
  6. delta:在关联期间要添加到每个像素的值。默认情况下为0
  7. BORDER_DEFAULT:我们默认设置此值(以下教程中有更多详细信息)
  • 我们的方案将实行一个而循环,每500毫秒我们的过滤器的内核大小的范围进行更新显示。

结果

  1. 在编译上面的代码之后,可以执行它作为参数作为图像的路径。结果应该是一个窗口,显示由归一化过滤器模糊的图像。每个0.5秒的内核大小应该改变,从下面的一系列快照可以看出:

OpenCV制作自己的线性滤镜