掩膜(mask)

掩膜(mask)掩膜 mask 1 掩膜 mask 的定义用选定的图像 图形或物体 对处理的图像 全部或局部 进行遮挡 来控制图像处理的区域或处理过程

大家好,欢迎来到IT知识分享网。

掩膜(mask)

1.掩膜(mask)的定义

用选定的图像,图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。用于覆盖的特定图像或物体称为掩模或模板。光学图像处理中,掩模可以足胶片,滤光片等。

掩模是由0和1组成的一个二进制图像。当在某一功能中应用掩模时,1值区域被处理,被屏蔽的0值区域不被包括在计算中。通过指定的数据值,数据范围,有限或无限值,感兴趣区和注释文件来定义图像掩模,也可以应用上述选项的任意组合作为输入来建立掩模。

 

掩膜是一种图像滤镜的模板,实用掩膜经常处理的是遥感图像。当提取道路或者河流,或者房屋时,通过一个N * N的矩阵来对图像进行像素过滤,然后将我们需要的地物或者标志突出显示出来。这个矩阵就是一种掩膜。

在OpenCV的中,掩模操作是相对简单的。大致的意思是,通过一个掩模矩阵,重新计算图像中的每一个像素值。掩模矩阵控制了旧图像当前位置以及周围位置像素对新图像当前位置像素值的影响力度。用数学术语讲,即我们自定义一个权重表。

 

2.掩膜的用法

 

 

3.掩膜运算的一个小实例

 

 

掩膜(mask)

掩膜操作实现图像对比度调整

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

实例代码:

#include <opencv2\opencv.hpp> #include <iostream> #include <math.h> using namespace std; using namespace cv; int main() {     Mat src, dst;     src = imread("E:\\VS2015Opencv\\vs2015\\project\\picture\\cat.jpg");     if (!src.data)     {         cout << "could not load image..." << endl;         return -1;     }     namedWindow("source image", CV_WINDOW_AUTOSIZE);     imshow("source image", src);     //1).empty() 判断文件读取是否正确     //2).rows 获取图像行数(高度)     //3).cols 获取图像列数(长度)     //4).channels() 获取图像通道数     //5).depth() 获取图像位深度     //【1】记录程序开始点timeStart     double timeStart = (double)getTickCount();//计算时间语句                                               //进行矩阵的掩膜操作     int cols = (src.cols - 1)*src.channels();//837 //获取图像的列数,一定不要忘记图像的通道数     int offsetx = src.channels();//图像的通道数 3     int rows = src.rows;//220     dst = Mat::zeros(src.size(), src.type());//返回指定的大小和类型的数组 创建一个跟src一样大小 类型的图像矩阵     for (int row = 1; row < (rows - 1); row++)     {         //Mat.ptr<uchar>(int i=0) 获取像素矩阵的指针,索引i表示第几行,从0开始计行数。         //获得当前行指针const uchar*  current= myImage.ptr<uchar>(row );         //获取当前像素点P(row, col)的像素值 p(row, col) =current[col]         //Mat.ptr<uchar>(row):获取第row行的图像像素指针。图像的行数从0开始计数         //获取点P(row, col)的像素值:P(row.col) = Mat.ptr<uchar>(row)[col]         const uchar *previous = src.ptr<uchar>(row - 1);//获取上一行指针         const uchar *current = src.ptr<uchar>(row);//获取当前行的指针         const uchar *next = src.ptr<uchar>(row + 1);//获取下一行的指针         uchar *output = dst.ptr<uchar>(row);//目标对象像素         for (int col = offsetx; col < cols; col++)         {             //current[col-offsetx]是当前的像素点的左边那个像素点的位置,因为一个像素点有三个通道             //current[col+offsetx]是当前的像素点的右边那个像素点的位置,因为一个像素点有三个通道             //previous[col]表示当前像素点对应的上一行的那个像素点             //next[col]表示当前像素点对应的下一行的那个像素点             output[col] = 5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]);         }     }     //OpenCV提高了函数filter2D来实现掩膜操作:     //Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);//定义掩膜     //调用filter2D     //filter2D(src, dst, src.depth(), kernel);     double timeconsume = ((double)getTickCount() - timeStart) / getTickFrequency();     cout << "运行上面程序共耗时: " << timeconsume << endl;     //输出 掩膜操作后的图像     namedWindow("contrast image", CV_WINDOW_AUTOSIZE);     imshow("contrast image", dst);     waitKey(0);     return 0; }

  

掩膜(mask)

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

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

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

添加上:

#include <opencv2\opencv.hpp> #include <iostream> #include <math.h> using namespace std; using namespace cv; int main() { Mat src, dst; src = imread("E:\\VS2015Opencv\\vs2015\\project\\picture\\cat.jpg"); if (!src.data) { cout << "could not load image..." << endl; return -1; } namedWindow("source image", CV_WINDOW_AUTOSIZE); imshow("source image", src); //1).empty() 判断文件读取是否正确 //2).rows 获取图像行数(高度) //3).cols 获取图像列数(长度) //4).channels() 获取图像通道数 //5).depth() 获取图像位深度 //【1】记录程序开始点timeStart double timeStart = (double)getTickCount();//计算时间语句 //进行矩阵的掩膜操作 int cols = (src.cols - 1)*src.channels();//837 //获取图像的列数,一定不要忘记图像的通道数 int offsetx = src.channels();//图像的通道数 3 int rows = src.rows;//220 dst = Mat::zeros(src.size(), src.type());//返回指定的大小和类型的数组 创建一个跟src一样大小 类型的图像矩阵 for (int row = 1; row < (rows - 1); row++) { //Mat.ptr<uchar>(int i=0) 获取像素矩阵的指针,索引i表示第几行,从0开始计行数。 //获得当前行指针const uchar* current= myImage.ptr<uchar>(row ); //获取当前像素点P(row, col)的像素值 p(row, col) =current[col] //Mat.ptr<uchar>(row):获取第row行的图像像素指针。图像的行数从0开始计数 //获取点P(row, col)的像素值:P(row.col) = Mat.ptr<uchar>(row)[col] const uchar *previous = src.ptr<uchar>(row - 1);//获取上一行指针 const uchar *current = src.ptr<uchar>(row);//获取当前行的指针 const uchar *next = src.ptr<uchar>(row + 1);//获取下一行的指针 uchar *output = dst.ptr<uchar>(row);//目标对象像素 for (int col = offsetx; col < cols; col++) { //像素范围处理saturate_cast<uchar> output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col])); //current[col-offsetx]是当前的像素点的左边那个像素点的位置,因为一个像素点有三个通道 //current[col+offsetx]是当前的像素点的右边那个像素点的位置,因为一个像素点有三个通道 //previous[col]表示当前像素点对应的上一行的那个像素点 //next[col]表示当前像素点对应的下一行的那个像素点 //output[col] = 5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]); } } double timeconsume = ((double)getTickCount() - timeStart) / getTickFrequency(); cout << "运行上面程序共耗时: " << timeconsume << endl; //输出 掩膜操作后的图像 namedWindow("contrast image", CV_WINDOW_AUTOSIZE); imshow("contrast image", dst); waitKey(0); return 0; }
 

 

掩膜(mask)

 函数调用filter2D功能

#include <opencv2\opencv.hpp> #include <iostream> #include <math.h> using namespace std; using namespace cv; int main() {     Mat src, dst;     src = imread("E:\\VS2015Opencv\\vs2015\\project\\picture\\cat.jpg");     if (!src.data)     {         cout << "could not load image..." << endl;         return -1;     }     namedWindow("source image", CV_WINDOW_AUTOSIZE);     imshow("source image", src);     //1).empty() 判断文件读取是否正确     //2).rows 获取图像行数(高度)     //3).cols 获取图像列数(长度)     //4).channels() 获取图像通道数     //5).depth() 获取图像位深度     //【1】记录程序开始点timeStart     double timeStart = (double)getTickCount();//计算时间语句                                               //进行矩阵的掩膜操作     int cols = (src.cols - 1)*src.channels();//837 //获取图像的列数,一定不要忘记图像的通道数     int offsetx = src.channels();//图像的通道数 3     int rows = src.rows;//220     dst = Mat::zeros(src.size(), src.type());//返回指定的大小和类型的数组 创建一个跟src一样大小 类型的图像矩阵     for (int row = 1; row < (rows - 1); row++)     {         //Mat.ptr<uchar>(int i=0) 获取像素矩阵的指针,索引i表示第几行,从0开始计行数。         //获得当前行指针const uchar*  current= myImage.ptr<uchar>(row );         //获取当前像素点P(row, col)的像素值 p(row, col) =current[col]         //Mat.ptr<uchar>(row):获取第row行的图像像素指针。图像的行数从0开始计数         //获取点P(row, col)的像素值:P(row.col) = Mat.ptr<uchar>(row)[col]         const uchar *previous = src.ptr<uchar>(row - 1);//获取上一行指针         const uchar *current = src.ptr<uchar>(row);//获取当前行的指针         const uchar *next = src.ptr<uchar>(row + 1);//获取下一行的指针         uchar *output = dst.ptr<uchar>(row);//目标对象像素         for (int col = offsetx; col < cols; col++)         {             //像素范围处理saturate_cast<uchar>             output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]));             //current[col-offsetx]是当前的像素点的左边那个像素点的位置,因为一个像素点有三个通道             //current[col+offsetx]是当前的像素点的右边那个像素点的位置,因为一个像素点有三个通道             //previous[col]表示当前像素点对应的上一行的那个像素点             //next[col]表示当前像素点对应的下一行的那个像素点             //output[col] = 5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]);         }     }     //OpenCV提高了函数filter2D来实现掩膜操作:     Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);//定义掩膜     //调用filter2D     filter2D(src, dst, src.depth(), kernel);     double timeconsume = ((double)getTickCount() - timeStart) / getTickFrequency();     cout << "运行上面程序共耗时: " << timeconsume << endl;     //输出 掩膜操作后的图像     namedWindow("contrast image", CV_WINDOW_AUTOSIZE);     imshow("contrast image", dst);     waitKey(0);     return 0; }

 小结

 可以看看下面代码:

#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> using namespace std; using namespace cv; int main() { Mat image, mask; Rect r1(100, 100, 250, 300); Mat img1, img2, img3, img4; image = imread("E:\\VS2015Opencv\\vs2015\\project\\picture\\cat.jpg"); mask = Mat::zeros(image.size(), CV_8UC1); mask(r1).setTo(255); img1 = image(r1); image.copyTo(img2, mask); image.copyTo(img3); img3.setTo(0, mask); imshow("Image sequence", image); imshow("img1", img1); imshow("img2", img2); imshow("img3", img3); imshow("mask", mask); waitKey(); return 0; }

注意程序中的这两句关于Mask的操作。

 mask = Mat::zeros(image.size(), CV_8UC1); mask(r1).setTo(255); //r1是已经设置好的兴趣区域 

解释一下上面两句的操作。

  • 第一步建立与原图一样大小的mask图像,并将所有像素初始化为0,因此全图成了一张全黑色图。
  • 第二步将mask图中的r1区域的所有像素值设置为255,也就是整个r1区域变成了白色。

这样就能得到Mask图像了。

掩膜(mask)

image.copyTo(img2, mask);

 这句是原始图image拷贝到目的图img2上。

其实拷贝的动作完整版本是这样的:

原图(image)与掩膜(mask)进行与运算后得到了结果图(img2)。

说白了,mask就是位图啊,来选择哪个像素允许拷贝,哪个像素不允许拷贝。如果mask像素的值是非0的,我就拷贝它,否则不拷贝。

因为我们上面得到的mask中,感兴趣的区域是白色的,表明感兴趣区域的像素都是非0,而非感兴趣区域都是黑色,表明那些区域的像素都是0。一旦原图与mask图进行与运算后,得到的结果图只留下原始图感兴趣区域的图像了。也正如下图所示。

掩膜(mask)

如果想要直接抠出目标区域,直接这样写就OK了:

img1 = image(r1);

掩膜(mask)

上面两句代码所做的事情是首先将原始图image拷贝一份给img3,然后img3将mask白色区域设置为0(黑色),好比如果mask中像素非0的,我就把我图像对应的那个点的像素值设置为0,否则啥也不做。伪代码是   if mask(i,j)>0 then img3(i,j)=0。

也就是说mask为1的位置设置为0,如下图

掩膜(mask)

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/116607.html

(0)
上一篇 2025-11-27 18:20
下一篇 2025-11-27 18:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信