您的位置:首页 > 运维架构

OpenCV学习(三):矩阵的掩模的操作

2017-09-22 23:43 302 查看
上一篇介绍了OpenCV中imread,cvtColor,imshow,imwrite的使用,这一篇打算介绍Mat的像素指针,以及掩模操作。

像素指针

对图像操作,基本都是对图像的每个像素操作,在OpenCV中
Mat.ptr<uchar>(int i=0)
可以获取像素的指针,i表示第i行,从第0列开始操作。

这样获取当前行的像素指针
const uchar*  current = myImage.ptr<uchar>( row )
,那么获取像素点P(row, col)的像素值
p(row, col) = current[col]


eg:

Mat inMat = imread("1.png");
uchar u = inMat.ptr<uchar>(0)[0];


上面先载入一张图片到inMat中,然后从inMat中获取第1行第1列的像素并赋给uchar类型的u。

掩模操作

知道了获取图像的像素方法,接下来就可以对图像进行掩模操作,从而提高图片的对比度。



接下来就根据上面图片的公式,来实现图片像素的操作。

Mat inMat = imread("1.png");
if (!inMat.data) {  //判断图像是否读取成功
cout << "图像读取失败" << endl;
return;
}

imshow("原图像", inMat);

int channel = inMat.channels(); //获取图像的通道数
int row = inMat.rows;
int col = inMat.cols;
Mat outMat = Mat(inMat.size(), inMat.type());
for (int i = 1; i < row-1; i++) {
for (int j = channel; j < (col-1)*channel; j++) {
outMat.ptr<uchar>(i)[j] = 5 * inMat.ptr<uchar>(i)[j]-
(inMat.ptr<uchar>(i - 1)[j] +
inMat.ptr<uchar>(i + 1)[j] +
inMat.ptr<uchar>(i)[j-channel] +
inMat.ptr<uchar>(i)[j+channel]);
}
}
imshow("掩模之后的图像", outMat);
}


注意:

< 1 >我们在显示图片的时候,可以不用调用
namedwindow
来创建窗口,可以直接调用
imshow
,来创建并显示窗口图像。

< 2 >像素计算操作时,不能直接从原点(0, 0)到最大点(col, row)来计算计算像素值,否则计算就会超过范围 。

< 3 >在对列进行操作时,别忘了图像的通道值。

运行结果



可以看见掩模之后的图片失真很严重,这是因为我们像素计算之后的值可能为负数或者超过了范围。

此时我们可以用到一个函数saturate_cast< uchar >,当计算的值为负数,或者很大时,可以使我们计算的像素值保证在0~255之间。

更改之后的代码如下

outMat.ptr<uchar>(i)[j] = saturate_cast<uchar>(5 * inMat.ptr<uchar>(i)[j]-
(inMat.ptr<uchar>(i - 1)[j] +
inMat.ptr<uchar>(i + 1)[j] +
inMat.ptr<uchar>(i)[j-channel] +
inMat.ptr<uchar>(i)[j+channel]));


此时运行的结果如下:



可以看见结果好多了

filter2D

对于上面的代码显然是最原始的像素计算方式,此时我们可以使用filter2D达到最简洁的像素计算方式。

< 1 >定义掩模

Mat kernel = (Mat_< char >(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);

< 2 >调用filter2D

filter2D(inMat, outMat, inMat.depth(), kernel);

(1)参数一:输入的图像

(2)参数二:输出的图像

(3)参数三:输出的图像深度,一般和输入图像的深度一样,也可以直接填-1,和前面一样

此时附上完整代码

void test4(){
Mat inMat = imread("1.png");
if (!inMat.data) { //判断图像是否读取成功
cout << "图像读取失败" << endl;
return;
}

imshow("原图像", inMat);

int channel = inMat.channels(); //获取图像的通道数
int row = inMat.rows;
int col = inMat.cols;
Mat outMat = Mat(inMat.size(), inMat.type());
for (int i = 1; i < row-1; i++) {
for (int j = channel; j < (col-1)*channel; j++) {
outMat.ptr<uchar>(i)[j] = saturate_cast<uchar>(5 * inMat.ptr<uchar>(i)[j]- (inMat.ptr<uchar>(i - 1)[j] + inMat.ptr<uchar>(i + 1)[j] + inMat.ptr<uchar>(i)[j-channel] + inMat.ptr<uchar>(i)[j+channel]));
}
}
imshow("掩模之后的图像", outMat);

Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
filter2D(inMat, outMat, inMat.depth(), kernel);
imshow("filter2D变化之后的图像", outMat);
}


运行结果:



可以看见,filter2D和前面的计算结果显示的样子基本一样。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: