1.掩膜(mask)概念

用选定的图像,图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。用于覆盖的特定图像或物体称为掩模或模板。光学图像处理中,掩模可以足胶片,滤光片等。掩模是由0和1组成的一个二进制图像。当在某一功能中应用掩模时,1值区域被处理,被屏蔽的0值区域不被包括在计算中。通过指定的数据值,数据范围,有限或无限值,感兴趣区和注释文件来定义图像掩模,也可以应用上述选项的任意组合作为输入来建立掩模。

2.掩膜的作用

数字图像处理中,掩模为二维矩阵数组,有时也用多值图像数字图像处理中,图像掩模主要用于:

  • 提取感兴趣区,用预先制作的感兴趣区掩模与待处理图像相乘,得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0。
  • 屏蔽作用,用掩模对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计。
  • 结构特征提取,用相似性变量或图像匹配方法检测和提取图像中与掩模相似的结构特征。
  • 特殊形状图像的制作
  • 掩膜是一种图像滤镜的模板,实用掩膜经常处理的是遥感图像。当提取道路或者河流,或者房屋时,通过一个N * N的矩阵来对图像进行像素过滤,然后将我们需要的地物或者标志突出显示出来。这个矩阵就是一种掩膜。
  • 在OpenCV的中,掩模操作是相对简单的。大致的意思是,通过一个掩模矩阵,重新计算图像中的每一个像素值。掩模矩阵控制了旧图像当前位置以及周围位置像素对新图像当前位置像素值的影响力度。用数学术语讲,即我们自定义一个权重表

3.通过掩膜操作实现图像对比图的改变

矩阵的掩膜操作十分简单,根据掩膜来重新计算每个像素的像素值,掩膜(mask)也被称为内核。

通过掩膜操作实现图像对比度提高,公式如下

Mat kern = (Mat_<char>(,) <<  , -,  ,
-, , -,
, -, );

红色是中心像素,从上到下,从左到右对每个像素做同样的处理操作,得到最终结果就是对比度提高之后的输出图像垫对象。

4.像素范围处理saturate_cast <typename _Tp>()

  • saturate_cast <UCHAR>( - 100),返回0
  • saturate_cast <UCHAR>(288),返回255
  • saturate_cast <UCHAR>(100),返回100

这个函数的功能是确保RGB值范围在0〜255之间。

5.自定义使用掩膜操作实现图像对比度的提高

(1)获取对象像素指针

------CV_Assert(myImage.depth())

------Mat.ptr<uchar>(int i=0)获取像素矩阵的指针,索引i表示第几行,从0行开始计数

------获得当前行指针const uchar * current= myImage.ptr<uchar>(row);

------获取当前像素点P(row,col)的像素值p(row,col)=current[col]

上源代码:

using namespace std;
using namespace cv; int main(int argc, char **argv)
{
Mat src = imread("E:\\vsprom\\learn02\\nv1.jpg");
if (src.empty())
{
cout << "can not load imagefile...." << endl;
return -;
}
namedWindow("in image win", CV_WINDOW_AUTOSIZE);
imshow("in image win", src); Mat dst;
dst = Mat::zeros(src.size(), src.type());//用原图像的尺寸和类型初始化目标图像并将所有像素值清零
int cols = src.cols * src.channels();//图像矩阵的宽度(列数)=原图像列数*图像的通道数,因为掩膜矩阵要在图像矩阵内,所以计算时要给列和行减1
int rows = src.rows;//图像的高度(行数)
int offsetx = src.channels();//掩膜计算偏移量等于图像通道数
for (int row = ; row < (rows - ); row++)//从第二行开始到倒数第二行结束
{
const uchar* previous = src.ptr<uchar>(row - );//上一行
const uchar* current = src.ptr<uchar>(row);//获取row行的像素指针
const uchar* next = src.ptr<uchar>(row + );//下一行
uchar* outcurrent = dst.ptr<uchar>(row);//输出图像的当前行像素指针
for (int col = offsetx; col < (cols - offsetx); col++)//从第二列(按通道偏移计算)到倒数第二列
{
outcurrent[col] = saturate_cast<uchar>( * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]));//分别对应中间,左右,右边,上面,下面;使用掩膜修改输出图像每一点的像素值,然后saturate_cast限制像素范围为0-255
} }
//将修改完的输出图像在窗口展示出来
namedWindow("out win", CV_WINDOW_AUTOSIZE);
imshow("out win", dst); waitKey();
return ;
}

效果图:第一张为原图,第二张位对比度提高后的图

6.使用opencv 的API实现图像掩膜

1.定义一个3*3的掩膜如下

Mat kernal = (Mat_<char>(, ) << , -, , -, , -, , -, );

2.使用opencv函数进行掩膜操作

    filter2D(src, dst, src.depth(), kernal);

源代码如下:

#include<opencv2\opencv.hpp>
#include<iostream> using namespace std;
using namespace cv; int main(int argc, char **argv)
{
Mat src = imread("E:\\vsprom\\learn02\\nv1.jpg");
if (src.empty())
{
cout << "can not load imagefile...." << endl;
return -;
}
namedWindow("in image win", CV_WINDOW_AUTOSIZE);
imshow("in image win", src); Mat dst;
//dst = Mat::zeros(src.size(), src.type());//用原图像的尺寸和类型初始化目标图像并将所有像素值清零
//int cols = src.cols * src.channels();//图像矩阵的宽度(列数)=原图像列数*图像的通道数,因为掩膜矩阵要在图像矩阵内,所以计算时要给列和行减1
//int rows = src.rows;//图像的高度(行数)
//int offsetx = src.channels();//掩膜计算偏移量等于图像通道数
//for (int row = 1; row < (rows - 1); row++)//从第二行开始到倒数第二行结束
//{
// const uchar* previous = src.ptr<uchar>(row - 1);//上一行
// const uchar* current = src.ptr<uchar>(row);//获取row行的像素指针
// const uchar* next = src.ptr<uchar>(row + 1);//下一行
// uchar* outcurrent = dst.ptr<uchar>(row);//输出图像的当前行像素指针
// for (int col = offsetx; col < (cols - offsetx); col++)//从第二列(按通道偏移计算)到倒数第二列
// {
// outcurrent[col] = saturate_cast<uchar>( 5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]));//分别对应中间,左右,右边,上面,下面;使用掩膜修改输出图像每一点的像素值,然后saturate_cast限制像素范围为0-255
// } //} //创建掩膜 3*3
Mat kernal = (Mat_<char>(, ) << , -, , -, , -, , -, );
//掩膜操作
filter2D(src, dst, src.depth(), kernal); //将修改完的输出图像在窗口展示出来
namedWindow("dst win", CV_WINDOW_AUTOSIZE);
imshow("dst win", dst); waitKey();
return ;
}

处理结果如下图:

跟我一起学opencv 第二课之图像的掩膜操作的更多相关文章

  1. OpenCV 第二课 认识图像的存储结构

    OpenCV 第二课 认识图像的存储结构 Mat Mat 类包含两部分,矩阵头和矩阵体.矩阵头包含矩阵的大小,存储方式和矩阵体存储空间的指针.因此,Mat中矩阵头的大小是固定的,矩阵体大小是不定的. ...

  2. 跟我一起学opencv 第一课之图像加载,修改,保存

    使用opencv前记得引入库和头文件: #include<opencv2\opencv.hpp> 1.加载图像(cv::imread)(OPENCV 支持 JPG,PNG,TIFF等常见格 ...

  3. opencv第二课 进行缩放图片~

    #include<stdio.h> #include<iostream> #include<opencv2\opencv.hpp> using namespace ...

  4. opencv第二课,使用cmake编译OpenCV,并添加opencv_contrib模块

    一.下载安装cmake 想要在Windows平台下生成OpenCV的解决方案,我们需要一个名为cmake的开源软件,可以在camke的官网:http://www.cmake.org/上下载到 或者点击 ...

  5. 从零开始学Kotlin第二课

    字符串模板 fun main(args:Array<String>){ //主函数main方法 println(diaryGenerater("天安门")); } // ...

  6. 小哈学Python第二课:Hello Word

    Python入门 1.Hello World 2.Hello World

  7. OpenCV第二课,嵌入MFC

    单纯显示图片,只需链接 opencv_core2411d.libopencv_highgui2411d.lib 1.首先创建一个MFC的dlg,添加Picture Control控件 void CCO ...

  8. 快学Scala 第二课 (apply, if表达式,循环,函数的带名参数,可变长参数,异常)

    apply方法是Scala中十分常见的方法,你可以把这种用法当做是()操作符的重载形式. 像以上这样伴生对象的apply方法是Scala中构建对象的常用手法,不再需要使用new. if 条件表达式的值 ...

  9. opencv学习笔记(五)----图像的形态学操作

    图像的形态学操作有基本的腐蚀和膨胀操作和其余扩展形态学变换操作(高级操作)-----开运算,闭运算,礼帽(顶帽)操作,黑帽操作...(主要也是为了去噪声,改善图像) 形态学操作都是用于处理二值图像(其 ...

随机推荐

  1. Jenkins 的安装部署

    一.Windows环境中安装Jenkins 原文:http://www.cnblogs.com/yangxia-test/p/4354328.html 在最简单的情况下,Jenkins 只需要两个步骤 ...

  2. 今天读一读七天学会NodeJS

    七天学会NODEJS NodeJS基础 小结 本章介绍了有关NodeJS的基本概念和使用方法,总结起来有以下知识点: NodeJS是一个JS脚本解析器,任何操作系统下安装NodeJS本质上做的事情都是 ...

  3. 3. Java面向对象之泛型-指定多个泛型

    3. Java面向对象之泛型-指定多个泛型 package generic; class MutiGeneric<K, T> { private K key; private T take ...

  4. latex中长公式换行,很好的办法

    今天在编辑公式时,有一个公式很长,写到一行就出去了.当时之前换行都是方程组或者在括号完之后换,都没有问题.但是今天我也换行的是在括号中间断开.这样出现问题,编辑的时候会出错误提醒.上网查了一些论坛,也 ...

  5. 使用wordpress搭建自己的独立博客

    最近想要搭建自己的私人博客, 各种百度,完整的搭建步骤如下! 首先得要有自己的vps或者云主机,我这里是自己的云主机,有自己的域名(我这边目前没有买域名)! 搭建步骤! 1,安装lnmp(linux+ ...

  6. TestNG监听器实现用例运行失败自动截图、重运行功能

    注: 以下内容引自 http://blog.csdn.net/sunnyyou2011/article/details/45894089 (此非原出处,亦为转载,但博主未注明原出处) 使用Testng ...

  7. BZOJ1500 [NOI2005]维修数列-fhq_Treap

    题面见这里 反正是道平衡树,就拿 fhq_Treap 写了写... 这道题思路基本是围绕“用 Treap 维护中序遍历” 和 中序遍历的性质 来进行的操作 所以就可以类比线段树进行一些操作 1. 建树 ...

  8. C# 语言历史版本特性(C# 1.0到C# 8.0汇总)

    历史版本 C#作为微软2000年以后.NET平台开发的当家语言,发展至今具有17年的历史,语言本身具有丰富的特性,微软对其更新支持也十分支持.微软将C#提交给标准组织ECMA,C# 5.0目前是ECM ...

  9. ply python 图片压缩 图片裁剪 旋转

    http://tech.seety.org/python/python_imaging.html

  10. python yield用法 (tornado, coroutine)

    yield关键字用来定义生成器(Generator),其具体功能是可以当return使用,从函数里返回一个值,不同之处是用yield返回之后,可以让函数从上回yield返回的地点继续执行.也就是说,y ...