1、什么是掩膜(Mask)
用选定的图像、图形或物体,对被处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。用于覆盖的特定图像或物体称为掩模或模板。光学图像处理中,掩模可以是胶片、滤光片等。数字图像处理中,掩模为二维矩阵数组(一般是由0和1组成的二进制矩阵),有时也用多值图像。
在OpenCV中,掩模操作是相对简单的。大致的意思是,通过一个掩模矩阵,重新计算图像中的每一个像素值。掩模矩阵控制了旧图像当前位置以及周围位置像素对新图像当前位置像素值的影响力度。
用数学术语讲,即我们自定义一个权重表。
2、掩膜的用途
(1)、提取感兴趣区:用预先制作的感兴趣区掩模与待处理图像相乘,得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0;
(2)、屏蔽作用:用掩模对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计;
(3)、结构特征提取:用相似性变量或图像匹配方法检测和提取图像中与掩模相似的结构特征;
(4)、特殊形状图像的制作。
3、模板类指针ptr
模板类指针ptr是矩阵的行指针,用于读取/修改矩阵的行。常用于创建行指针而对矩阵的元素进行访问。
常用形式为:
//模板类型* myPtr = 矩阵对象.ptr<模板类型>(第row行)
type* myPtr = myMat.ptr<type>(row)//myPtr表示该矩阵第row行的行指针
//矩阵对象.ptr<模板类型>(第row行)[第col列]
myMat.ptr<type>(row)[col]//表示第该矩阵第row行第col列的元素数据
//注意:模板类型要与矩阵元素数据类型相匹配。
模板类指针ptr代码示例:
Mat myMatB(3,3,CV_8UC1);//创建3x3矩阵对象
//为矩阵元素数据分配介于0~255之间的随机数
randu(myMatB, Scalar::all(0), Scalar::all(255));
uchar* myCharB = myMatB.ptr<uchar>(1);
cout<<"myMatB contains : "<<endl<<myMatB<<endl<<endl;
//用行指针访问行数组元素
myCharB[2] = 216;
cout<<"Now myMatB contains : "<<endl<<myMatB<<endl<<endl;
for(int i = 0; i < 3; i++)
{
cout<<(int)myCharB[i]<<" ";
}
cout<<endl;
//输出结果:
myMatB contains :
[ 91, 2, 79;
179, 52, 205;
236, 8, 181]
Now myMatB contains :
[ 91, 2, 79;
179, 52, 216;
236, 8, 181]
179 52 216
4、CV_Assert(bool )和saturate_cast<type>(type )
(1)、CV_Assert(bool 表达式)
作用是,如果表达式的值为false,则返回错误信息。与C++中的Assert()函数类似。
(2)、saturate_cast<type>(type )
以saturate_cast<char>(myChar)为例:若myChar值小于0,则函数返回0;若myChar值大于255,则函数返回255;否则函数返回myChar的值。
5、矩阵掩膜操作
(1)、demo中的锐化原理:
I(i, j) = 5*I(i, j) - [I(i-1, j) + I(i+1, j) + I(i, j-1) + I(i, j+1)]
/*即掩膜矩阵为:
[ 0, -1, 0 ;
-1, 5, -1 ;
0, -1, 0 ]
*/
//此掩膜可对图像进行锐化处理
(2)、实现方法一(直接调 filter2D 函数):
void maskOperation(Mat& myMat)
{
Mat myMask = (Mat_<char>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
//掩膜函数
filter2D(myMat, myMat, myMat.depth(), myMask);
}
(3)、实现方法二(用行指针ptr操作像素):
void sharpenOperation(Mat& myMat)
{
CV_Assert(myMat.depth() == CV_8U); // accept only uchar images
const int myChannel = myMat.channels();
Mat Result;
Result.create(myMat.size(),myMat.type());
for(int j = 1 ; j < myMat.rows-1; ++j)
{
const uchar* previous = myMat.ptr<uchar>(j - 1);
const uchar* current = myMat.ptr<uchar>(j );
const uchar* next = myMat.ptr<uchar>(j + 1);
uchar* output = Result.ptr<uchar>(j);
for(int i= myChannel;i < myChannel*(myMat.cols-1); ++i)
{
*output++ = saturate_cast<uchar>(5*current[i]
-current[i-myChannel] - current[i+myChannel] - previous[i] next[i]);
}
}
Result.row(0).setTo(Scalar(0));
Result.row(Result.rows-1).setTo(Scalar(0));
Result.col(0).setTo(Scalar(0));
Result.col(Result.cols-1).setTo(Scalar(0));
myMat = Result;
}