opencv 第二课 矩阵的掩膜操作
第二课 矩阵的掩膜操作
本章主要讲述了 掩膜的基本理论,与对图片的操作:
左边是原始图片,右边是通过掩膜操作生成的图片,对比一下可以看出来差别的。
先让我们了解下基本函数:
Mat.ptr<uchar>(int i=0) 获取像素矩阵的指针,索引i表示第几行,从0开始计行数。
获得当前行指针const uchar* current= myImage.ptr<uchar>(row );
获取当前像素点P(row, col)的像素值 p(row, col) =current[col]
saturate_cast<uchar>(-100),返回 0。
saturate_cast<uchar>(288),返回255
lsaturate_cast<uchar>(100),返回100
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main()
{
Mat src, dsr;
src = imread("D:/image/1.png");
if (!src.data)
{
cout << "could not " << endl;
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
int cols = (src.cols -1 )* src.channels();
int offsetx = src.channels(); //通道数
int rows = src.rows;
dsr = Mat::zeros(src.size(), src.type());
for (int row = 1; row < (rows-1); row++)
{
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 = dsr.ptr<uchar>(row);
for (int col = offsetx; col < cols; col++)
{
output[col] = saturate_cast<uchar>(5 * current[col] - (current[col-offsetx] +
current[col + offsetx] + previous[col] + next[col]
));
}
}
namedWindow("current image demo", CV_WINDOW_AUTOSIZE);
imshow("current image demo", dsr);
waitKey(0);
return 0;
}
这里要解释一下,src.channels() 是获取图片的通道数,以上述图片的话是是RGB图片,src.channels() 获取的值为3,
这里解释一下图片数据的存储,R 指红的值,取值为0~255,同理G ,B 取值也是0~255, 通过RGB三个数据,组成了一个像素,R G B 分别都是 uchar类型,所以是24位,每个是8位。3个字节,也就是3通道。
举个简单的例子,一个图片存的数是 R G B 取值随机的数 0~255
存储的为:
RGB RGB RGB RGB RGB RGB RGB
RGB RGB RGB RGB RGB RGB RGB
RGB RGB RGB RGB RGB RGB RGB
这里为了方便,空格不占数组位,我们要第一个要改变R的值,所以是 row 为 R 的一行 col 为 R 的一列
(row - 1, col), (row +1, col) (row, col - 3), (row, col +3) 这4个值 为R的值
R = 5 * R -(R(row - 1, col) + R(row +1, col) + R(row, col - 3) + R(row, col +3);
后面的G ,B 一次类推,这样就把对应的数据都改写了一遍,且周边数据不变。
函数调用filter2D功能
opencv为了方便把上述的功能封装起来让我们一起来看:
定义掩膜: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等。
上面的代码,需要改变一下,可以得到相同的结果。
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main()
{
Mat src, dsr;
src = imread("D:/image/1.png");
if (!src.data)
{
cout << "could not " << endl;
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
Mat kernel = (Mat_<char>(3,3) << 0, -1, 0,
-1, 5, -1,
0, -1, 0);
filter2D(src, dsr, src.depth(), kernel);
namedWindow("current image demo", CV_WINDOW_AUTOSIZE);
imshow("current image demo", dsr);
waitKey(0);
return 0;
}
是不是非常的简单,哈哈哈,你学会了吗。 喜欢的同学可以关注我的博客,一起学习,加油!