什么是掩膜(mask)
定义:用选定的图像、图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。用于覆盖的特定图像或物体称为掩模或模板。光学图像处理中,掩模可以足胶片、滤光片等。
数字图像处理中,掩模为二维矩阵数组,有时也用多值图像。数字图像处理中,图像掩模主要用于:
-
提取感兴趣区,用预先制作的感兴趣区掩模与待处理图像相乘,得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0。
-
屏蔽作用,用掩模对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计。
-
结构特征提取,用相似性变量或图像匹配方法检测和提取图像中与掩模相似的结构特征。
-
特殊形状图像的制作。
掩膜是一种图像滤镜的模板,实用掩膜经常处理的是遥感图像。当提取道路或者河流,或者房屋时,通过一个n*n的矩阵来对图像进行像素过滤,然后将我们需要的地物或者标志突出显示出来。这个矩阵就是一种掩膜。
在OpenCV中,掩模操作是相对简单的。大致的意思是,通过一个掩模矩阵,重新计算图像中的每一个像素值。掩模矩阵控制了旧图像当前位置以及周围位置像素对新图像当前位置像素值的影响力度。用数学术语讲,即我们自定义一个权重表
掩膜操作之抠图
#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);r1是设置好的感兴趣区域
Mat img1, img2, img3, img4;
image = imread("lol17.jpg");
mask = Mat::zeros(image.size(), CV_8UC1);//第一步建立与原图一样大小的mask图像,并将所有像素初始化为0,因此全图成了一张全黑色图
mask(r1).setTo(255);//第二步将mask图中的r1区域的所有像素值设置为255,也就是整个r1区域变成了白色。这样就能得到Mask图像了。
img1 = image(r1);
image.copyTo(img2, mask);//注意这句,原图(image)与掩膜(mask)进行与运算后得到了结果图(img2)
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;
}
原始image图
mask图像
原图(image)与掩膜(mask)进行与运算后得到了结果图(img2)。
何为图与掩膜的与运算?
其实就是原图中的每个像素和掩膜中的每个对应像素进行与运算。比如1 & 1 = 1;1 & 0 = 0;
比如一个3 * 3的图像与3 * 3的掩膜进行运算,得到的结果图像就是:
说白了,mask就是位图啊,来选择哪个像素允许拷贝,哪个像素不允许拷贝。如果mask像素的值是非0的,我就拷贝它,否则不拷贝。
因为我们上面得到的mask中,感兴趣的区域是白色的,表明感兴趣区域的像素都是非0,而非感兴趣区域都是黑色,表明那些区域的像素都是0。一旦原图与mask图进行与运算后,得到的结果图只留下原始图感兴趣区域的图像了。也正如下图所示。
image.copyTo(img2, mask);
下面两句代码所做的事情跟上面的差不多,首先将原始图image拷贝一份给img3,然后img3将mask白色区域设置为0(黑色),好比如果mask中像素非0的,我就把我图像对应的那个点的像素值设置为0,否则啥也不做。伪代码是if mask(i,j)>0 then img3(i,j)=0。
image.copyTo(img3);
img3.setTo(0, mask);
如果想要直接抠出目标区域,直接这样写就OK了:
img1 = image(r1);
学到mask(r1)是代表mask图像中的r1部分
提高图像的对比度
矩阵的掩膜操作十分简单,根据掩膜来重新计算每个像素的像素值,掩膜(mask)也被称为 kernel。
通过掩膜操作实现图像对比度提高。
I(i,j) = 5*I(i,j) - [I(i-1,j) + I(i+1,j) + I(i,j-1) + I(i,j+1)]
Mat kern = (Mat_<char>(3,3) << 0, -1, 0,
-1, 5, -1,
0, -1, 0);
红色是中心像素,从上到下,从左到右对每个像素做同样的处理操作,得到最终结果就是对比度提高之后的输出图像Mat对象
方法一是原始的
方法2:函数调用filter2D功能
-
定义掩膜:Mat kernel = (Mat_<char>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
filter2D( src, dst, src.depth(), kernel );其中src与dst是Mat类型变量、src.depth表示位图深度,有32、24、8等