OpenCV2邻域和模板操作
在图像处理中,通过当前位置的邻域像素计算新的像素值是很常见的操作。当邻域包含图像的上几行和下几行时,就需要同时扫描图像的若干行,这就是图像的邻域操作了。至于模板操作是实现空间滤波的基础,通常是使用一个模板(一个的矩形)滑过整幅图像产生新的像素。下面介绍通过使用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邻域和模板操作的更多相关文章
- thinkPHP 模板操作
1.assign赋值 $this->assign('title','模板操作'); $this->assign('bests',$bests);//$bests是二维数组 2.变量的输出 ...
- OpenFaaS实战之四:模板操作(template)
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- C# 后台模块 Word 模板操作
public static string CreateWord() { //********************************************** //来自博客http://bl ...
- Matlab 图像的邻域和块操作
图像的邻域操作是指输出图像的像素点取值,由输入图像的某个像素点及其邻域内的像素,通常像素点的邻域是一个远小于图像本身尺寸.形状规则的像素块,如2×2,3×3正方形.2×3矩形等,或者近似圆形的多边形. ...
- C#中按模板操作Word —— 如何向Word中插入图片
一.Word对象模型的重叠性分析 本文主要介绍通过书签Bookmark向Word文档中插入图片的方法.在此之前我们先简单讨论下Word对象模型的重叠性.如果你对Word对象模型还不熟悉,请参考本专栏第 ...
- jar word 模板操作比较好用的工具
个人觉得比较好用的java word 模板 http://deepoove.com/poi-tl/
- OpenCV2:第十章 视频操作
一.简介 OpenCV提供了专门操作视频的接口类VideoCapture 二.构造VideoCapture类 VideoCapture::VideoCapture() VideoCapture::Vi ...
- OpenCV2:第八章 视频操作
一.简介 OpenCV提供了专门操作视频的接口类VideoCapture类,可以从文件或摄像设备中读取视频
- Django模板操作
进行加减运算 def index(request): a = request.GET['a'] b = request.GET['b'] c = int(a) + int(b) return Http ...
随机推荐
- 配置iis时,浏览项目提示 无法识别的属性“targetFramework”。请注意属性名称区分大小写。
无法识别的属性“targetFramework”.请注意属性名称区分大小写. 行 12: </appSettings>行 13: <system.web>行 14: ...
- PHP基础知识之类
类中的方法访问方式: class A{ function foo() { }} 1.A::foo(); 2.$a = new A(); $a->foo(); 3 ...
- 浅谈Js对象的概念、创建、调用、删除、修改!
一.我们经常困惑,对象究竟是什么,其实这是一种思维,一种意识上的东西,就像我们都说 世界是有物质组成的道理一样,理解了下面的几句话!对象也不是那么抽象! 1.javascript中的所有事 ...
- 业务安全通用解决方案——WAF数据风控
业务安全通用解决方案——WAF数据风控 作者:南浔@阿里云安全 “你们安全不要阻碍业务发展”.“这个安全策略降低用户体验,影响转化率”——这是甲方企业安全部门经常听到合作团队抱怨.但安全从业者加入公司 ...
- .NET支持多平台后的一点拙见
我们目前对.NET的理解大部分可以归纳为:起初它是Java平台(注意是平台,不要跟Java语言搞混淆)的一个克隆品,后来慢慢演变,有了自己的特性.由于Java平台最显著的特点就是“平台独立性”(或者说 ...
- 使用shell/python获取hostname/fqdn释疑
一直以来被Linux的hostname和fqdn(Fully Qualified Domain Name)困惑了好久,今天专门抽时间把它们的使用细节弄清了. 一.设置hostname/fqdn 在Li ...
- 关于printf错用格式化字符串导致double和long double输出错误的小随笔
[题外话] 以前用HUSTOJ给学校搭建Online Judge,所有的评测都是在Linux下进行的.后来为了好往学校服务器上部署,所以大家重新做了一套Online Judge,Web和Judge都是 ...
- 用FlexGrid做开发,轻松处理百万级表格数据
表格数据处理是我们项目开发中经常会遇到的设计需求之一,所需处理的数据量也较大,通常是万级.甚至百万级.此时,完全依赖平台自带的表格工具,往往无法加载如此大的数据量,或者加载得很慢影响程序执行. 那么, ...
- 为什么可以说Java语言是准动态语言?
什么是动态语言? 动态语言,是指程序在运行时可以改变其结构:新的函数可以被引进,已有的函数可以被删除等在结构上的变化.比如JavaScript便是一个典型的动态语言. 除此之外如Ruby.Python ...
- Web前端开发大系概览 (前端开发技术栈)
前言 互联网建立50多年了,网站开发技术日新月异,但web前端始终离不开浏览器,最终还是HTML+JavaScript+CSS这3个核心,围绕这3个核心而开发出来大量技术框架/解决方案. 我从2000 ...