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. python获取日期加减之后的日期

    python语言中的datetime模块可以利用其中的方法获取不同的日期,比如获取当前日期.明天.昨天.上个月.下个月和明年.下面利用几个实例说明这些日期的获取方法,操作如下:     第一步,利用d ...

  2. Django—models相关操作

    一.在django后台admin管理页面添加自己增加的表结构 通过终端命令:python3 manage.py makemigrations, python3 manage.py migrate 我们 ...

  3. linux相关命令及配置(四)

    Linux第四章课堂笔记一.RPM包管理命令 1.RPM包是本地文件,存在于本地文件中 2.使用RPM命令管理.rpm包 3.挂载光驱 # mount /dev/cdrom /media/ 查看:rp ...

  4. Java注解Retention、Documented、Target的含义

    Retention注解 Retention(保留)注解说明,这种类型的注解会被保留到那个阶段. 有三个值: 1.RetentionPolicy.SOURCE -- 这种类型的Annotations只在 ...

  5. BZOJ_2006_[NOI2010]超级钢琴_贪心+堆+ST表

    BZOJ_2006_[NOI2010]超级钢琴_贪心+堆+ST表 Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐 ...

  6. Python 命令行(CLI)基础库

    在 CLI 下写 UI 应用 前阵子看了一下自己去年写的 Python-视频转字符动画,感觉好糗..所以几乎把整篇文章重写了一遍.并使用 curses 库实现字符动画的播放. 但是感觉,curses ...

  7. ELK入门使用-与springboot集成

    前言 ELK官方的中文文档写的已经挺好了,为啥还要记录本文?因为我发现,我如果不写下来,过几天就忘记了,而再次捡起来必然还要经历资料查找筛选测试的过程.虽然这个过程很有意义,但并不总是有那么多时间去做 ...

  8. Robot Framework 源码解析(1) - java入口点

    一直很好奇Robot Framework 是如何通过关键字驱动进行测试的,好奇它是如何支持那么多库的,好奇它是如何完成截图的.所以就打算研究一下它的源码. 这是官方给出的Robot framework ...

  9. LSTM实现中文文本情感分析

    1. 背景介绍 文本情感分析是在文本分析领域的典型任务,实用价值很高.本模型是第一个上手实现的深度学习模型,目的是对深度学习做一个初步的了解,并入门深度学习在文本分析领域的应用.在进行模型的上手实现之 ...

  10. 使用Kubernetes演示金丝雀发布

    使用Kubernetes演示金丝雀发布 为了更直观的看出金丝雀发布的效果,我们这里使用了Prometheus监控来观察这个过程.不知道怎么使用Prometheus的同学请看使用Prometheus监控 ...