在图像处理中,通过当前位置的邻域像素计算新的像素值是很常见的操作。当邻域包含图像的上几行和下几行时,就需要同时扫描图像的若干行,这就是图像的邻域操作了。至于模板操作是实现空间滤波的基础,通常是使用一个模板(一个的矩形)滑过整幅图像产生新的像素。下面介绍通过使用OpenCV2实现Laplace算子锐化图像,来介绍OpenCV2中对邻域和模板的操作。

锐化处理主要的目的是突出灰度的过渡部分,通常由微分来定义和实现锐化算子的各种方法。Laplace算子是最贱的各向同性微分算子,常用的Laplace模板如下:

使用Laplace算子锐化图像时需要注意模板中心的系数,如果中心系数是负的,就需要将原图像减去经过Laplace算子处理后的图像,得到锐化后的结果。如果中心系数是正的,则相反。

锐化图像时不能以In-Place的方式来完成,需要提供一个输出图像。在对图像遍历时使用两个3个指针:一个指向当前行,一个指向当前行的上一行,一个指向当前行的下一行。而且,由于每个像素值的计算都需要它的上下左右四个相邻像素,所以无法对图像的边界进行计算,需要另作处理。具体实现代码如下:

   1:  /*
   2:      0    -1    0
   3:      -1    4    -1
   4:      0    -1    0
   5:  */
   6:  void sharpen(const Mat & image,Mat & result)
   7:  {
   8:      CV_Assert(image.depth() == CV_8U);
   9:   
  10:      result.create(image.size(),image.type());
  11:   
  12:      const int channels = image.channels() ;
  13:      for(int j = 1 ;j < image.rows - 1 ; j ++){
  14:          const uchar * previous = image.ptr<const uchar>(j - 1) ; // 当前行的上一行
  15:          const uchar * current = image.ptr<const uchar>(j) ; //当前行
  16:          const uchar * next = image.ptr<const uchar>(j + 1) ; //当前行的下一行
  17:   
  18:          uchar * output = result.ptr<uchar>(j) ;  // 输出行
  19:          for(int i = channels ; i < channels * (image.cols - 1) ; i ++) {
  20:              * output ++ = saturate_cast<uchar>( 4 * current[i] - previous[i] - next[i] - current[i - channels] - current[ i + channels]) ;
  21:          }
  22:      }
  23:   
  24:      //对图像边界进行处理
  25:      //边界像素设置为0
  26:      result.row(0).setTo(Scalar(0));
  27:      result.row(result.rows-1).setTo(Scalar(0)) ;
  28:      result.col(0).setTo(Scalar(0));
  29:      result.col(result.cols-1).setTo(Scalar(0));
  30:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

这里使用指针遍历整个图像,使用三个指针同时扫描图像的三行,另外使用一个指针指向输出行。在计算输出像素时,使用模板函数saturate_cast<uchar>对计算结果进行调整。这是因为对像素值的计算有可能导致结果超出了像素允许的范围,即小于0或者大于255,当计算结果是浮点数时,该函数会将结果取整至最近的整数。

由于边界的像素没有完整的邻域,无法使用模板计算其值,需要单独处理。这里只是简单的将其值设为0.

测试代码:

   1:      Mat image = imread("d:\\lenna.jpg") ;
   2:      Mat result ;
   3:      sharpen(image,result) ;
   4:      imwrite("d:\\lenna1.jpg",result) ;
   5:      imwrite("d:\\lenna2.jpg",image + result) ;

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

结果如下:

这里需要说明,在OpenCV2中对Mat进行了大量的运算符重载,例如上面,两幅图像相加直接使用image + result即可。另外,如位操作符:&,|,^,~;函数max,min,abs;比较操作符:<,<=,>,>=,比较操作符返回一个8位二进制图像。另外矩阵乘法m1 * m2,矩阵求逆 m1.inv(),矩阵转置m.t(),举证的行列式m.determinate(),向量的模v.norm(),向量叉乘v.corss(v1),向量的点乘v.dot(v1)等。

由于使用模板实现空间滤波在图像处理中非常的常用,在OpenCV中专门定义了一个特殊的函数来完成该处理:

filter2D.

函数原型:

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

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }参数:

src,输入图像

dst 输出图像,和输入图像有相同的大小和通道

ddepth 输出图像的depth,如果为负数,则和输入图像的depth相同

kernel 模板

anchor 进行卷积运算的中心位置,默认的是kernel的中心

delta 可选值,加到输出像素上的值

bordertype 对输出图像边界的处理。

使用filter2D实现Laplace算子

   1:      Mat kern = (Mat_<char> (3,3) << 1,1,1,
   2:                                      1,-8,1,
   3:                                      1,1,1) ;
   4:      filter2D(image,result,image.depth(),kern) ;
这里只需要定义好kernel调用filter2D即可,而且OpenCV对该函数进行了优化,其效率要比上面使用指针实现的要高。

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

OpenCV2邻域和模板操作的更多相关文章

  1. thinkPHP 模板操作

    1.assign赋值 $this->assign('title','模板操作'); $this->assign('bests',$bests);//$bests是二维数组 2.变量的输出 ...

  2. OpenFaaS实战之四:模板操作(template)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  3. C# 后台模块 Word 模板操作

    public static string CreateWord() { //********************************************** //来自博客http://bl ...

  4. Matlab 图像的邻域和块操作

    图像的邻域操作是指输出图像的像素点取值,由输入图像的某个像素点及其邻域内的像素,通常像素点的邻域是一个远小于图像本身尺寸.形状规则的像素块,如2×2,3×3正方形.2×3矩形等,或者近似圆形的多边形. ...

  5. C#中按模板操作Word —— 如何向Word中插入图片

    一.Word对象模型的重叠性分析 本文主要介绍通过书签Bookmark向Word文档中插入图片的方法.在此之前我们先简单讨论下Word对象模型的重叠性.如果你对Word对象模型还不熟悉,请参考本专栏第 ...

  6. jar word 模板操作比较好用的工具

    个人觉得比较好用的java word 模板 http://deepoove.com/poi-tl/

  7. OpenCV2:第十章 视频操作

    一.简介 OpenCV提供了专门操作视频的接口类VideoCapture 二.构造VideoCapture类 VideoCapture::VideoCapture() VideoCapture::Vi ...

  8. OpenCV2:第八章 视频操作

    一.简介 OpenCV提供了专门操作视频的接口类VideoCapture类,可以从文件或摄像设备中读取视频

  9. Django模板操作

    进行加减运算 def index(request): a = request.GET['a'] b = request.GET['b'] c = int(a) + int(b) return Http ...

随机推荐

  1. 游戏编程技巧 - Type Object

    Type Object 使用场景 你在制作一款和LOL类似的游戏,里面有许多英雄,因此你想建立一个英雄基类,然后把各种英雄都继承自该基类,这些英雄类都有生命值和攻击力等属性.每次策划想增加一个英雄,你 ...

  2. java基本数据类型

    基本数据类型概念 java是一种强类型语言,意味着必须为每一个变量声明一种数据类型. java拥有8中基本数据类型,主要包含如下:4中整形类型(long.int.short.byte)表示整形数值:两 ...

  3. SQL Server 2016 CTP2.3 的关键特性

    SQL Server 2016 CTP2.3 的关键特性 数据库方面的增强 Row Level Security已经支持In-memory OLTP 表.用户现在可以对内存优化表实施row-level ...

  4. Android5.1.1 - APK签名校验分析和修改源码绕过签名校验

    Android5.1.1 - APK签名校验分析和修改源码绕过签名校验 作者:寻禹@阿里聚安全 APK签名校验分析 找到PackageParser类,该类在文件“frameworks/base/cor ...

  5. 旺信UWP正式版发布

    下载链接:https://www.microsoft.com/store/apps/9nblggh5lq9x 各位园主好,在旺信Beta版发布后近两个月,我们的新版本1.1.0终于上线了,并且更名为旺 ...

  6. 企业IT管理员IE11升级指南【2】—— Internet Explorer 11 对Adobe Flash的支持

    企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...

  7. this的安身之处

    在JavaScript的大千世界中,this对象就像一个行踪不定.居无定所的浪子一般,它的生活仿佛可以随处而安,而内心却又似有着笃定的坚守,它就是这么有趣! 初学JavaScript时的我们,多多少少 ...

  8. [译]Asp.net MVC 之 Contorllers(二)

    URL路由模块 取代URL重写 路由请求 URL路由模块的内部结构 应用程序路由 URL模式和路由 定义应用程序路由 处理路由 路由处理程序 处理物理文件请求 防止路由定义的URL 属性路由 书接上回 ...

  9. MySQL实现嵌套集合模型

    MySQL实现嵌套集合模型 译文主要是介绍如何用MySQL来存储嵌套集合数据.在其中会增加一些自己的理解,也会删除掉一些自认为无用的废话. 这篇文章主要讲的是嵌套集合模型,所以邻接表不是本文的重点,简 ...

  10. c#设计模式-组合模式

    在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象和复合对象 ...