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. 部署项目到tomcat步骤参考如下 2017.7.10

    http://jingyan.baidu.com/article/a501d80c0c65baec630f5ef6.html

  2. 利用post请求发送内容进行爬虫

    利用post请求发送内容进行爬虫 import requests url = 'http://www.iqianyue.com/mypost' header = {} header['Accept-L ...

  3. 苹果通知推送服务(APNS)一些关键特性摘要

    http://ramosli.iteye.com/blog/1940843 前段时间,仔细研究了APNS的文档,把一些关键的地方记录了下来,弄懂这些对于理解APNS的规则,至关重要. 1. If AP ...

  4. selenium获取元素后用click()点击没有作用,用Keys.ENTER就可以成功

    selenium获取元素后用click()点击没有作用,用键盘输入enter(Keys.ENTER)就可以成功 #coding = utf-8 from selenium import webdriv ...

  5. JSON 数据重复 出现$ref

    JSONArray  类型  如果我们往里面add数据的时候 如果数据相同,那么就会被替换成 $ref:   也就是被简化了 因为数据一样所直接 指向上一条数据 循环引用:当一个对象包含另一个对象时, ...

  6. linux系统日志查看

    系统 日志文件( 可以通过cat 或tail 命令来查看) /var/log/message 系统启动后的信息和错误日志,是Red Hat Linux中最常用的日志之一/var/log/secure ...

  7. enumerate取下标

    for index,item in enumerate(product_list): # print(product_list.index(item),item) print(index,item) ...

  8. Javascript保证精度的小数乘法

    众所周知,js的小数乘法很容易丢失精度,这是一件很恶心的事情.所以我写了这个方法,保证计算精度./** * js小数乘法 *@parameter arg1:被乘数(接受小数和整数) *@paramet ...

  9. Postman----request的body中实现数据驱动

    使用场景: 一个接口多次执行,要求body中的某个参数在每次运行时都要填写不同的值,根据不同值的传入,返回不同的结果 参考示例:通过接口测试创建5条待办名称不一样的待办事项.名称格式不作要求 解决方法 ...

  10. 启动链码报rpc error: code = Unimplemented desc = unknown service protos.ChaincodeSupport start error

    参考链接:https://stackoverflow.com/questions/48007519/unimplemented-desc-unknown-service-protos-chaincod ...